summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMohan T <mohant@nvidia.com>2012-04-26 10:53:57 +0530
committerSimone Willett <swillett@nvidia.com>2012-04-30 15:03:13 -0700
commitb5c77922776bc0d3cd5cb31c0794406638841013 (patch)
tree6634863d51d8039cd4fbcea57d20b171bd7c0fdc /drivers
parent52643b967355478d895cfe37fe68de7d356f1b8f (diff)
net: wireless: sd8797: Marvell sd8797 Wi-Fi driver
Initial commit for Marvell sd8797 Wi-Fi driver Package Ver: T3T-14.69.11.p111-M2614303_A0B0-MGPL Bug 954218 Change-Id: I76fcadb5cda054d1e489c4cff77a3c461bdac742 Signed-off-by: Mohan T <mohant@nvidia.com> Reviewed-on: http://git-master/r/97305 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/sd8797/Makefile474
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan.h35
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11d.c1514
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11h.c3180
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11h.h158
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11n.c1937
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11n.h420
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c508
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.h37
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c1135
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.h102
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_cfp.c1148
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c2927
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_decl.h883
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_fw.h4630
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_ieee.h1318
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_init.c1038
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_init.h88
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_ioctl.h2918
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_join.c1853
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_join.h40
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_main.h2693
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_meas.c464
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_meas.h54
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_misc.c2153
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_module.c47
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_scan.c4155
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_sdio.c1661
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_sdio.h307
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_shim.c939
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c1888
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c1640
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_sta_event.c595
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c5257
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c287
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c276
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_txrx.c374
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_uap.h104
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c3021
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c1393
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c556
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_util.h526
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_wmm.c2534
-rw-r--r--drivers/net/wireless/sd8797/mlan/mlan_wmm.h182
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c1263
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h195
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_debug.c674
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c1143
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h69
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_ioctl.c4307
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_main.c3773
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_main.h1510
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_priv.c6596
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_priv.h715
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_proc.c631
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_sdio.h140
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c728
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_shim.c1458
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_shim.h95
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c2476
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.h41
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_uap.c2692
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_uap.h410
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c1762
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.h30
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_uap_priv.c175
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_uap_priv.h194
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_uap_wext.c1766
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_wext.c3048
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_wext.h116
70 files changed, 93456 insertions, 0 deletions
diff --git a/drivers/net/wireless/sd8797/Makefile b/drivers/net/wireless/sd8797/Makefile
new file mode 100644
index 000000000000..52e3a3df3988
--- /dev/null
+++ b/drivers/net/wireless/sd8797/Makefile
@@ -0,0 +1,474 @@
+# File: Makefile
+#
+# Copyright (C) 2008-2012, Marvell International Ltd.
+#
+# This software file (the "File") is distributed by Marvell International
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991
+# (the "License"). You 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)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: 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
+
+# Enable WEXT for STA
+CONFIG_STA_WEXT=y
+
+# Enable WEXT for uAP
+CONFIG_UAP_WEXT=y
+
+# 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
+
+# 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
+
+# Manufacturing firmware support
+CONFIG_MFG_CMD_SUPPORT=y
+
+# Big-endian platform
+CONFIG_BIG_ENDIAN=n
+
+# 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
+
+# Use static link for app build
+export CONFIG_STATIC_LINK=y
+
+#############################################################################
+# Select Platform Tools
+#############################################################################
+
+MODEXT = ko
+EXTRA_CFLAGS += -I$(M)/mlan
+EXTRA_CFLAGS += -DLINUX
+
+# KERNELDIR point to the installed kernel directory.
+# KERNELDIR can be set on the command line,
+# make KERNELDIR=/usr/src/arm/<arch-bsp-path>
+# Alternatively KERNELDIR can be set in the environment.
+# Default value for KERNELDIR is set below.
+KERNELDIR ?= /usr/src/arm/linux-2.6.39-T3T
+
+# CROSS_COMPILE specify the prefix used for all executables used
+# during compilation. Only gcc and related bin-utils executables
+# CROSS_COMPILE can be set on the command line
+# make CROSS_COMPILE=</usr/local/arm/4.1.1/bin/>arm-linux-
+# Alternatively CROSS_COMPILE can be set in the environment.
+# Default value for CROSS_COMPILE is set below.
+CROSS_COMPILE ?= /usr/local/arm-eabi-4.4.3/bin/arm-eabi-
+
+# INSTALLDIR specify the path to install the kernel module after
+# succesful compilation.
+# INSTALLDIR can be set on the command line
+# make INSTALLDIR=/tftpboot/<rootfs>
+# Alternatively INSTALLDIR can be set in the environment.
+# Default value for INSTALL is set below.
+INSTALLDIR ?= /tftpboot/pxa9xx/root
+
+# ARCH specifies the architecture of the target processor, this kernel
+# module will run.
+# ARCH can be set on the command line
+# make ARCH=<arm/i386>
+# Alternatively ARCH can be set in the environment
+# Default values of ARCH for specific platform are set below.
+ARCH ?= arm
+
+LD += -S
+
+BINDIR = ../bin_sd8797
+APPDIR= $(shell if test -d "mapp"; then echo mapp; fi)
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+
+ EXTRA_CFLAGS += -I$(KERNELDIR)/include
+
+ EXTRA_CFLAGS += -DFPNUM='"69"'
+
+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_PROC_DEBUG),y)
+ EXTRA_CFLAGS += -DPROC_DEBUG
+ export CONFIG_PROC_DEBUG
+endif
+
+ifeq ($(CONFIG_64BIT), y)
+ EXTRA_CFLAGS += -DMLAN_64BIT
+endif
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+ EXTRA_CFLAGS += -DSTA_SUPPORT
+ifeq ($(CONFIG_REASSOCIATION),y)
+ EXTRA_CFLAGS += -DREASSOCIATION
+endif
+ifeq ($(CONFIG_STA_WEXT),y)
+ EXTRA_CFLAGS += -DSTA_WEXT
+endif
+ifeq ($(CONFIG_STA_CFG80211),y)
+ EXTRA_CFLAGS += -DSTA_CFG80211
+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)
+ EXTRA_CFLAGS += -DUAP_SUPPORT
+ifeq ($(CONFIG_UAP_WEXT),y)
+ EXTRA_CFLAGS += -DUAP_WEXT
+endif
+ifeq ($(CONFIG_UAP_CFG80211),y)
+ EXTRA_CFLAGS += -DUAP_CFG80211
+endif
+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)
+ EXTRA_CFLAGS += -DWIFI_DIRECT_SUPPORT
+endif
+ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y)
+ EXTRA_CFLAGS += -DWIFI_DISPLAY_SUPPORT
+endif
+
+ifeq ($(CONFIG_MFG_CMD_SUPPORT),y)
+ EXTRA_CFLAGS += -DMFG_CMD_SUPPORT
+endif
+
+ifeq ($(CONFIG_BIG_ENDIAN),y)
+ EXTRA_CFLAGS += -DBIG_ENDIAN_SUPPORT
+endif
+
+ifeq ($(CONFIG_SDIO_MULTI_PORT_TX_AGGR),y)
+ EXTRA_CFLAGS += -DSDIO_MULTI_PORT_TX_AGGR
+endif
+
+ifeq ($(CONFIG_SDIO_MULTI_PORT_RX_AGGR),y)
+ EXTRA_CFLAGS += -DSDIO_MULTI_PORT_RX_AGGR
+endif
+
+
+ifeq ($(CONFIG_SDIO_SUSPEND_RESUME),y)
+ EXTRA_CFLAGS += -DSDIO_SUSPEND_RESUME
+endif
+
+ifeq ($(CONFIG_DFS_TESTING_SUPPORT),y)
+ EXTRA_CFLAGS += -DDFS_TESTING_SUPPORT
+endif
+
+#############################################################################
+# Make Targets
+#############################################################################
+
+ifneq ($(KERNELRELEASE),)
+
+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_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
+ifeq ($(CONFIG_STA_WEXT),y)
+MOALOBJS += mlinux/moal_wext.o
+endif
+endif
+ifeq ($(CONFIG_STA_CFG80211),y)
+MOALOBJS += mlinux/moal_cfg80211.o
+MOALOBJS += mlinux/moal_sta_cfg80211.o
+endif
+ifeq ($(CONFIG_UAP_CFG80211),y)
+MOALOBJS += mlinux/moal_cfg80211.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-m := mlan.o
+mlan-objs := $(MLANOBJS)
+MOALOBJS += mlinux/moal_sdio_mmc.o
+obj-m += sd8xxx.o
+sd8xxx-objs := $(MOALOBJS)
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+
+default:
+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
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
+
+endif
+
+###############################################################
+
+export CC LD EXTRA_CFLAGS 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
+
+ cp -f mlan.$(MODEXT) $(BINDIR)/mlan$(DBG).$(MODEXT)
+ cp -f sd8xxx.$(MODEXT) $(BINDIR)/sd8797$(DBG).$(MODEXT)
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+ cp -f README $(BINDIR)
+ cp -f README_RBC $(BINDIR)
+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 {} \;
+ -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 sd8xxx.$(MODEXT) $(INSTALLDIR)/sd8797$(DBG).$(MODEXT)
+ echo "sd8797 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 {} \;
+ -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/drivers/net/wireless/sd8797/mlan/mlan.h b/drivers/net/wireless/sd8797/mlan/mlan.h
new file mode 100644
index 000000000000..a341e1547099
--- /dev/null
+++ b/drivers/net/wireless/sd8797/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-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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/drivers/net/wireless/sd8797/mlan/mlan_11d.c b/drivers/net/wireless/sd8797/mlan/mlan_11d.c
new file mode 100644
index 000000000000..809de4cc9ede
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_11d.c
@@ -0,0 +1,1514 @@
+/** @file mlan_11d.c
+ *
+ * @brief This file contains functions for 802.11D.
+ *
+ * Copyright (C) 2008-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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
+********************************************************/
+
+/** 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 ", 0xFF}, /* Japan special */
+};
+
+#ifdef STA_SUPPORT
+/** Default Tx power */
+#define TX_PWR_DEFAULT 10
+
+/** Universal region code */
+#define UNIVERSAL_REGION_CODE 0xff
+
+/* 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 */
+};
+#endif /* STA_SUPPORT */
+
+/********************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @brief This function converts region string to integer code
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param region Region string
+ * @param code [output] Region code
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11d_region_2_code(pmlan_adapter pmadapter, t_u8 * region, OUT t_u8 * code)
+{
+ t_u8 i;
+ t_u8 size = sizeof(region_code_mapping) / sizeof(region_code_mapping_t);
+
+ ENTER();
+
+ /* Look for code in mapping table */
+ for (i = 0; i < size; i++) {
+ if (!memcmp(pmadapter, region_code_mapping[i].region,
+ region, COUNTRY_CODE_LEN)) {
+ *code = region_code_mapping[i].code;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+ }
+ }
+
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+}
+
+#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;
+ t_u8 size = sizeof(region_code_mapping) / sizeof(region_code_mapping_t);
+
+ ENTER();
+
+ /* Look for code in mapping table */
+ for (i = 0; i < size; 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 */
+ if ((pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA))
+ && 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)) {
+ cfp = channel_freq_power_UN_BG;
+ cfp_no = sizeof(channel_freq_power_UN_BG) / sizeof(chan_freq_power_t);
+ } else if (band & (BAND_A | BAND_AN)) {
+ cfp = channel_freq_power_UN_AJ;
+ cfp_no = sizeof(channel_freq_power_UN_AJ) / sizeof(chan_freq_power_t);
+ } 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 < 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;
+}
+
+#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 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)) {
+ cf = channel_freq_power_UN_AJ;
+ cnt = sizeof(channel_freq_power_UN_AJ) / sizeof(chan_freq_power_t);
+ } else {
+ cf = channel_freq_power_UN_BG;
+ cnt = sizeof(channel_freq_power_UN_BG) / sizeof(chan_freq_power_t);
+ }
+
+ /* Locate channel and return corresponding frequency */
+ for (i = 0; i < cnt; i++) {
+ if (chan == cf[i].channel)
+ freq = cf[i].freq;
+ }
+
+ LEAVE();
+ return freq;
+}
+
+/**
+ * @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 size = sizeof(chan_freq_power_t);
+ 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 =
+ (t_u8) (sizeof(channel_freq_power_UN_BG) / size);
+ 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)) {
+ /* If band A */
+
+ /* Set channel-frequency-power */
+ pmadapter->universal_channel[i].num_cfp =
+ sizeof(channel_freq_power_UN_AJ) / size;
+ 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:
+ 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:
+ 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;
+}
+
+/**
+ * @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 region_code = 0;
+
+ ENTER();
+
+ cfg_11d = (mlan_ds_11d_cfg *) pioctl_req->pbuf;
+ domain_info = &cfg_11d->param.domain_info;
+
+ /* Update region code and table based on country code */
+ if (wlan_11d_region_2_code(pmadapter, domain_info->country_code,
+ &region_code) == MLAN_STATUS_SUCCESS) {
+ pmadapter->region_code = region_code;
+ ret = wlan_set_regiontable(pmpriv, region_code, pmadapter->fw_bands);
+ if (ret != MLAN_STATUS_SUCCESS)
+ goto done;
+ }
+
+ wlan_11d_set_domain_info(pmpriv, domain_info->band,
+ 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;
+
+ done:
+ LEAVE();
+ return ret;
+}
+#endif /* STA_SUPPORT */
+
+#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 region_code = 0;
+
+ ENTER();
+
+ pdomain_tlv = (MrvlIEtypes_DomainParamSet_t *) domain_tlv;
+
+ // update region code & table based on country string
+ if (wlan_11d_region_2_code(pmadapter, pdomain_tlv->country_code,
+ &region_code) == MLAN_STATUS_SUCCESS) {
+ pmadapter->region_code = region_code;
+ ret = wlan_set_regiontable(pmpriv, region_code, pmadapter->fw_bands);
+ }
+
+ 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);
+
+ LEAVE();
+ return ret;
+}
+#endif
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11h.c b/drivers/net/wireless/sd8797/mlan/mlan_11h.c
new file mode 100644
index 000000000000..23970861db1e
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_11h.c
@@ -0,0 +1,3180 @@
+/** @file mlan_11h.c
+ *
+ * @brief This file contains functions for 802.11H.
+ *
+ * Copyright (C) 2008-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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"
+#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 */
+
+/** 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 (500) // 5 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 ((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 0x32: /* France */
+ 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 0x32: /* France */
+ 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 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;
+ break;
+ case 0x50: /* China */
+ 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;
+ }
+ }
+
+ /*
+ * 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;
+
+ ENTER();
+
+ if (pstate_dfs->dfs_check_pending) {
+ 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));
+
+ /* if DFS channel, add BASIC report TLV, and set radar bit */
+ if (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_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 *startPtr = MNULL;
+
+ ENTER();
+
+ /* Null Checks */
+ if ((ppbuffer == MNULL) || (((t_u8 *) (*ppbuffer)) == MNULL)) {
+ LEAVE();
+ return 0;
+ }
+
+ startPtr = (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 - startPtr);
+}
+
+/**
+ * @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 = 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.band_config & BAND_CONFIG_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
+ */
+static 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",
+ __FUNCTION__, 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", __FUNCTION__,
+ 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",
+ __FUNCTION__, 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 Determine if mlan_private list only contains UAP interface(s)
+ *
+ * @param priv_list List of mlan_private pointers
+ * @param priv_list_count Number of mlan_privates in above list
+ *
+ * @return MTRUE or MFALSE
+ */
+static t_bool
+wlan_only_uap_priv_in_list(mlan_private ** priv_list, t_u8 priv_list_count)
+{
+#if defined(STA_SUPPORT) && !defined(UAP_SUPPORT)
+ return MFALSE;
+#else
+ t_u8 uap_count = 0;
+ t_u8 sta_count = 0;
+ t_u8 i;
+
+ ENTER();
+ for (i = 0; i < priv_list_count; i++) {
+ if (GET_BSS_ROLE(priv_list[i]) == MLAN_BSS_ROLE_UAP)
+ uap_count++;
+ else
+ sta_count++;
+ }
+
+ LEAVE();
+ return ((uap_count > 0) && (sta_count == 0)) ? MTRUE : MFALSE;
+#endif
+}
+
+/**
+ * @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;
+
+ 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", __FUNCTION__);
+ 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 = 0; /* simplification */
+
+ pds_misc_cfg->param.cust_ie.len += pcust_chansw_ie->ie_length;
+ DBG_HEXDUMP(MCMD_D, "11h: custom_ie containing CHAN_SW IE",
+ (t_u8 *) pcust_chansw_ie, pds_misc_cfg->param.cust_ie.len);
+
+ /* assign output pointer before returning */
+ *ppioctl_req = pioctl_req;
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef UAP_SUPPORT
+/**
+ * @brief 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, t_u8 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 & UAP_BAND_CONFIG_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).
+ */
+ 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)
+ && (++rand_tries < MAX_RANDOM_CHANNEL_RETRIES));
+ }
+ }
+ }
+ }
+
+ 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", __FUNCTION__);
+ 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", __FUNCTION__);
+
+ 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) {
+ 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) {
+ 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;
+ pstate_rdh->uap_band_cfg = 0;
+ pstate_rdh->max_bcn_dtim_ms = 0;
+ memset(adapter, pstate_rdh->priv_list, 0, sizeof(pstate_rdh->priv_list));
+
+#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;
+
+ 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 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);
+
+ 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
+ *
+ * @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)
+{
+ t_s32 ret;
+ HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
+
+ 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;
+ chan_rpt_req.chan_desc.chanWidth = 0; // 1 for 40Mhz
+ chan_rpt_req.chan_desc.chanNum = channel;
+ chan_rpt_req.millisec_dwell_time =
+ WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION;
+#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", __FUNCTION__);
+ 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 {
+ // 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:
+ PRINTM(MINFO, "11h: Ret ChanRptReq. Set dfs_check_pending and wait"
+ " for EVENT_CHANNEL_REPORT.\n");
+ priv->adapter->state_dfs.dfs_check_pending = MTRUE;
+ 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;
+ ENTER();
+ priv->adapter->state_11h.recvd_chanswann_event = MTRUE;
+
+#ifdef STA_SUPPORT
+ /* do directed deauth. priv flag above will cause different reason code */
+ PRINTM(MINFO, "11h: handle_event_chanswann() - sending deauth\n");
+ ret = wlan_disconnect(priv, MNULL,
+ &priv->curr_bss_params.bss_descriptor.mac_address);
+
+ /* 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);
+#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;
+}
+#endif // DFS_TESTING_SUPPORT
+
+/**
+ * @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 *pChanRptRsp;
+ MrvlIEtypes_Data_t *pTlv;
+ MeasRptBasicMap_t *pMeasRptBasic;
+ t_u8 *pBuffer;
+ t_s32 evtLen;
+ t_u16 tlvLen;
+ t_u32 sec, uSec;
+ wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+
+ ENTER();
+ pChanRptRsp = (HostCmd_DS_CHAN_RPT_RSP *) & pevent->event_buf;
+ DBG_HEXDUMP(MCMD_D, "11h: Event ChanRptReady (HostCmd_DS_CHAN_RPT_RSP)",
+ (t_u8 *) pChanRptRsp, wlan_le32_to_cpu(pevent->event_len));
+
+ if (wlan_le32_to_cpu(pChanRptRsp->cmd_result) == MLAN_CMD_RESULT_SUCCESS) {
+ pBuffer = (t_u8 *) & pChanRptRsp->tlv_buffer;
+ evtLen = wlan_le32_to_cpu(pevent->event_len);
+ evtLen -=
+ sizeof(HostCmd_DS_CHAN_RPT_RSP) - sizeof(pChanRptRsp->tlv_buffer);
+
+ while (evtLen >= sizeof(MrvlIEtypesHeader_t)) {
+ pTlv = (MrvlIEtypes_Data_t *) pBuffer;
+ tlvLen = wlan_le16_to_cpu(pTlv->header.len);
+
+ switch (wlan_le16_to_cpu(pTlv->header.type)) {
+ case TLV_TYPE_CHANRPT_11H_BASIC:
+ pMeasRptBasic = (MeasRptBasicMap_t *) & pTlv->data;
+ if (pMeasRptBasic->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 += (tlvLen + sizeof(pTlv->header));
+ evtLen -= (tlvLen + sizeof(pTlv->header));
+ evtLen = (evtLen > 0) ? evtLen : 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;
+
+ 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)
+{
+ 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);
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Driver handling for RADAR_DETECTED event
+ *
+ * @param pmadapter Pointer to mlan_adapter
+ *
+ * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_11h_radar_detected_handling(mlan_adapter * pmadapter)
+{
+#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;
+ mlan_private *pmpriv = MNULL;
+ t_u32 i;
+ wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
+
+ ENTER();
+
+ switch (pstate_rdh->stage) {
+ case RDH_CHK_INTFS:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s\n",
+ __FUNCTION__, 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", __FUNCTION__,
+ pstate_rdh->priv_list_count);
+ for (i = 0; i < pstate_rdh->priv_list_count; i++)
+ PRINTM(MINFO, "%s(): priv_list[%d] = %p\n",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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;
+ pstate_rdh->uap_band_cfg = 0;
+ 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",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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) {
+ if (wlan_only_uap_priv_in_list(pstate_rdh->priv_list,
+ pstate_rdh->priv_list_count)) {
+#ifdef UAP_SUPPORT
+ /* Assume all UAPs on same channel, use first UAP */
+ pmpriv = pstate_rdh->priv_list[0];
+ pstate_rdh->priv_curr_idx = 0;
+ /* 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
+#endif
+ } else {
+ /* 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 */
+ pmpriv = pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
+ pstate_rdh->curr_channel = pmpriv->uap_state_chan_cb.channel;
+ pstate_rdh->uap_band_cfg = pmpriv->uap_state_chan_cb.band_config;
+ PRINTM(MCMD_D, "%s(): uap_band_cfg=0x%02x\n",
+ __FUNCTION__, pstate_rdh->uap_band_cfg);
+ }
+#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 */
+ i = 0;
+ do {
+#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.
+ band_config);
+ else
+#endif
+ pstate_rdh->new_channel =
+ wlan_11h_get_adhoc_start_channel(pmpriv);
+ } while ((pstate_rdh->new_channel == pstate_rdh->curr_channel) && (++i < MAX_RANDOM_CHANNEL_RETRIES)); /* avoid
+ deadloop
+ */
+ if (i >= MAX_RANDOM_CHANNEL_RETRIES) /* report error */
+ PRINTM(MERROR, "%s(): ERROR - could not choose new_chan"
+ " (!= curr_chan) !!\n", __FUNCTION__);
+
+#ifdef DFS_TESTING_SUPPORT
+ if (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;
+ }
+#endif
+ PRINTM(MCMD_D, "%s(): curr_chan=%d, new_chan=%d\n",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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;
+
+ if (wlan_11h_is_dfs_master(pmpriv)) { /* adhoc creator */
+ 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",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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 preparng CHAN_SW IE.\n",
+ __FUNCTION__);
+ break; // EXIT CASE
+ }
+
+ PRINTM(MMSG,
+ "11h: Radar Detected - adding CHAN_SW IE to interfaces.\n");
+ 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",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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((5 * 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 preparng CHAN_SW IE.\n",
+ __FUNCTION__);
+ 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",
+ __FUNCTION__, 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_STOP_INTFS;
+#ifdef DFS_TESTING_SUPPORT
+ if (pmadapter->dfs_test_params.no_channel_change_on_radar) {
+ PRINTM(MCMD_D, "dfs_testing - no channel change on radar."
+ " Also skip stop/restart interface stages.\n",
+ pmadapter->dfs_test_params.no_channel_change_on_radar);
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_RESTART_TRAFFIC;
+ goto rdh_restart_traffic; // skip several stages
+ }
+#endif
+ // FALL THROUGH TO NEXT STAGE
+
+ case RDH_STOP_INTFS:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n",
+ __FUNCTION__, 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)
+ break; // EXIT CASE
+ // else
+ pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+ pstate_rdh->stage = RDH_SET_NEW_CHANNEL;
+ // FALL THROUGH TO NEXT STAGE
+
+ case RDH_SET_NEW_CHANNEL:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n",
+ __FUNCTION__, 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;
+ pstate_rdh->uap_band_cfg |= UAP_BAND_CONFIG_5GHZ; /* DFS
+ only
+ in
+ 5GHz
+ */
+ 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)
+ 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:
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n",
+ __FUNCTION__, 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);
+ ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+ ret = wlan_11h_check_update_radar_det_state(pmpriv);
+ }
+ 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)
+ 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:
+#ifdef DFS_TESTING_SUPPORT
+ rdh_restart_traffic:
+#endif
+ PRINTM(MCMD_D, "%s(): stage(%d)=%s\n",
+ __FUNCTION__, pstate_rdh->stage,
+ RDH_stage_str[pstate_rdh->stage]);
+
+ /* 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",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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;
+ }
+ 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();
+
+ /* 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].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].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/drivers/net/wireless/sd8797/mlan/mlan_11h.h b/drivers/net/wireless/sd8797/mlan/mlan_11h.h
new file mode 100644
index 000000000000..cfa7fb915b39
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_11h.h
@@ -0,0 +1,158 @@
+/** @file mlan_11h.h
+ *
+ * @brief This header file contains data structures and
+ * function declarations of 802.11h
+ *
+ * Copyright (C) 2008-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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)
+
+/**
+ * 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);
+
+/** 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);
+
+/** 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);
+#endif
+
+/** 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);
+
+/** 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);
+
+#endif /*_MLAN_11H_ */
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n.c b/drivers/net/wireless/sd8797/mlan/mlan_11n.c
new file mode 100644
index 000000000000..d55c2e7e4ab3
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_11n.c
@@ -0,0 +1,1937 @@
+/** @file mlan_11n.c
+ *
+ * @brief This file contains functions for 11n handling.
+ *
+ * Copyright (C) 2008-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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"
+
+/********************************************************
+ 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;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *) pioctl_req->pbuf;
+ cfg->param.tx_buf_size = (t_u32) pmadapter->max_tx_buf_size;
+ pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @brief Set/get htcapinfo configuration
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param pioctl_req A pointer to ioctl request buffer
+ *
+ * @return MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_htusrcfg(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) {
+ pmadapter->usr_dot_11n_dev_cap_bg = cfg->param.htcap_cfg.htcap;
+ PRINTM(MINFO, "Set: UsrDot11nCap for 2.4GHz 0x%x\n",
+ pmadapter->usr_dot_11n_dev_cap_bg);
+ }
+ if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_A) {
+ pmadapter->usr_dot_11n_dev_cap_a = cfg->param.htcap_cfg.htcap;
+ PRINTM(MINFO, "Set: UsrDot11nCap for 5GHz 0x%x\n",
+ pmadapter->usr_dot_11n_dev_cap_a);
+ }
+ if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BOTH) {
+ pmadapter->usr_dot_11n_dev_cap_bg = cfg->param.htcap_cfg.htcap;
+ pmadapter->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 = pmadapter->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 = pmadapter->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;
+
+ ENTER();
+
+ cfg = (mlan_ds_11n_cfg *) pioctl_req->pbuf;
+ if (pioctl_req->action == MLAN_ACT_GET) {
+ cfg->param.stream_cfg = pmadapter->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
+ pmadapter->usr_dev_mcs_support = cfg->param.stream_cfg;
+ break;
+ case HT_STREAM_MODE_1X1:
+ pmadapter->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 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();
+
+ if (!
+ (ptx_tbl =
+ (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ priv->adapter->callbacks.
+ moal_spin_lock,
+ priv->adapter->callbacks.
+ moal_spin_unlock))) {
+ 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;
+ }
+ /* 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->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 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 {
+ if (pmpriv->media_connected == MTRUE) {
+ PRINTM(MERROR, "Can not set aggr priority table in connected"
+ " state\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ 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];
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @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 {
+ if (pmpriv->media_connected == MTRUE) {
+ PRINTM(MERROR, "Can not set aggr priority table in connected"
+ " state\n");
+ pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+
+ 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];
+ }
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @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];
+
+ 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(pmadapter->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(pmadapter->usr_dot_11n_dev_cap_bg)
+ || ISSUPP_CHANWIDTH40(pmadapter->usr_dot_11n_dev_cap_a)
+ )
+ 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();
+
+ if (!
+ (ptx_tbl =
+ (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr, MNULL,
+ MNULL))) {
+ 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();
+
+ if (!
+ (ptx_tbl =
+ (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ priv->adapter->callbacks.
+ moal_spin_lock,
+ priv->adapter->callbacks.
+ moal_spin_unlock))) {
+ 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,
+ MrvlIETypes_HTCap_t * pht_cap, t_u8 bands)
+{
+ mlan_adapter *pmadapter = priv->adapter;
+ t_u32 usr_dot_11n_dev_cap;
+
+ ENTER();
+
+ if (bands & BAND_A)
+ usr_dot_11n_dev_cap = pmadapter->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap = pmadapter->usr_dot_11n_dev_cap_bg;
+
+ if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+ SETHT_SUPPCHANWIDTH(pht_cap->ht_cap.ht_cap_info);
+ else
+ RESETHT_SUPPCHANWIDTH(pht_cap->ht_cap.ht_cap_info);
+
+ if (ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+ SETHT_GREENFIELD(pht_cap->ht_cap.ht_cap_info);
+ else
+ RESETHT_GREENFIELD(pht_cap->ht_cap.ht_cap_info);
+
+ if (ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+ SETHT_SHORTGI20(pht_cap->ht_cap.ht_cap_info);
+ else
+ RESETHT_SHORTGI20(pht_cap->ht_cap.ht_cap_info);
+
+ if (ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+ SETHT_SHORTGI40(pht_cap->ht_cap.ht_cap_info);
+ else
+ RESETHT_SHORTGI40(pht_cap->ht_cap.ht_cap_info);
+
+ if (ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+ SETHT_RXSTBC(pht_cap->ht_cap.ht_cap_info, 1);
+ else
+ RESETHT_RXSTBC(pht_cap->ht_cap.ht_cap_info);
+
+ if (ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+ SETHT_40MHZ_INTOLARANT(pht_cap->ht_cap.ht_cap_info);
+ else
+ RESETHT_40MHZ_INTOLARANT(pht_cap->ht_cap.ht_cap_info);
+
+ /* No user config for LDPC coding capability yet */
+ if (ISSUPP_RXLDPC(pmadapter->hw_dot_11n_dev_cap))
+ SETHT_LDPCCODINGCAP(pht_cap->ht_cap.ht_cap_info);
+ else
+ RESETHT_LDPCCODINGCAP(pht_cap->ht_cap.ht_cap_info);
+
+ /* No user config for TX STBC yet */
+ if (ISSUPP_TXSTBC(pmadapter->hw_dot_11n_dev_cap))
+ SETHT_TXSTBC(pht_cap->ht_cap.ht_cap_info);
+ else
+ RESETHT_TXSTBC(pht_cap->ht_cap.ht_cap_info);
+
+ /* No user config for Delayed BACK yet */
+ if (GET_DELAYEDBACK(pmadapter->hw_dot_11n_dev_cap))
+ SETHT_DELAYEDBACK(pht_cap->ht_cap.ht_cap_info);
+ else
+ RESETHT_DELAYEDBACK(pht_cap->ht_cap.ht_cap_info);
+
+ /* Need change to support 8k AMSDU receive */
+ RESETHT_MAXAMSDU(pht_cap->ht_cap.ht_cap_info);
+
+ 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
+ *
+ * @return N/A
+ */
+void
+wlan_fill_ht_cap_tlv(mlan_private * priv,
+ MrvlIETypes_HTCap_t * pht_cap, t_u8 bands)
+{
+ 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 = pmadapter->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap = pmadapter->usr_dot_11n_dev_cap_bg;
+
+ /* Fill HT cap info */
+ wlan_fill_cap_info(priv, pht_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(pmadapter->usr_dev_mcs_support);
+ /* Set MCS for 1x1/2x2 */
+ memset(pmadapter, (t_u8 *) pht_cap->ht_cap.supported_mcs_set, 0xff,
+ rx_mcs_supp);
+ /* Clear all the other values */
+ 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 (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+ 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;
+}
+#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 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));
+
+ if ((ptx_ba_tbl = wlan_11n_get_txbastream_status(priv,
+ BA_STREAM_SETUP_INPROGRESS)))
+ {
+ 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_11n_create_txbastream_tbl(priv, pdel_ba->peer_mac_addr, tid,
+ BA_STREAM_SETUP_INPROGRESS);
+ if ((ptx_ba_tbl = wlan_11n_get_txbastream_status(priv,
+ BA_STREAM_SETUP_INPROGRESS)))
+ {
+ mlan_11n_delete_bastream_tbl(priv, ptx_ba_tbl->tid,
+ ptx_ba_tbl->ra, TYPE_DELBA_SENT,
+ MTRUE);
+ }
+ }
+ }
+
+ 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;
+
+ 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;
+ if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) {
+ if ((ptx_ba_tbl = wlan_11n_get_txbastream_tbl(priv, tid,
+ padd_ba_rsp->
+ peer_mac_addr))) {
+ PRINTM(MCMND,
+ "ADDBA REQ: %02x:%02x:%02x:%02x:%02x:%02x tid=%d ssn=%d win_size=%d,amsdu=%d\n",
+ padd_ba_rsp->peer_mac_addr[0], padd_ba_rsp->peer_mac_addr[1],
+ padd_ba_rsp->peer_mac_addr[2], padd_ba_rsp->peer_mac_addr[3],
+ padd_ba_rsp->peer_mac_addr[4], padd_ba_rsp->peer_mac_addr[5],
+ 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;
+ } else {
+ PRINTM(MERROR, "BA stream not created\n");
+ }
+ } else {
+ mlan_11n_delete_bastream_tbl(priv, tid, padd_ba_rsp->peer_mac_addr,
+ TYPE_DELBA_SENT, MTRUE);
+ if (padd_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) {
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+ disable_station_ampdu(priv, tid, padd_ba_rsp->peer_mac_addr);
+#endif /* UAP_SUPPORT */
+ priv->aggr_prio_tbl[tid].ampdu_ap = BA_STREAM_NOT_ALLOWED;
+
+ } else {
+ /* reset packet threshold */
+ ra_list =
+ wlan_wmm_get_ralist_node(priv, tid, padd_ba_rsp->peer_mac_addr);
+ 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 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);
+ 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 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;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @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;
+ 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 = pmadapter->usr_dot_11n_dev_cap_a;
+ else
+ usr_dot_11n_dev_cap = pmadapter->usr_dot_11n_dev_cap_bg;
+
+ 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);
+
+ 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);
+ }
+
+ 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].radio_type =
+ wlan_band_to_radio_type((t_u8) pbss_desc->bss_band);
+
+ if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+ ISALLOWED_CHANWIDTH40(pbss_desc->pht_info->ht_info.field2))
+ SET_SECONDARYCHAN(pchan_list->chan_scan_param[0].radio_type,
+ GET_SECONDARYCHAN(pbss_desc->pht_info->ht_info.
+ field2));
+
+ 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 *) pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
+ pext_cap->header.len);
+
+ 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);
+ }
+
+ 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_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;
+ 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();
+
+ pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+ priv->tx_ba_stream_tbl_ptr.plock);
+
+ 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:
+ pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+ priv->tx_ba_stream_tbl_ptr.plock);
+ 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();
+
+ while ((del_tbl_ptr = (TxBAStreamTbl *)
+ util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ priv->adapter->callbacks.moal_spin_lock,
+ priv->adapter->callbacks.moal_spin_unlock))) {
+ wlan_11n_delete_txbastream_tbl_entry(priv, del_tbl_ptr);
+ }
+
+ util_init_list((pmlan_linked_list) & priv->tx_ba_stream_tbl_ptr);
+
+ 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
+ *
+ * @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)
+{
+ TxBAStreamTbl *ptx_tbl;
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ if (!(ptx_tbl = (TxBAStreamTbl *) util_peek_list(pmadapter->pmoal_handle,
+ &priv->
+ tx_ba_stream_tbl_ptr,
+ pmadapter->callbacks.
+ moal_spin_lock,
+ pmadapter->callbacks.
+ moal_spin_unlock))) {
+ 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)) {
+ LEAVE();
+ return ptx_tbl;
+ }
+
+ ptx_tbl = ptx_tbl->pnext;
+ }
+
+ 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 *newNode = MNULL;
+ pmlan_adapter pmadapter = priv->adapter;
+
+ ENTER();
+
+ if (!wlan_11n_get_txbastream_tbl(priv, tid, ra)) {
+ PRINTM(MDAT_D, "get_txbastream_tbl TID %d\n", tid);
+ DBG_HEXDUMP(MDAT_D, "RA", ra, MLAN_MAC_ADDR_LENGTH);
+
+ pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+ sizeof(TxBAStreamTbl), MLAN_MEM_DEF,
+ (t_u8 **) & newNode);
+ util_init_list((pmlan_linked_list) newNode);
+
+ newNode->tid = tid;
+ newNode->ba_status = ba_status;
+ memcpy(pmadapter, newNode->ra, ra, MLAN_MAC_ADDR_LENGTH);
+
+ util_enqueue_list_tail(pmadapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ (pmlan_linked_list) newNode,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ }
+
+ 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 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_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int
+wlan_send_delba(mlan_private * priv, 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);
+
+ /* We don't wait for the response of this command */
+ ret = wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA,
+ HostCmd_ACT_GEN_SET, 0, MNULL, &delba);
+
+ 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));
+
+ 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 *rxReorderTblPtr;
+ int count = 0;
+ ENTER();
+ if (!
+ (rxReorderTblPtr =
+ (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))) {
+ LEAVE();
+ return count;
+ }
+ while (rxReorderTblPtr != (RxReorderTbl *) & priv->rx_reorder_tbl_ptr) {
+ ptbl->tid = (t_u16) rxReorderTblPtr->tid;
+ memcpy(priv->adapter, ptbl->ta, rxReorderTblPtr->ta,
+ MLAN_MAC_ADDR_LENGTH);
+ ptbl->start_win = rxReorderTblPtr->start_win;
+ ptbl->win_size = rxReorderTblPtr->win_size;
+ ptbl->amsdu = rxReorderTblPtr->amsdu;
+ for (i = 0; i < rxReorderTblPtr->win_size; ++i) {
+ if (rxReorderTblPtr->rx_reorder_ptr[i])
+ ptbl->buffer[i] = MTRUE;
+ else
+ ptbl->buffer[i] = MFALSE;
+ }
+ rxReorderTblPtr = rxReorderTblPtr->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;
+
+ ENTER();
+
+ if (!(ptxtbl = (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ priv->adapter->callbacks.
+ moal_spin_lock,
+ priv->adapter->callbacks.
+ moal_spin_unlock))) {
+ LEAVE();
+ return count;
+ }
+
+ 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 >= MLAN_MAX_TX_BASTREAM_SUPPORTED)
+ break;
+ }
+
+ LEAVE();
+ return count;
+}
+
+/**
+ * @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();
+ for (i = 0; i < MAX_NUM_TID; ++i) {
+ if ((ptx_tbl = wlan_11n_get_txbastream_tbl(priv, i, ra))) {
+ wlan_11n_delete_txbastream_tbl_entry(priv, ptx_tbl);
+ }
+ }
+ LEAVE();
+ return;
+}
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n.h b/drivers/net/wireless/sd8797/mlan/mlan_11n.h
new file mode 100644
index 000000000000..dc3d98974f03
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_11n.h
@@ -0,0 +1,420 @@
+/** @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-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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 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
+/** 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);
+#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);
+/** 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, 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);
+/** 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);
+/** 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);
+
+/** 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;
+ if ((sta_ptr = wlan_get_station_entry(priv, mac))) {
+ 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;
+ if ((sta_ptr = wlan_get_station_entry(priv, mac))) {
+ 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;
+ if ((sta_ptr = wlan_get_station_entry(priv, ptr->ra))) {
+ 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;
+ if ((sta_ptr = wlan_get_station_entry(priv, ra))) {
+ sta_ptr->ampdu_sta[tid] = BA_STREAM_NOT_ALLOWED;
+ }
+ return;
+}
+
+/**
+ * @brief This function checks whether current BA stream is high priority or not
+ *
+ * @param priv A pointer to mlan_private
+ * @param tid TID
+ *
+ * @return MTRUE or MFALSE
+ */
+static INLINE t_u8
+wlan_is_cur_bastream_high_prio(mlan_private * priv, int tid)
+{
+ TxBAStreamTbl *ptx_tbl;
+
+ ENTER();
+
+ if (!
+ (ptx_tbl =
+ (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ priv->adapter->callbacks.
+ moal_spin_lock,
+ priv->adapter->callbacks.
+ moal_spin_unlock)))
+ return MFALSE;
+
+ while (ptx_tbl != (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) {
+ if (priv->aggr_prio_tbl[tid].ampdu_user >
+ priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user) {
+ LEAVE();
+ return MTRUE;
+ }
+
+ ptx_tbl = ptx_tbl->pnext;
+ }
+
+ LEAVE();
+ return MFALSE;
+}
+
+/**
+ * @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;
+
+ return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED)
+ ? MTRUE : MFALSE);
+}
+
+/**
+ * @brief This function checks whether AMSDU is allowed for BA stream
+ *
+ * @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 int INLINE
+wlan_is_amsdu_in_ampdu_allowed(mlan_private * priv, raListTbl * ptr, int tid)
+{
+ TxBAStreamTbl *ptx_tbl;
+ ENTER();
+ if ((ptx_tbl = wlan_11n_get_txbastream_tbl(priv, tid, ptr->ra))) {
+ LEAVE();
+ return ptx_tbl->amsdu;
+ }
+ LEAVE();
+ return 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) {
+ if ((sta_ptr = wlan_get_station_entry(priv, ptr->ra))) {
+ 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;
+ for (i = 0; i < priv->adapter->priv_num; i++) {
+ if ((pmpriv = priv->adapter->priv[i]))
+ bastream_num +=
+ wlan_wmm_list_len(priv->adapter,
+ (pmlan_list_head) & pmpriv->
+ tx_ba_stream_tbl_ptr);
+ }
+ return ((bastream_num < MLAN_MAX_TX_BASTREAM_SUPPORTED) ? 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();
+
+ if (!
+ (ptx_tbl =
+ (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle,
+ &priv->tx_ba_stream_tbl_ptr,
+ priv->adapter->callbacks.
+ moal_spin_lock,
+ priv->adapter->callbacks.
+ moal_spin_unlock))) {
+ 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 BA stream is setup
+ *
+ * @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 int INLINE
+wlan_is_bastream_setup(mlan_private * priv, raListTbl * ptr, int tid)
+{
+ TxBAStreamTbl *ptx_tbl;
+
+ ENTER();
+
+ if ((ptx_tbl = wlan_11n_get_txbastream_tbl(priv, tid, ptr->ra))) {
+ LEAVE();
+ return IS_BASTREAM_SETUP(ptx_tbl) ? MTRUE : MFALSE;
+ }
+
+ LEAVE();
+ return MFALSE;
+}
+
+/**
+ * @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 int INLINE
+wlan_is_11n_enabled(mlan_private * priv, t_u8 * ra)
+{
+ int ret = MFALSE;
+ ENTER();
+#ifdef UAP_SUPPORT
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+ if ((!(ra[0] & 0x01)) && (priv->is_11n_enabled))
+ ret = is_station_11n_enabled(priv, ra);
+ }
+#endif /* UAP_SUPPORT */
+ LEAVE();
+ return ret;
+}
+#endif /* !_MLAN_11N_H_ */
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c b/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c
new file mode 100644
index 000000000000..239be3d67cea
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c
@@ -0,0 +1,508 @@
+/** @file mlan_11n_aggr.c
+ *
+ * @brief This file contains functions for 11n Aggregation.
+ *
+ * Copyright (C) 2008-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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 (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;
+
+ ENTER();
+ while (total_pkt_len > 0) {
+ /* Length will be in network format, change it to host */
+ pkt_len = mlan_ntohs((*(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH))));
+ 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;
+ int pad;
+ mlan_status ret = MLAN_STATUS_FAILURE;
+ RxPacketHdr_t *prx_pkt;
+ mlan_buffer *daggr_mbuf = MNULL;
+ mlan_adapter *pmadapter = priv->adapter;
+ t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03,
+ 0x00, 0x00, 0x00
+ };
+
+ ENTER();
+
+ data = (t_u8 *) (pmbuf->pbuf + pmbuf->data_offset);
+ total_pkt_len = pmbuf->data_len;
+
+ /* Sanity test */
+ if (total_pkt_len > MLAN_RX_DATA_BUF_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 > 0) {
+ 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);
+ 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, 0, MFALSE);
+ if (daggr_mbuf == MNULL) {
+ PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
+ LEAVE();
+ return MLAN_STATUS_FAILURE;
+ }
+ 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 */
+ ret =
+ pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+ daggr_mbuf);
+
+ 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:
+ 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;
+ t_u32 sec, usec;
+ 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");
+
+ if ((pmbuf_src =
+ (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle,
+ &pra_list->buf_head, MNULL, MNULL))) {
+
+ if (!(pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter,
+ pmadapter->tx_buf_size, 0,
+ MTRUE))) {
+ 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;
+
+ /* 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
+ } 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);
+ }
+
+ 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:
+ pmadapter->data_sent = MFALSE;
+ 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);
+ }
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+ &usec);
+ PRINTM_NETINTF(MDATA, priv);
+ PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec);
+
+ exit:
+ LEAVE();
+ return (pkt_size + headroom);
+}
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.h b/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.h
new file mode 100644
index 000000000000..ef8108a764c0
--- /dev/null
+++ b/drivers/net/wireless/sd8797/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-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c b/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c
new file mode 100644
index 000000000000..cabd78b9017f
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c
@@ -0,0 +1,1135 @@
+/** @file mlan_11n_rxreorder.c
+ *
+ * @brief This file contains the handling of RxReordering in wlan
+ * driver.
+ *
+ * Copyright (C) 2008-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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)
+{
+ ENTER();
+ 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_TIMER_MS));
+
+ 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;
+ }
+
+ 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);
+ priv->adapter->callbacks.moal_free_timer(pmadapter->pmoal_handle,
+ rx_reor_tbl_ptr->timer_context.
+ timer);
+ }
+
+ 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);
+
+ 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 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;
+ int startWin;
+
+ ENTER();
+ reorder_cnxt->timer_is_set = MFALSE;
+ wlan_11n_display_tbl_ptr(reorder_cnxt->priv->adapter, reorder_cnxt->ptr);
+
+ if ((startWin = wlan_11n_find_last_seqnum(reorder_cnxt->ptr)) >= 0) {
+ PRINTM(MINFO, "Flush data %d\n", startWin);
+ wlan_11n_dispatch_pkt_until_start_win(reorder_cnxt->priv,
+ reorder_cnxt->ptr,
+ ((reorder_cnxt->ptr->start_win +
+ startWin + 1) & (MAX_TID_VALUE -
+ 1)));
+ }
+
+ wlan_11n_display_tbl_ptr(reorder_cnxt->priv->adapter, reorder_cnxt->ptr);
+ 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
+ */
+ if ((rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tid, ta))) {
+ 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 %02x:%02x:%02x:%02x:"
+ "%02x:%02x, win_size %d\n", __FUNCTION__,
+ seq_num, tid, ta[0], ta[1], ta[2], ta[3],
+ ta[4], ta[5], 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;
+ if (queuing_ra_based(priv)) {
+ // TODO for adhoc
+ if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+ if ((sta_ptr = wlan_get_station_entry(priv, ta)))
+ last_seq = sta_ptr->rx_seq[tid];
+ }
+ PRINTM(MINFO, "UAP/ADHOC:last_seq=%d start_win=%d\n", last_seq,
+ new_node->start_win);
+ } else {
+ last_seq = priv->rx_seq[tid];
+ }
+ if ((last_seq != DEFAULT_SEQ_NUM) && (last_seq >= new_node->start_win)) {
+ PRINTM(MDAT_D, "Update start_win: last_seq=%d, start_win=%d\n",
+ last_seq, new_node->start_win);
+ new_node->start_win = last_seq + 1;
+ }
+ new_node->win_size = win_size;
+
+ 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\n", new_node);
+ 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();
+
+ if (!
+ (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))) {
+ 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);
+
+ LEAVE();
+ return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @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->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 (priv->addba_reject[tid]
+#ifdef STA_SUPPORT
+ || ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+ && priv->wps.session_enable)
+#endif
+#ifdef UAP_SUPPORT
+ || ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+ && (priv->adapter->pending_bridge_pkts > 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 ||
+ (priv->aggr_prio_tbl[tid].amsdu == BA_STREAM_NOT_ALLOWED))
+ /* 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;
+ 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);
+
+ 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();
+
+ if (!
+ (rx_reor_tbl_ptr =
+ wlan_11n_get_rxreorder_tbl((mlan_private *) priv, tid, ta))) {
+ if (pkt_type != PKT_TYPE_BAR)
+ wlan_11n_dispatch_pkt(priv, payload);
+
+ LEAVE();
+ return ret;
+
+ } else {
+ 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 ");
+
+ 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 %02x:%02x:%02x:%02x:%02x:%02x\n",
+ tid, ta[0], ta[1], ta[2], ta[3], ta[4], ta[5]);
+ 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 ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { /* Wrap */
+ if (seq_num >= ((start_win + (TWOPOW11)) &
+ (MAX_TID_VALUE - 1)) && (seq_num < start_win)) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ } else if ((seq_num < start_win) ||
+ (seq_num > (start_win + (TWOPOW11)))) {
+ 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 < (TWOPOW11 - (MAX_TID_VALUE - 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;
+
+ if ((ret = wlan_11n_dispatch_pkt_until_start_win(priv,
+ rx_reor_tbl_ptr,
+ start_win))) {
+ 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
+ *
+ * @return N/A
+ */
+void
+mlan_11n_delete_bastream_tbl(mlan_private * priv, int tid,
+ t_u8 * peer_mac, t_u8 type, int initiator)
+{
+ RxReorderTbl *rx_reor_tbl_ptr;
+ TxBAStreamTbl *ptxtbl;
+ t_u8 cleanup_rx_reorder_tbl;
+
+ ENTER();
+
+ if (type == TYPE_DELBA_RECEIVE)
+ cleanup_rx_reorder_tbl = (initiator) ? MTRUE : MFALSE;
+ else
+ cleanup_rx_reorder_tbl = (initiator) ? MFALSE : MTRUE;
+
+ PRINTM(MEVENT, "DELBA: %02x:%02x:%02x:%02x:%02x:%02x tid=%d,"
+ "initiator=%d\n", peer_mac[0],
+ peer_mac[1], peer_mac[2],
+ peer_mac[3], peer_mac[4], peer_mac[5], tid, initiator);
+
+ if (cleanup_rx_reorder_tbl) {
+ if (!(rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tid,
+ peer_mac))) {
+ PRINTM(MWARN, "TID, TA not found in table!\n");
+ LEAVE();
+ return;
+ }
+ wlan_11n_delete_rxreorder_tbl_entry(priv, rx_reor_tbl_ptr);
+ } else {
+ if (!(ptxtbl = wlan_11n_get_txbastream_tbl(priv, tid, peer_mac))) {
+ PRINTM(MWARN, "TID, RA not found in table!\n");
+ LEAVE();
+ return;
+ }
+
+ wlan_11n_delete_txbastream_tbl_entry(priv, ptxtbl);
+ }
+
+ 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: %02x:%02x:%02x:%02x:%02x:%02x tid=%d ssn=%d win_size=%d,amsdu=%d\n",
+ padd_ba_rsp->peer_mac_addr[0], padd_ba_rsp->peer_mac_addr[1],
+ padd_ba_rsp->peer_mac_addr[2], padd_ba_rsp->peer_mac_addr[3],
+ padd_ba_rsp->peer_mac_addr[4], padd_ba_rsp->peer_mac_addr[5],
+ 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);
+
+ if ((rx_reor_tbl_ptr =
+ wlan_11n_get_rxreorder_tbl(priv, tid,
+ padd_ba_rsp->peer_mac_addr))) {
+ 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 &&
+ (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
+ rx_reor_tbl_ptr->amsdu = MTRUE;
+ else
+ rx_reor_tbl_ptr->amsdu = MFALSE;
+ }
+ } else {
+ PRINTM(MERROR,
+ "ADDBA RSP: Failed(%02x:%02x:%02x:%02x:%02x:%02x tid=%d)\n",
+ padd_ba_rsp->peer_mac_addr[0], padd_ba_rsp->peer_mac_addr[1],
+ padd_ba_rsp->peer_mac_addr[2], padd_ba_rsp->peer_mac_addr[3],
+ padd_ba_rsp->peer_mac_addr[4], padd_ba_rsp->peer_mac_addr[5],
+ tid);
+ if ((rx_reor_tbl_ptr =
+ wlan_11n_get_rxreorder_tbl(priv, tid,
+ padd_ba_rsp->peer_mac_addr))) {
+ 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,
+ "%02x:%02x:%02x:%02x:%02x:%02x tid=%d seq_num=%d bitmap_len=%d\n",
+ tlv_rxba->mac[0], tlv_rxba->mac[1], tlv_rxba->mac[2],
+ tlv_rxba->mac[3], tlv_rxba->mac[4], tlv_rxba->mac[5],
+ 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;
+ }
+ 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 will send a DELBA for each entry in the priv's
+ * rx reordering table
+ *
+ * @param priv A pointer to mlan_private
+ */
+t_void
+wlan_send_delba_to_all_in_reorder_tbl(pmlan_private priv)
+{
+ RxReorderTbl *rx_reor_tbl_ptr;
+
+ ENTER();
+
+ if (!
+ (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))) {
+ LEAVE();
+ return;
+ }
+
+ while (rx_reor_tbl_ptr != (RxReorderTbl *) & priv->rx_reorder_tbl_ptr) {
+ if (rx_reor_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
+ rx_reor_tbl_ptr->ba_status = BA_STREAM_SETUP_INPROGRESS;
+ wlan_send_delba(priv, rx_reor_tbl_ptr->tid, rx_reor_tbl_ptr->ta, 0);
+ }
+ rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+ }
+ LEAVE();
+}
+
+/**
+ * @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) {
+ if ((rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, i, ta))) {
+ wlan_11n_delete_rxreorder_tbl_entry(priv, rx_reor_tbl_ptr);
+ }
+ }
+ LEAVE();
+ return;
+}
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.h b/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.h
new file mode 100644
index 000000000000..4ff15834c8a3
--- /dev/null
+++ b/drivers/net/wireless/sd8797/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-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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);
+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);
+
+/** send delba for all entries in reorder_tbl */
+t_void wlan_send_delba_to_all_in_reorder_tbl(pmlan_private priv);
+
+/** clean up reorder_tbl */
+void wlan_cleanup_reorder_tbl(mlan_private * priv, t_u8 * ta);
+#endif /* _MLAN_11N_RXREORDER_H_ */
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_cfp.c b/drivers/net/wireless/sd8797/mlan/mlan_cfp.c
new file mode 100644
index 000000000000..742c9cd368bc
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_cfp.c
@@ -0,0 +1,1148 @@
+/**
+ * @file mlan_cfp.c
+ *
+ * @brief This file contains WLAN client mode channel, frequency and power
+ * related code
+ *
+ * Copyright (C) 2009-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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"
+
+/********************************************************
+ Local Variables
+********************************************************/
+
+/** 100mW */
+#define WLAN_TX_PWR_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
+
+/**
+ * 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},
+ {2, 2417, WLAN_TX_PWR_US_DEFAULT},
+ {3, 2422, WLAN_TX_PWR_US_DEFAULT},
+ {4, 2427, WLAN_TX_PWR_US_DEFAULT},
+ {5, 2432, WLAN_TX_PWR_US_DEFAULT},
+ {6, 2437, WLAN_TX_PWR_US_DEFAULT},
+ {7, 2442, WLAN_TX_PWR_US_DEFAULT},
+ {8, 2447, WLAN_TX_PWR_US_DEFAULT},
+ {9, 2452, WLAN_TX_PWR_US_DEFAULT},
+ {10, 2457, WLAN_TX_PWR_US_DEFAULT},
+ {11, 2462, WLAN_TX_PWR_US_DEFAULT}
+};
+
+/** Band: 'B/G', Region: Europe ETSI/China */
+static chan_freq_power_t channel_freq_power_EU_BG[] = {
+ {1, 2412, WLAN_TX_PWR_EMEA_DEFAULT},
+ {2, 2417, WLAN_TX_PWR_EMEA_DEFAULT},
+ {3, 2422, WLAN_TX_PWR_EMEA_DEFAULT},
+ {4, 2427, WLAN_TX_PWR_EMEA_DEFAULT},
+ {5, 2432, WLAN_TX_PWR_EMEA_DEFAULT},
+ {6, 2437, WLAN_TX_PWR_EMEA_DEFAULT},
+ {7, 2442, WLAN_TX_PWR_EMEA_DEFAULT},
+ {8, 2447, WLAN_TX_PWR_EMEA_DEFAULT},
+ {9, 2452, WLAN_TX_PWR_EMEA_DEFAULT},
+ {10, 2457, WLAN_TX_PWR_EMEA_DEFAULT},
+ {11, 2462, WLAN_TX_PWR_EMEA_DEFAULT},
+ {12, 2467, WLAN_TX_PWR_EMEA_DEFAULT},
+ {13, 2472, WLAN_TX_PWR_EMEA_DEFAULT}
+};
+
+/** Band: 'B/G', Region: France */
+static chan_freq_power_t channel_freq_power_FR_BG[] = {
+ {1, 2412, WLAN_TX_PWR_FR_100MW},
+ {2, 2417, WLAN_TX_PWR_FR_100MW},
+ {3, 2422, WLAN_TX_PWR_FR_100MW},
+ {4, 2427, WLAN_TX_PWR_FR_100MW},
+ {5, 2432, WLAN_TX_PWR_FR_100MW},
+ {6, 2437, WLAN_TX_PWR_FR_100MW},
+ {7, 2442, WLAN_TX_PWR_FR_100MW},
+ {8, 2447, WLAN_TX_PWR_FR_100MW},
+ {9, 2452, WLAN_TX_PWR_FR_100MW},
+ {10, 2457, WLAN_TX_PWR_FR_10MW},
+ {11, 2462, WLAN_TX_PWR_FR_10MW},
+ {12, 2467, WLAN_TX_PWR_FR_10MW},
+ {13, 2472, WLAN_TX_PWR_FR_10MW}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
+ {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
+ {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT}
+};
+
+/** Band : 'B/G', Region: Special */
+static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
+ {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT},
+ {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT}
+};
+
+/**
+ * The 2.4GHz CFP tables
+ */
+static cfp_table_t cfp_table_BG[] = {
+ {0x10, /* US FCC */
+ channel_freq_power_US_BG,
+ sizeof(channel_freq_power_US_BG) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x20, /* CANADA IC */
+ channel_freq_power_US_BG,
+ sizeof(channel_freq_power_US_BG) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x30, /* EU */
+ channel_freq_power_EU_BG,
+ sizeof(channel_freq_power_EU_BG) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x32, /* FRANCE */
+ channel_freq_power_FR_BG,
+ sizeof(channel_freq_power_FR_BG) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x40, /* JAPAN */
+ channel_freq_power_JPN40_BG,
+ sizeof(channel_freq_power_JPN40_BG) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x41, /* JAPAN */
+ channel_freq_power_JPN41_BG,
+ sizeof(channel_freq_power_JPN41_BG) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x50, /* China */
+ channel_freq_power_EU_BG,
+ sizeof(channel_freq_power_EU_BG) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0xff, /* Special */
+ channel_freq_power_SPECIAL_BG,
+ sizeof(channel_freq_power_SPECIAL_BG) / sizeof(chan_freq_power_t),
+ }
+ ,
+/* Add new region here */
+};
+
+/** Number of the CFP tables for 2.4GHz */
+#define MLAN_CFP_TABLE_SIZE_BG (sizeof(cfp_table_BG)/sizeof(cfp_table_t))
+
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: USA FCC, Spain, France */
+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},
+ {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},
+ {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}
+};
+
+/** Band: 'A', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN_A[] = {
+ {8, 5040, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+ {12, 5060, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+ {16, 5080, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
+ {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[] = {
+ {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}
+};
+
+/**
+ * The 5GHz CFP tables
+ */
+static cfp_table_t cfp_table_A[] = {
+ {0x10, /* US FCC */
+ channel_freq_power_A,
+ sizeof(channel_freq_power_A) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x20, /* CANADA IC */
+ channel_freq_power_CAN_A,
+ sizeof(channel_freq_power_CAN_A) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x30, /* EU */
+ channel_freq_power_EU_A,
+ sizeof(channel_freq_power_EU_A) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x32, /* FRANCE */
+ channel_freq_power_A,
+ sizeof(channel_freq_power_A) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x40, /* JAPAN */
+ channel_freq_power_JPN_A,
+ sizeof(channel_freq_power_JPN_A) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x41, /* JAPAN */
+ channel_freq_power_JPN_A,
+ sizeof(channel_freq_power_JPN_A) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0x50, /* China */
+ channel_freq_power_CN_A,
+ sizeof(channel_freq_power_CN_A) / sizeof(chan_freq_power_t),
+ }
+ ,
+ {0xff, /* Special */
+ channel_freq_power_JPN_A,
+ sizeof(channel_freq_power_JPN_A) / sizeof(chan_freq_power_t),
+ }
+ ,
+/* Add new region here */
+};
+
+/** Number of the CFP tables for 5GHz */
+#define MLAN_CFP_TABLE_SIZE_A (sizeof(cfp_table_A)/sizeof(cfp_table_t))
+
+/********************************************************
+ Global Variables
+********************************************************/
+/**
+ * The table to keep region code
+ */
+t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] =
+ { 0x10, 0x20, 0x30, 0x32, 0x40, 0x41, 0x50, 0xff };
+
+/**
+ * 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, 0 };
+
+/**
+ * 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, 0
+};
+
+/**
+ * The rates supported in A mode for ad-hoc
+ */
+t_u8 AdhocRates_A[A_SUPPORTED_RATES] =
+ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0 };
+
+/**
+ * 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, 0 };
+
+/**
+ * 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, 0 };
+
+/**
+ * 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, 0 };
+
+/**
+ * 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, 0
+};
+
+/**
+ * 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 (band & (BAND_B | BAND_G | BAND_GN)) {
+ 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)) {
+ 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;
+ }
+ }
+ }
+
+ PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band, region);
+
+ LEAVE();
+ return MNULL;
+}
+
+/********************************************************
+ Global Functions
+********************************************************/
+
+#ifdef STA_SUPPORT
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief Use index to get the data rate
+ *
+ * @param pmadapter A pointer to mlan_adapter structure
+ * @param index The index of data rate
+ * @param ht_info ht info
+ *
+ * @return Data rate or 0
+ */
+
+t_u32
+wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 ht_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 */
+
+ t_u32 rate = 0;
+ ENTER();
+
+ if (ht_info & MBIT(0)) {
+ if (index == MLAN_RATE_BITMAP_MCS0) {
+ if (ht_info & MBIT(2))
+ rate = 0x0D; /* MCS 32 SGI rate */
+ else
+ rate = 0x0C; /* MCS 32 LGI rate */
+ } else if (index < MCS_NUM_SUPP) {
+ if (ht_info & MBIT(1)) {
+ if (ht_info & MBIT(2))
+ rate = mcs_rate[1][index]; /* SGI, 40M */
+ else
+ rate = mcs_rate[0][index]; /* LGI, 40M */
+ } else {
+ if (ht_info & MBIT(2))
+ rate = mcs_rate[3][index]; /* SGI, 20M */
+ else
+ rate = mcs_rate[2][index]; /* LGI, 20M */
+ }
+ } 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)
+ if ((ptr = wlan_memchr(pmadapter, WlanDataRates, (t_u8) rate,
+ sizeof(WlanDataRates)))) {
+ 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: /* 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_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(MERROR, "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: /* 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_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 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 BAND_G:
+ case BAND_G | BAND_GN:
+ 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_B | BAND_G | BAND_GN:
+ 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:
+ 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:
+ 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 BAND_B:
+ PRINTM(MINFO, "Band: Adhoc B\n");
+ k = wlan_copy_rates(rates, k, AdhocRates_B, sizeof(AdhocRates_B));
+ break;
+ case BAND_G:
+ case BAND_G | BAND_GN:
+ 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:
+ 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:
+ PRINTM(MINFO, "Band: Adhoc A\n");
+ k = wlan_copy_rates(rates, k, AdhocRates_A, sizeof(AdhocRates_A));
+ break;
+ }
+ }
+
+ LEAVE();
+ return k;
+}
+
+/**
+ * @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;
+ chan_freq_power_t *cfp;
+ int cfp_no;
+
+ ENTER();
+
+ 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;
+ i++;
+ }
+ if (band & (BAND_A | BAND_AN)) {
+ 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;
+ }
+ 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].radar_detect;
+ break;
+ }
+ }
+
+ done:
+ LEAVE();
+ return required;
+}
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c b/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c
new file mode 100644
index 000000000000..8b91ae2c43c2
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c
@@ -0,0 +1,2927 @@
+/**
+ * @file mlan_cmdevt.c
+ *
+ * @brief This file contains the handling of CMD/EVENT in MLAN
+ *
+ * Copyright (C) 2009-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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_11h.h"
+#include "mlan_sdio.h"
+/********************************************************
+ Local Variables
+********************************************************/
+
+/*******************************************************
+ Global Variables
+********************************************************/
+
+/********************************************************
+ Local Functions
+********************************************************/
+
+/**
+ * @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 dara 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) {
+ while (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) {
+ ptr++;
+ }
+
+ if (wlan_isxdigit(*ptr)) {
+ *dptr++ = wlan_atox(ptr);
+ ptr += 2;
+ } else {
+ ptr++;
+ }
+ }
+ LEAVE();
+ return (dptr - dst);
+}
+
+/**
+ * @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;
+ }
+
+ if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock)) {
+ pcmd_node = (cmd_ctrl_node *) util_dequeue_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_free_q,
+ pmadapter->callbacks.
+ moal_spin_lock,
+ pmadapter->callbacks.
+ moal_spin_unlock);
+ } else {
+ PRINTM(MERROR, "GET_CMD_NODE: cmd_ctrl_node is not available\n");
+ pcmd_node = MNULL;
+ }
+
+ 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;
+}
+
+/**
+ * @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();
+
+ if (!
+ (pcmd_node =
+ (cmd_ctrl_node *) util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.
+ moal_spin_unlock))) {
+ LEAVE();
+ return MNULL;
+ }
+ while (pcmd_node != (cmd_ctrl_node *) & pmadapter->cmd_pending_q) {
+ if (pcmd_node->pioctl_buf == pioctl_req) {
+ 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 sec, usec;
+
+ 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_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ 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));
+
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->curr_cmd = pcmd_node;
+ wlan_release_cmd_lock(pmadapter);
+
+ cmd_code = wlan_le16_to_cpu(pcmd->command);
+ cmd_size = wlan_le16_to_cpu(pcmd->size);
+
+ pcmd_node->cmdbuf->data_len = cmd_size;
+
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &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 (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+ wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->curr_cmd = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+
+ pmadapter->dbg.num_cmd_host_to_card_failure++;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* 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));
+
+ /* Clear BSS_NO_BITS from HostCmd */
+ cmd_code &= HostCmd_CMD_ID_MASK;
+ /* soft_reset command has no command response, we should return here */
+ if (cmd_code == HostCmd_CMD_SOFT_RESET) {
+ PRINTM(MCMND, "DNLD_CMD: SoftReset\n");
+ if (pioctl_buf) {
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->curr_cmd->pioctl_buf = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+ MLAN_STATUS_SUCCESS);
+ }
+ goto done;
+ }
+
+ /* Setup the timer after transmit command */
+ pcb->moal_start_timer(pmadapter->pmoal_handle, pmadapter->pmlan_cmd_timer,
+ MFALSE, MRVDRV_TIMER_60S);
+
+ 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 = 0;
+ 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);
+
+ ENTER();
+
+ 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,
+ (wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY))->
+ bss_num,
+ (wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY))->
+ 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(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY)) ==
+ MLAN_BSS_ROLE_UAP)
+ pmadapter->ps_state = PS_STATE_SLEEP_CFM;
+#ifdef STA_SUPPORT
+ if (GET_BSS_ROLE(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY)) ==
+ 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 = &priv->adapter->callbacks;
+
+ ENTER();
+
+ 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++) {
+ if (!(pcmd_array[i].pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+ MRVDRV_SIZE_OF_CMD_BUFFER,
+ 0, MTRUE))) {
+ PRINTM(MERROR,
+ "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+ }
+
+ for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
+ wlan_insert_cmd_to_free_q(pmadapter, &pcmd_array[i]);
+ }
+ 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;
+ t_u32 in_ts_sec;
+ t_u32 in_ts_usec;
+ 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));
+ }
+ }
+ /* 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);
+
+ /* 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)
+ ) {
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+ &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);
+
+ 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 = pmpriv->adapter;
+ cmd_ctrl_node *pcmd_node = MNULL;
+ HostCmd_DS_COMMAND *cmd_ptr = MNULL;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *) pioctl_buf;
+
+ ENTER();
+
+ /* 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");
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* 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;
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ if (pioctl_req)
+ pioctl_req->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /* 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
+ 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,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ 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);
+ if (pcmd == MNULL) {
+ PRINTM(MERROR, "QUEUE_CMD: pcmd is MNULL\n");
+ goto done;
+ }
+
+ 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,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ } else {
+ util_enqueue_list_head(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ (pmlan_linked_list) pcmd_node,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ }
+
+ 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,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+
+ 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,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ 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;
+ t_u32 sec, usec, 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;
+ wlan_release_cmd_lock(pmadapter);
+ PRINTM(MERROR, "CMD_RESP: 0x%x been canceled!\n",
+ wlan_le16_to_cpu(resp->command));
+ wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
+ if (pioctl_buf)
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ 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 */
+ 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);
+ 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;
+
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &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_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+ wlan_request_cmd_lock(pmadapter);
+ 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) {
+ 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;
+ wlan_release_cmd_lock(pmadapter);
+
+ 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 = 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);
+ } else {
+ wlan_release_cmd_lock(pmadapter);
+ }
+
+ if ((pmadapter->hw_status == WlanHardwareStatusInitializing) &&
+ (pmadapter->last_init_cmd == cmdresp_no)) {
+ i = pmpriv->bss_index + 1;
+ while (!(pmpriv_next = pmadapter->priv[i]) && i < pmadapter->priv_num)
+ 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);
+ }
+ }
+
+ 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;
+ t_u32 sec, usec;
+ t_u8 i;
+ mlan_private *pmpriv = MNULL;
+
+ ENTER();
+
+ pmadapter->cmd_timer_is_set = MFALSE;
+ pmadapter->num_cmd_timeout++;
+ pmadapter->dbg.num_cmd_timeout++;
+ if (!pmadapter->curr_cmd) {
+ PRINTM(MWARN, "CurCmd Empty\n");
+ goto exit;
+ }
+ 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;
+ }
+
+ if (pcmd_node) {
+ 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];
+ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &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);
+ }
+
+ PRINTM(MERROR, "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_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);
+ }
+ if (pmadapter->hw_status == WlanHardwareStatusInitializing)
+ 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)
+{
+ mlan_callbacks *pcb = (pmlan_callbacks) & pmadapter->callbacks;
+ cmd_ctrl_node *pcmd_node = MNULL;
+
+ ENTER();
+
+ while ((pcmd_node =
+ (cmd_ctrl_node *) util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->scan_pending_q,
+ pcb->moal_spin_lock,
+ pcb->moal_spin_unlock))) {
+ util_unlink_list(pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
+ (pmlan_linked_list) pcmd_node, pcb->moal_spin_lock,
+ pcb->moal_spin_unlock);
+ pcmd_node->pioctl_buf = MNULL;
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ }
+ wlan_request_cmd_lock(pmadapter);
+ pmadapter->scan_processing = MFALSE;
+ wlan_release_cmd_lock(pmadapter);
+
+ LEAVE();
+}
+#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);
+ if ((pmadapter->curr_cmd) && (pmadapter->curr_cmd->pioctl_buf)) {
+ pioctl_buf = (mlan_ioctl_req *) pmadapter->curr_cmd->pioctl_buf;
+ pmadapter->curr_cmd->pioctl_buf = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+ pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+ pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+ MLAN_STATUS_FAILURE);
+ } else {
+ wlan_release_cmd_lock(pmadapter);
+ }
+ /* Cancel all pending command */
+ while ((pcmd_node =
+ (cmd_ctrl_node *) util_peek_list(pmadapter->pmoal_handle,
+ &pmadapter->cmd_pending_q,
+ pcb->moal_spin_lock,
+ pcb->moal_spin_unlock))) {
+ util_unlink_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
+ (pmlan_linked_list) pcmd_node, pcb->moal_spin_lock,
+ pcb->moal_spin_unlock);
+ 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);
+ }
+#ifdef STA_SUPPORT
+ /* Cancel all pending scan command */
+ wlan_flush_scan_queue(pmadapter);
+#endif
+ LEAVE();
+}
+
+/**
+ * @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;
+
+ 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);
+ 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;
+ }
+
+ 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,
+ pmadapter->callbacks.moal_spin_lock,
+ pmadapter->callbacks.moal_spin_unlock);
+ pcmd_node->pioctl_buf = MNULL;
+ wlan_release_cmd_lock(pmadapter);
+ wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+ wlan_request_cmd_lock(pmadapter);
+ }
+ wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+ if (pioctl_req->req_id == MLAN_IOCTL_SCAN) {
+ /* IOCTL will be completed, avoid calling IOCTL complete again from
+ EVENT */
+ if (pmadapter->pext_scan_ioctl_req == pioctl_req)
+ pmadapter->pext_scan_ioctl_req = MNULL;
+ /* Cancel all pending scan command */
+ wlan_flush_scan_queue(pmadapter);
+ }
+#endif
+ 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 (activated) {
+ if (priv->adapter->is_hs_configured) {
+ priv->adapter->hs_activated = 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();
+}
+
+/**
+ * @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_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+ wlan_request_cmd_lock(pmadapter);
+ 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_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_htinfo = resp->params.tx_rate.ht_info;
+ if (!pmpriv->is_data_rate_auto) {
+ pmpriv->data_rate = wlan_index_to_data_rate(pmadapter,
+ pmpriv->tx_rate,
+ pmpriv->tx_htinfo);
+ }
+
+ 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_htinfo & MBIT(0))
+ rate->param.rate_cfg.rate =
+ pmpriv->tx_rate + MLAN_RATE_INDEX_MCS0;
+ else
+ /* 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.rate_cfg.rate =
+ (pmpriv->tx_rate >
+ MLAN_RATE_INDEX_OFDM0) ? pmpriv->tx_rate -
+ 1 : pmpriv->tx_rate;
+ } else {
+ rate->param.rate_cfg.rate =
+ wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate,
+ pmpriv->tx_htinfo);
+ }
+ } else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) {
+ if (pmpriv->tx_htinfo & MBIT(0)) {
+ rate->param.data_rate.tx_data_rate =
+ pmpriv->tx_rate + MLAN_RATE_INDEX_MCS0;
+ if (pmpriv->tx_htinfo & MBIT(1))
+ rate->param.data_rate.tx_ht_bw = MLAN_HT_BW40;
+ else
+ rate->param.data_rate.tx_ht_bw = MLAN_HT_BW20;
+ if (pmpriv->tx_htinfo & MBIT(2))
+ rate->param.data_rate.tx_ht_gi = MLAN_HT_SGI;
+ else
+ rate->param.data_rate.tx_ht_gi = MLAN_HT_LGI;
+ } else
+ /* 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;
+ if (pmpriv->rxpd_htinfo & MBIT(0)) {
+ rate->param.data_rate.rx_data_rate =
+ pmpriv->rxpd_rate + MLAN_RATE_INDEX_MCS0;
+ if (pmpriv->rxpd_htinfo & MBIT(1))
+ rate->param.data_rate.rx_ht_bw = MLAN_HT_BW40;
+ else
+ rate->param.data_rate.rx_ht_bw = MLAN_HT_BW20;
+ if (pmpriv->tx_htinfo & MBIT(2))
+ rate->param.data_rate.rx_ht_gi = MLAN_HT_SGI;
+ else
+ rate->param.data_rate.rx_ht_gi = MLAN_HT_LGI;
+ } else
+ /* 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_multicast_list) + MLAN_SUB_COMMAND_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 = &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_cfg->cfg_index = 0;
+
+ 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 < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(t_u16);
+ i++)
+ rate_scope->ht_mcs_rate_bitmap[i] =
+ wlan_cpu_to_le16(pbitmap_rates[2 + 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 < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(t_u16);
+ i++)
+ rate_scope->ht_mcs_rate_bitmap[i] =
+ wlan_cpu_to_le16(pmpriv->bitmap_rates[2 + 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;
+ 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 = &resp->params.tx_rate_cfg;
+
+ tlv_buf = (t_u8 *) ((t_u8 *) prate_cfg) + sizeof(HostCmd_DS_TX_RATE_CFG);
+ 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 < sizeof(prate_scope->ht_mcs_rate_bitmap) / sizeof(t_u16);
+ i++)
+ pmpriv->bitmap_rates[2 + i] =
+ wlan_le16_to_cpu(prate_scope->ht_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;
+ } 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 = 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 = index + MLAN_RATE_INDEX_MCS0;
+ }
+ 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_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
+
+ /*
+ * This should be issued in the very first to config
+ * SDIO_GPIO interrupt mode.
+ */
+ if (wlan_set_sdio_gpio_int(pmpriv) != MLAN_STATUS_SUCCESS) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FUNC_INIT,
+ HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+ if (ret) {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ /** Cal data dnld cmd prepare */
+ if ((pmadapter->pcal_data) && (pmadapter->cal_data_len > 0)) {
+ ret =
+ wlan_prepare_cmd(pmpriv, HostCmd_CMD_CFG_DATA, HostCmd_ACT_GEN_SET,
+ 0, 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(pmpriv, HostCmd_CMD_GET_HW_SPEC,
+ 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;
+ }
+ }
+
+ ret = MLAN_STATUS_PENDING;
+ done:
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @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_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 cal_data_offset;
+ t_u8 *temp_pcmd = (t_u8 *) pcmd;
+
+ ENTER();
+
+ cal_data_offset = S_DS_GEN + sizeof(HostCmd_DS_802_11_CFG_DATA);
+ if ((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 + cal_data_offset));
+ } else {
+ ret = MLAN_STATUS_FAILURE;
+ goto done;
+ }
+
+ pcfg_data->action = cmd_action;
+ pcfg_data->type = 2; /* cal data type */
+ pcfg_data->data_len = len;
+
+ pcmd->command = HostCmd_CMD_CFG_DATA;
+ pcmd->size = pcfg_data->data_len + cal_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, "Cal data cmd resp failed\n");
+ ret = MLAN_STATUS_FAILURE;
+ }
+ LEAVE();
+ return ret;
+}
+
+/**
+ * @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;
+ pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *) pioctl_buf;
+
+ ENTER();
+
+ pmadapter->fw_cap_info = wlan_le32_to_cpu(hw_spec->fw_cap_info);
+#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;
+ }
+
+ 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_GN) {
+ pmadapter->config_bands |= BAND_AN;
+ for (i = 0; i < pmadapter->priv_num; i++) {
+ if (pmadapter->priv[i])
+ pmadapter->priv[i]->config_bands |= BAND_AN;
+ }
+
+ pmadapter->fw_bands |= BAND_AN;
+ }
+ 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 */
+
+ pmadapter->fw_release_number = hw_spec->fw_release_number;
+ pmadapter->number_of_antenna = wlan_le16_to_cpu(hw_spec->number_of_antenna);
+
+ PRINTM(MINFO, "GET_HW_SPEC: fw_release_number- 0x%X\n",
+ wlan_le32_to_cpu(pmadapter->fw_release_number));
+ PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
+ hw_spec->permanent_addr[0], hw_spec->permanent_addr[1],
+ hw_spec->permanent_addr[2], hw_spec->permanent_addr[3],
+ hw_spec->permanent_addr[4], hw_spec->permanent_addr[5]);
+ 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);
+
+ pmadapter->hw_dot_11n_dev_cap = wlan_le32_to_cpu(hw_spec->dot_11n_dev_cap);
+ pmadapter->usr_dot_11n_dev_cap_bg = pmadapter->hw_dot_11n_dev_cap &
+ DEFAULT_11N_CAP_MASK_BG;
+ pmadapter->usr_dot_11n_dev_cap_a = pmadapter->hw_dot_11n_dev_cap &
+ DEFAULT_11N_CAP_MASK_A;
+ pmadapter->usr_dev_mcs_support = pmadapter->hw_dev_mcs_support =
+ hw_spec->dev_mcs_support;
+ wlan_show_dot11ndevcap(pmadapter, pmadapter->hw_dot_11n_dev_cap);
+ wlan_show_devmcssupport(pmadapter, pmadapter->hw_dev_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(MINFO, "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->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);
+ }
+
+ 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 */
+
+ 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;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ * @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;
+}
+
+/**
+ * @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;
+}
+#endif
diff --git a/drivers/net/wireless/sd8797/mlan/mlan_decl.h b/drivers/net/wireless/sd8797/mlan/mlan_decl.h
new file mode 100644
index 000000000000..d0ca7acae937
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_decl.h
@@ -0,0 +1,883 @@
+/** @file mlan_decl.h
+ *
+ * @brief This file declares the generic data structures and APIs.
+ *
+ * Copyright (C) 2008-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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 "303"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef 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)
+
+/** 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 0
+
+/** DMA alignment */
+#define DMA_ALIGNMENT 64
+/** 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 2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED 16
+
+/** Default Win size attached during ADDBA request */
+#define MLAN_AMPDU_DEF_TXWINSIZE 32
+/** Default Win size attached during ADDBA response */
+#define MLAN_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 12
+/** Rate index for MCS 7 */
+#define MLAN_RATE_INDEX_MCS7 19
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9 21
+/** Rate index for MCS15 */
+#define MLAN_RATE_INDEX_MCS15 27
+/** Rate index for MCS 32 */
+#define MLAN_RATE_INDEX_MCS32 44
+/** Rate index for MCS 127 */
+#define MLAN_RATE_INDEX_MCS127 139
+
+/** 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
+
+/** 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)
+
+/** 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)
+
+/** 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 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)
+
+#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 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;
+
+/** 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,
+ MLAN_ERROR_FW_CMDRESP,
+ MLAN_ERROR_DATA_TX_FAIL,
+ MLAN_ERROR_DATA_RX_FAIL,
+ /** Driver errors below (MSB=1) */
+ MLAN_ERROR_PKT_SIZE_INVALID = 0x80000001,
+ MLAN_ERROR_PKT_TIMEOUT,
+ MLAN_ERROR_PKT_INVALID,
+ MLAN_ERROR_CMD_INVALID,
+ MLAN_ERROR_CMD_TIMEOUT,
+ MLAN_ERROR_CMD_DNLD_FAIL,
+ MLAN_ERROR_CMD_CANCEL,
+ MLAN_ERROR_CMD_RESP_FAIL,
+ MLAN_ERROR_CMD_ASSOC_FAIL,
+ MLAN_ERROR_CMD_SCAN_FAIL,
+ MLAN_ERROR_IOCTL_INVALID,
+ MLAN_ERROR_IOCTL_FAIL,
+ MLAN_ERROR_EVENT_UNKNOWN,
+ MLAN_ERROR_INVALID_PARAMETER,
+ MLAN_ERROR_NO_MEM,
+ /** 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_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,
+ MLAN_EVENT_ID_FW_ADHOC_LINK_LOST,
+ MLAN_EVENT_ID_FW_DISCONNECTED,
+ MLAN_EVENT_ID_FW_MIC_ERR_UNI,
+ MLAN_EVENT_ID_FW_MIC_ERR_MUL,
+ MLAN_EVENT_ID_FW_BCN_RSSI_LOW,
+ MLAN_EVENT_ID_FW_BCN_RSSI_HIGH,
+ MLAN_EVENT_ID_FW_BCN_SNR_LOW,
+ MLAN_EVENT_ID_FW_BCN_SNR_HIGH,
+ MLAN_EVENT_ID_FW_MAX_FAIL,
+ MLAN_EVENT_ID_FW_DATA_RSSI_LOW,
+ MLAN_EVENT_ID_FW_DATA_RSSI_HIGH,
+ MLAN_EVENT_ID_FW_DATA_SNR_LOW,
+ MLAN_EVENT_ID_FW_DATA_SNR_HIGH,
+ MLAN_EVENT_ID_FW_LINK_QUALITY,
+ MLAN_EVENT_ID_FW_PORT_RELEASE,
+ MLAN_EVENT_ID_FW_PRE_BCN_LOST,
+ MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE,
+ MLAN_EVENT_ID_FW_HS_WAKEUP,
+ MLAN_EVENT_ID_FW_BG_SCAN,
+ MLAN_EVENT_ID_FW_WEP_ICV_ERR,
+ MLAN_EVENT_ID_FW_STOP_TX,
+ MLAN_EVENT_ID_FW_START_TX,
+ MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN,
+ MLAN_EVENT_ID_FW_RADAR_DETECTED,
+ MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY,
+ MLAN_EVENT_ID_FW_BW_CHANGED,
+#ifdef WIFI_DIRECT_SUPPORT
+ MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED,
+#endif
+#ifdef UAP_SUPPORT
+ MLAN_EVENT_ID_UAP_FW_BSS_START,
+ MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE,
+ MLAN_EVENT_ID_UAP_FW_BSS_IDLE,
+ MLAN_EVENT_ID_UAP_FW_STA_CONNECT,
+ MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT,
+#endif
+
+ /* Event generated by MLAN driver (MSB=1) */
+ MLAN_EVENT_ID_DRV_CONNECTED = 0x80000001,
+ MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+ MLAN_EVENT_ID_DRV_HS_ACTIVATED,
+ MLAN_EVENT_ID_DRV_HS_DEACTIVATED,
+ MLAN_EVENT_ID_DRV_MGMT_FRAME,
+ MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM,
+ MLAN_EVENT_ID_DRV_PASSTHRU,
+ MLAN_EVENT_ID_DRV_SCAN_REPORT,
+ MLAN_EVENT_ID_DRV_MEAS_REPORT,
+ MLAN_EVENT_ID_DRV_REPORT_STRING,
+ MLAN_EVENT_ID_DRV_DBG_DUMP,
+} 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;
+} mlan_fw_image, *pmlan_fw_image;
+
+/** Custom data structure */
+typedef struct _mlan_init_param
+{
+ /** 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;
+
+/** 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[1];
+} mlan_event, *pmlan_event;
+
+/** 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;
+
+/** mlan_ioctl_req data structure */
+typedef struct _mlan_ioctl_req
+{
+ /** 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;
+
+ /** 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_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;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+#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 per BSS */
+#define MAX_MGMT_IE_INDEX 16
+
+/** 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];
+ /** Max mgmt IE TLV */
+ tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+#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_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_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 t_s8 * 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);
+} mlan_callbacks, *pmlan_callbacks;
+
+/** Interrupt Mode SDIO */
+#define INT_MODE_SDIO 0
+/** Interrupt Mode GPIO */
+#define INT_MODE_GPIO 1
+
+/** 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
+#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;
+#if defined(STA_SUPPORT)
+ /** 802.11d configuration */
+ t_u32 cfg_11d;
+#endif
+} 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);
+
+/** 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 t_void mlan_interrupt(IN t_void * pmlan_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/drivers/net/wireless/sd8797/mlan/mlan_fw.h b/drivers/net/wireless/sd8797/mlan/mlan_fw.h
new file mode 100644
index 000000000000..4b15b43711b5
--- /dev/null
+++ b/drivers/net/wireless/sd8797/mlan/mlan_fw.h
@@ -0,0 +1,4630 @@
+/** @file mlan_fw.h
+ *
+ * @brief This file contains firmware specific defines.
+ * structures and declares global function prototypes used
+ * in MLAN module.
+ *
+ * Copyright (C) 2008-2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You 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
+
+/** Ethernet header */
+typedef 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;
+
+} Eth803Hdr_t;
+
+/** RFC 1042 header */
+typedef 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;
+
+} Rfc1042Hdr_t;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** 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))
+
+/** 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) */
+#define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN)
+#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))
+#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 */
+#define GET_FW_DEFAULT_BANDS(_adapter) \
+ ((_adapter->fw_cap_info >> 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
+
+/** 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,
+ /** Key type : AES */
+ KEY_TYPE_ID_AES,
+ KEY_TYPE_ID_WAPI,
+} KEY_TYPE_ID;
+
+/** 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;
+
+/** WPA AES key length */
+#define WPA_AES_KEY_LEN 16
+/** WPA TKIP key length */
+#define WPA_TKIP_KEY_LEN 32
+
+/** WAPI key length */
+#define WAPI_KEY_LEN 50
+/** KEY_INFO_WAPI*/
+typedef enum _KEY_INFO_WAPI
+{
+ KEY_INFO_WAPI_MCAST = 0x01,
+ KEY_INFO_WAPI_UNICAST = 0x02,
+ KEY_INFO_WAPI_ENABLED = 0x04
+} KEY_INFO_WAPI;
+
+/** Maximum ethernet frame length sans FCS */
+#define MV_ETH_FRAME_LEN 1514
+
+/** 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 1000
+
+/** 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
+
+/** TLV type : Vendor Specific IE */
+#define TLV_TYPE_VENDOR_SPECIFIC_IE 0xdd
+
+/** 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 : 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 : 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 type : RXBA_SYNC */
+#define TLV_TYPE_RXBA_SYNC (PROPRIETARY_TLV_BASE_ID + 0x99) // 0x0199
+/** 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
+
+/** Test if 11n is enabled by checking the HTCap IE */
+#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN ||priv->adapter->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
+/** 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)
+/** 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)
+/** Default 11n capability mask for 5GHz */
+#define DEFAULT_11N_CAP_MASK_A (HWSPEC_CHANBW40_SUPP | HWSPEC_SHORTGI20_SUPP | \
+ HWSPEC_SHORTGI40_SUPP | HWSPEC_RXSTBC_SUPP)
+/** 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 : 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 : 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))
+/** 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))
+
+/** 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 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)))
+/** RadioType : Set secondary channel */
+#define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4))
+
+/** LLC/SNAP header len */
+#define LLC_SNAP_LEN 8
+
+/** 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
+/** HT bandwidth 20 MHz */
+#define HT_BW_20 0
+/** HT bandwidth 40 MHz */
+#define HT_BW_40 1
+
+/** 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
+
+/** 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 : 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 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 : 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 : 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: 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 : 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
+
+#endif /* UAP_SUPPORT */
+
+/** Host Command ID: Tx data pause */
+#define HostCmd_CMD_CFG_TX_DATA_PAUSE 0x0103
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** Host Command ID: WIFI_DIRECT_MODE_CONFIG */
+#define HOST_CMD_WIFI_DIRECT_MODE_CONFIG 0x00eb
+/** Host Command ID: Remain On Channel */
+#define HostCmd_CMD_802_11_REMAIN_ON_CHANNEL 0x010d
+#endif
+
+/** 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
+
+/** 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
+
+/* 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
+
+/* Radio type definitions for the channel TLV */
+/** Radio type BG */
+#define HostCmd_SCAN_RADIO_TYPE_BG 0
+/** Radio type A */
+#define HostCmd_SCAN_RADIO_TYPE_A 1
+
+/** 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 20
+/** Size of command buffer */
+#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
+
+/** Maximum number of BSS Descriptors */
+#define MRVDRV_MAX_BSSID_LIST 64
+
+/** Host command flag in command */
+#define CMD_F_HOSTCMD (1 << 0)
+/** command cancel flag in command */
+#define CMD_F_CANCELED (1 << 1)
+
+/** 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 : 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
+
+/** 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
+/** Remain on Channel expired event */
+#define EVENT_REMAIN_ON_CHANNEL_EXPIRED 0x0000005f
+#endif
+
+/** 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: 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 mask */
+#define EVENT_ID_MASK 0xffff
+
+/** BSS number mask */
+#define BSS_NUM_MASK 0xf
+
+/** Get BSS number from event cause (bit 23:16) */
+#define EVENT_GET_BSS_NUM(event_cause) \
+ (((event_cause) >> 16) & BSS_NUM_MASK)
+
+/** Get BSS type from event cause (bit 31:24) */
+#define EVENT_GET_BSS_TYPE(event_cause) \
+ (((event_cause) >> 24) & 0x00ff)
+
+/** Event_WEP_ICV_ERR structure */
+typedef MLAN_PACK_START struct _Event_WEP_ICV_ERR
+{
+ /** Reason code */
+ t_u16 reason_code;
+ /** Source MAC address */
+ t_u8 src_mac_addr[MLAN_MAC_ADDR_LENGTH];
+ /** WEP decryption used key */
+ t_u8 wep_key_index;
+ /** WEP key length */
+ t_u8 wep_key_length;
+ /** WEP key */
+ t_u8 key[MAX_WEP_KEY_SIZE];
+} MLAN_PACK_END Event_WEP_ICV_ERR;
+
+/** WLAN_802_11_FIXED_IEs */
+typedef MLAN_PACK_START struct _WLAN_802_11_FIXED_IEs
+{
+ /** Timestamp */
+ t_u8 time_stamp[8];
+ /** Beacon interval */
+ t_u16 beacon_interval;
+ /** Capabilities*/
+ t_u16 capabilities;
+} MLAN_PACK_END WLAN_802_11_FIXED_IEs;
+
+/** WLAN_802_11_VARIABLE_IEs */
+typedef MLAN_PACK_START struct _WLAN_802_11_VARIABLE_IEs
+{
+ /** Element ID */
+ t_u8 element_id;
+ /** Length */
+ t_u8 length;
+ /** IE data */
+ t_u8 data[1];
+} MLAN_PACK_END WLAN_802_11_VARIABLE_IEs;
+
+/** TLV related data structures*/
+/** 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;
+
+/** 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
+
+/** 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
+
+/** 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 reserved1;
+} 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;
+ /** Ht Info [Bit 0] RxRate format: LG=0, HT=1
+ * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1
+ * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */
+ t_u8 ht_info;
+ /** Reserved */
+ t_u8 reserved;
+} MLAN_PACK_END RxPD, *PRxPD;
+
+#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 reserved1;
+ /** Reserved */
+ t_u32 reserved;
+} 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 number */
+ t_u16 seq_num;
+ /** Packet Priority */
+ t_u8 priority;
+ /** reserved */
+ t_u8 reserved1;
+} MLAN_PACK_END UapRxPD, *PUapRxPD;
+
+/** Fixed size of station association event */
+#define ASSOC_EVENT_FIX_SIZE 12
+
+/** 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;
+
+/** 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_2_7:6;
+ /** 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;
+ /** Reserved */
+ t_u8 reserved_2_7:6;
+#endif
+} MLAN_PACK_END ChanScanMode_t;
+
+/** secondary channel is below */
+#define SECOND_CHANNEL_BELOW 0x30
+/** secondary channel is above */
+#define SECOND_CHANNEL_ABOVE 0x10
+/** channel offset */
+enum
+{
+ SEC_CHAN_NONE = 0,
+ SEC_CHAN_ABOVE = 1,
+ SEC_CHAN_BELOW = 3
+};
+/** channel bandwidth */
+enum
+{
+ CHAN_BW_20MHZ = 0,
+ CHAN_BW_10MHZ,
+ CHAN_BW_40MHZ,
+};
+/** ChanScanParamSet_t */
+typedef MLAN_PACK_START struct _ChanScanParamSet_t
+{
+ /** Channel scan parameter : Radio type */
+ t_u8 radio_type;
+ /** 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 : Radio type */
+ t_u8 radio_type;
+ /** 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_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_ActionFrame_t */
+typedef MLAN_PACK_START struct
+{
+ MrvlIEtypesHeader_t header; /**< Header */
+
+ t_u8 srcAddr[MLAN_MAC_ADDR_LENGTH];
+ t_u8 dstAddr[MLAN_MAC_ADDR_LENGTH];
+
+ IEEEtypes_ActionFrame_t actionFrame;
+
+} MLAN_PACK_END MrvlIETypes_ActionFrame_t;
+
+/** MrvlIEtypes_RxBaSync_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RxBaSync_t
+{
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** mac address */
+ t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+ /** tid */
+ t_u8 tid;
+ /** reserved field */
+ t_u8 reserved;
+ /** start seq num */
+ t_u16 seq_num;
+ /** bitmap len */
+ t_u16 bitmap_len;
+ /** bitmap */
+ t_u8 bitmap[1];
+} MLAN_PACK_END MrvlIEtypes_RxBaSync_t;
+
+/** MrvlIEtypes_RsnParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RsnParamSet_t
+{
+ /** Header */
+ MrvlIEtypesHeader_t header;
+ /** RSN IE */
+ t_u8 rsn_ie[1];
+} MLAN_PACK_END MrvlIEtypes_RsnParamSet_t;
+
+/** Key_param_set fixed length */
+#define KEYPARAMSET_FIXED_LEN 6
+
+/** MrvlIEtype_KeyParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtype_KeyParamSet_t
+{
+ /** Type ID */
+ t_u16 type;
+ /** Length of Payload */
+ t_u16 length;
+ /** Type of Key: WEP=0, TKIP=1, AES=2 */
+ t_u16 key_type_id;
+ /** Key Control Info specific to a key_type_id */
+ t_u16 key_info;
+ /** Length of key */
+ t_u16 key_len;
+ /** Key material of size key_len */
+ t_u8 key[50];
+} MLAN_PACK_END MrvlIEtype_KeyParamSet_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_KeyParamSet_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;
+
+/* 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 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;
+} ps_param;
+
+/** Structure definition for the new auto deep sleep command */
+typedef struct __auto_ds_param
+{
+ /** Deep sleep inactivity timeout */
+ t_u16 deep_sleep_timeout;
+} auto_ds_param;
+
+/** Structure definition for sleep confirmation in the new ps command */
+typedef struct __sleep_confirm_param
+{
+ /** response control 0x00 - response not needed, 0x01 - response needed */
+ t_u16 resp_ctrl;
+} 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 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 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 */
+} 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
+
+/** 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;
+
+/** 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;
+
+/** 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;
+} 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 */
+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_u16 action;
+ /** Reserved field */
+ t_u16 reserved;
+} 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];
+} 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;
+ /** Ht Info [Bit 0] RxRate format: LG=0, HT=1
+ * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1
+ * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */
+ t_u8 ht_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;
+
+/** 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,
+} 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];
+} MLAN_PACK_END MrvlRateScope_t;
+
+/** MrvlRateDropControl_t */
+typedef MLAN_PACK_START struct _MrvlRateDropControl_t
+{
+ /** Header Length */
+ t_u16 length;
+ /** Rate Information */
+ t_u32 rate_info[1];
+} MLAN_PACK_END MrvlRateDropControl_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;
+ /** Tx Rate Configuration Index */
+ t_u16 cfg_index;
+ /* 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_u16 current_level;
+ /** Maximum power */
+ t_u8 max_power;
+ /** Minimum power */
+ t_u8 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_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 */
+ t_u8 bandcfg;
+ /** channel */
+ t_u8 channel;
+ /** remain time: Unit ms*/
+ t_u32 remain_period;
+} MLAN_PACK_END HostCmd_DS_REMAIN_ON_CHANNEL;
+
+/** 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;
+#endif
+
+#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;
+
+/*
+ * 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
+{
+ /** Reserved */
+ t_u32 reserved;
+ /** 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;
+ */
+} MLAN_PACK_END HostCmd_DS_802_11_SCAN_EXT;
+
+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 */
+ t_u8 band;
+ /** 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_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_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_ECL_SYSTEM_CLOCK_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG
+{
+ /** Action */
+ t_u16 action;