qcacmn: Moving spectral module to cmn_dev

As part of second phase of Spectral Analysis(SA)
convergence [WIN & MCL], spectral module code is being moved to cmn_dev.
Also includes fixes for checkpatch.

CRs-Fixed: 2146231
Change-Id: I939509193786b0bd2cbd5f1af64d4a94739a2af5
diff --git a/spectral/Kbuild b/spectral/Kbuild
new file mode 100644
index 0000000..eac23f4
--- /dev/null
+++ b/spectral/Kbuild
@@ -0,0 +1,205 @@
+ifeq ($(obj),)
+obj := .
+endif
+
+DEPTH := ../..
+
+ifeq ($(strip ${QCA_PARTNER_MAKE_F_SUPPORT}),1)
+export QCA_PARTNER_MAKE_F_INC=1
+endif
+
+include $(obj)/$(DEPTH)/os/linux/Makefile-linux.common
+
+INCS += -I$(HAL) -I$(HAL)/$(OS) -I$(ATH) -I$(ATH_RATE) -I$(ATH_PKTLOG) -I$(WLAN) -I$(IF_WLAN) -I$(ATH_SPECTRAL) -I$(ATHEROSPATH) -I$(obj)/$(DEPTH)/../../apps/spectral/common
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/inc -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/obj_mgr/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/cmn_defs/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/scan/dispatcher/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/cmn_defs/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/global_umac_dispatcher/lmac_if/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/scheduler/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/global_lmac_if/inc
+INCS += -I$(obj)/$(DEPTH)/umac/scan
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/mgmt_txrx/dispatcher/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/regulatory/dispatcher/inc
+INCS += -I$(obj)/$(DEPTH)/umac/son/dispatcher/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/dfs/dispatcher/inc
+
+ifeq ($(WLAN_CONV_CRYPTO_SUPPORTED), 1)
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/crypto/inc
+endif
+
+#Start of offload related deifines
+HOST_CMN_CONVG_SRC := $(DEPTH)/cmn_dev
+HOST_CMN_CONVG_HIF_SRC := $(DEPTH)/cmn_dev/hif/src
+HOST_CMN_CONVG_HIF_INC1 := $(DEPTH)/cmn_dev/hif
+HOST_CMN_CONVG_HTC_INC := $(DEPTH)/cmn_dev/htc
+HOST_CMN_CONVG_DP_INC := $(DEPTH)/cmn_dev/dp/wifi3.0
+HOST_CMN_CONVG_CFG_INC := $(DEPTH)/cmn_dev/wlan_cfg
+HOST_CMN_CONVG_HAL_INC := $(DEPTH)/cmn_dev/hal/inc
+HOST_CMN_CONVG_HAL_WIFI_INC := $(DEPTH)/cmn_dev/hal/wifi3.0
+
+INCS += -I$(obj)/$(DEPTH)/include -I$(obj)/$(DEPTH)/umac/include \
+        -I$(obj)/$(DEPTH)/umac/if_lmac -I$(obj)/$(DEPTH)/umac/crypto \
+        -I$(obj)/$(DEPTH)/umac/scan -I$(obj)/$(DEPTH)/umac/resmgr \
+        -I$(obj)/$(DEPTH)/umac/pm -I$(obj)/$(DEPTH)/umac/txrx \
+        -I$(obj)/$(DEPTH)/umac/acs -I$(obj)/$(DEPTH)/umac/txbf \
+        -I$(obj)/$(DEPTH)/umac/wnm \
+        -I$(obj)/$(DEPTH)/umac/tdls \
+        -I$(obj)/$(DEPTH)/umac/rpt_placement \
+        -I$(obj)/$(DEPTH)/umac/wifipos \
+        -I$(obj)/$(DEPTH)/umac/wds -I$(obj)/$(DEPTH)/umac/ique \
+        -I$(obj)/$(DEPTH)/hal -I$(obj)/$(DEPTH)/lmac/ath_dev \
+        -I$(obj)/$(DEPTH)/hal/$(OS) \
+        -I$(obj)/$(DEPTH)/umac/vi_dbg \
+        -I$(obj)/$(DEPTH)/umac/smart_antenna \
+        -I$(obj)/$(DEPTH)/umac/smart_ant \
+        -I$(obj)/$(DEPTH)/umac/ald \
+        -I$(obj)/$(DEPTH)/lmac/ath_pktlog \
+        -I$(obj)/$(DEPTH)/lmac/ratectrl \
+        -I$(obj)/$(DEPTH)/os/linux/mem/ \
+        -I$(obj)/$(DEPTH)/umac/base \
+        -I$(obj)/$(DEPTH)/qca_ol \
+        -I$(obj)/$(DEPTH)/cmn_dev/qdf/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/qdf/linux/src \
+        -I$(obj)/$(DEPTH)/cmn_dev/hif \
+        -I$(obj)/$(DEPTH)/cmn_dev/hif/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/hif/src \
+        -I$(obj)/$(DEPTH)/cmn_dev/hif/src/ce \
+        -I$(obj)/$(DEPTH)/cmn_dev/hif/src/pcie \
+        -I$(obj)/$(DEPTH)/cmn_dev/hif/src/snoc \
+        -I$(obj)/$(DEPTH)/cmn_dev/hif/src/dispatcher \
+        -I$(obj)/$(DEPTH)/cmn_dev/pld_stub/inc  \
+        -I$(obj)/$(DEPTH)/cmn_dev/hal/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/hal/wifi3.0 \
+        -I$(obj)/$(DEPTH)/cmn_dev/dp/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/dp/wifi3.0 \
+        -I$(obj)/$(DEPTH)/cmn_dev/wlan_cfg \
+        -I$(obj)/$(HOST_CMN_CONVG_SRC)/htc \
+        -I$(obj)/$(DEPTH)/cmn_dev/wmi/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/obj_mgr/inc \
+        -I$(obj)/$(HOST_CMN_CONVG_SRC)/scheduler/inc \
+        -I$(obj)/$(HOST_CMN_CONVG_SRC)/init_deinit/dispatcher/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/umac/global_umac_dispatcher/lmac_if/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/mgmt_txrx/dispatcher/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/target_if/init_deinit/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/global_lmac_if/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/os_if/linux \
+        -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/cmn_defs/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/target_if/core/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/umac/scan/dispatcher/inc \
+        -I$(obj)/$(DEPTH)/umac/scan \
+        -I$(obj)/$(DEPTH)/cmn_dev/ol_if \
+        -I$(obj)/$(DEPTH)/cmn_dev/target_if/scan/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/serialization/core/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/umac/regulatory/dispatcher/inc \
+        -I$(obj)/$(DEPTH)/cmn_dev/target_if/regulatory/inc \
+
+PERF_PWR_OFFLOAD_INC += -I$(PERF_PWR_OFFLOAD_DIR_PATH)/wlan/include \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/wlan/ath_pktlog/include \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/htt/include \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/wlan/txrx/include \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/include \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/include \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/hif/pci \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/hif/pci/linux   \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/os/linux/include \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/wlan/regdmn \
+ -I$(PERF_PWR_OFFLOAD_DIR_PATH)/wlan/lmac_offload_if \
+ -I$(HOST_CMN_CONVG_HIF_INC1)/inc \
+ -I$(HOST_CMN_CONVG_HIF_INC1)/src \
+ -I$(HOST_CMN_CONVG_HIF_INC1)/src/pcie \
+ -I$(HOST_CMN_CONVG_HIF_INC1)/src/snoc \
+ -I$(HOST_CMN_CONVG_SRC)/pld_stub/inc \
+ -I$(HOST_CMN_CONVG_HIF_SRC)/ce \
+ -I$(HOST_CMN_CONVG_HTC_INC) \
+ -I$(HOST_CMN_CONVG_CFG_INC) \
+ -I$(HOST_CMN_CONVG_DP_INC) \
+ -I$(HOST_CMN_CONVG_HAL_INC) \
+ -I$(HOST_CMN_CONVG_HAL_WIFI_INC) \
+ -I$(PERF_PWR_OFFLOAD_WMI_SRC)/inc \
+ -I$(obj)/$(DEPTH)/offload/extra_include
+
+INCS += $(PERF_PWR_OFFLOAD_INC)
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/target_if/spectral
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/wmi/inc
+INCS += -I$(PERF_PWR_OFFLOAD_DIR_PATH)/hw/include
+#end of offload related defines
+
+#Start of Legacy spectral related defines
+INCS += -I$(HAL) -I$(HAL)/$(OS) -I$(ATH) -I$(ATH_RATE) -I$(ATH_PKTLOG) -I$(WLAN) -I$(IF_WLAN) -I$(ATH_SPECTRAL) -I$(ATHEROSPATH) -I$(obj)/$(DEPTH)/../../apps/spectral/common
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/inc -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/obj_mgr/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/cmn_defs/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/scan/dispatcher/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/cmn_defs/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/global_umac_dispatcher/lmac_if/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/scheduler/inc
+INCS += -I$(obj)/$(DEPTH)/umac/scan
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/mgmt_txrx/dispatcher/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/regulatory/dispatcher/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/dfs/dispatcher/inc
+
+SPECTRAL_DA_OBJS := $(DEPTH)/lmac/spectral/spectral.o \
+                    $(DEPTH)/lmac/spectral/spectral_netlink.o \
+                    $(DEPTH)/lmac/spectral/spectral_cmds.o \
+                    $(DEPTH)/lmac/spectral/spectral_process_data.o \
+                    $(DEPTH)/lmac/spectral/spectral_phyerr.o
+#End of legacy spectral defines
+
+ifeq ($(QCA_AIRTIME_FAIRNESS), 1)
+ccflags-y+= -DWLAN_ATF_ENABLE
+INCS += -I$(obj)/$(DEPTH)/umac/airtime_fairness/dispatcher/inc
+endif
+
+ifeq ($(UNIFIED_SMARTANTENNA), 1)
+ccflags-y+= -DWLAN_SA_API_ENABLE
+INCS += -I$(obj)/$(DEPTH)/umac/sa_api/dispatcher/inc
+endif
+
+ifeq ($(strip ${QCA_DFS_COMPONENT_ENABLE}),1)
+ccflags-y+= -DDFS_COMPONENT_ENABLE
+endif
+
+obj-m += qca_spectral.o
+
+ccflags-y+= $(INCS) $(COPTS) -DSPECTRAL_USE_NETLINK_SOCKETS=1 -DWLAN_SPECTRAL_ENABLE=1
+
+ifeq ($(strip ${QCA_PARTNER_MAKE_F_SUPPORT}),1)
+MOD_CFLAGS = -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(qca_spectral.mod)"  -D"KBUILD_MODNAME=KBUILD_STR(qca_spectral)"
+endif
+
+INCS += -I$(obj)/$(DEPTH)/spectral/dispatcher/inc
+
+SPECTRAL_TIF_OBJS +=  $(DEPTH)/cmn_dev/target_if/spectral/target_if_spectral.o \
+                      $(DEPTH)/cmn_dev/target_if/spectral/target_if_spectral_netlink.o \
+                      $(DEPTH)/cmn_dev/target_if/spectral/target_if_spectral_phyerr.o \
+                      $(DEPTH)/cmn_dev/target_if/spectral/target_if_spectral_sim.o
+
+SPECTRAL_CMN_OBJS +=  core/spectral_direct_attach.o \
+                      core/spectral_offload.o \
+                      core/spectral_common.o \
+                      dispatcher/src/wlan_spectral_utils_api.o \
+                      dispatcher/src/wlan_spectral_ucfg_api.o \
+                      dispatcher/src/wlan_spectral_tgt_api.o \
+                      core/spectral_module.o
+
+qca_spectral-objs +=  ${SPECTRAL_CMN_OBJS} \
+                      ${SPECTRAL_TIF_OBJS} \
+                      ${SPECTRAL_DA_OBJS}
+
+ifeq ($(strip ${QCA_PARTNER_MAKE_F_SUPPORT}),1)
+all: qca_spectral.ko
+
+qca_spectral.mod.o: qca_spectral.mod.c
+	${CC} -c -o $@ ${ccflags-y} ${MOD_CFLAGS} $<
+
+qca_spectral.o: ${qca_spectral-objs}
+	$(LD) -m elf32btsmip -r -o qca_spectral.o $(qca_spectral-objs)
+	$(KERNELPATH)/scripts/mod/modpost qca_spectral.o
+
+qca_spectral.ko: qca_spectral.o qca_spectral.mod.o
+	$(LD) $(LDOPTS) -o qca_spectral.ko qca_spectral.o qca_spectral.mod.o
+
+%.o: %.c
+	${CC} -c -o $@ ${ccflags-y} $<
+endif
diff --git a/spectral/core/spectral_cmn_api_i.h b/spectral/core/spectral_cmn_api_i.h
new file mode 100644
index 0000000..4436c0d
--- /dev/null
+++ b/spectral/core/spectral_cmn_api_i.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SPECTRAL_CMN_API_I_H_
+#define _SPECTRAL_CMN_API_I_H_
+
+#include "spectral_defs_i.h"
+
+/**
+ * wlan_spectral_psoc_obj_create_handler(): handler for psoc object create
+ * @psoc: reference to global psoc object
+ * @arg:  reference to argument provided during registration of handler
+ *
+ * This is a handler to indicate psoc object created. Hence spectral_context
+ * object can be created and attached to psoc component list.
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ *         QDF_STATUS_E_FAILURE if psoc is null
+ *         QDF_STATUS_E_NOMEM on failure of spectral object allocation
+ */
+QDF_STATUS wlan_spectral_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc,
+							void *arg);
+
+/**
+ * wlan_spectral_psoc_obj_destroy_handler(): handler for psoc object delete
+ * @psoc: reference to global psoc object
+ * @arg:  reference to argument provided during registration of handler
+ *
+ * This is a handler to indicate psoc object going to be deleted.
+ * Hence spectral_context object can be detached from psoc component list.
+ * Then spectral_context object can be deleted.
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ *         QDF_STATUS_E_FAILURE on failure
+ */
+QDF_STATUS wlan_spectral_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc,
+						  void *arg);
+
+/**
+ * wlan_spectral_pdev_obj_create_handler(): handler for pdev object create
+ * @pdev: reference to global pdev object
+ * @arg:  reference to argument provided during registration of handler
+ *
+ * This is a handler to indicate pdev object created. Hence pdev specific
+ * spectral object can be created and attached to pdev component list.
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ *         QDF_STATUS_E_FAILURE if pdev is null
+ *         QDF_STATUS_E_NOMEM on failure of spectral object allocation
+ */
+QDF_STATUS wlan_spectral_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev,
+						 void *arg);
+
+/**
+ * wlan_spectral_pdev_obj_destroy_handler(): handler for pdev object delete
+ * @pdev: reference to global pdev object
+ * @arg:  reference to argument provided during registration of handler
+ *
+ * This is a handler to indicate pdev object going to be deleted.
+ * Hence pdev specific spectral object can be detached from pdev component list.
+ * Then pdev_spectral object can be deleted.
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ *         QDF_STATUS_E_FAILURE on failure
+ */
+QDF_STATUS wlan_spectral_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev,
+						  void *arg);
+
+/**
+ * spectral_control_cmn(): common handler for demultiplexing requests from
+ *                         higher layer
+ * @pdev:    reference to global pdev object
+ * @id:      spectral config command id
+ * @indata:  reference to input data
+ * @insize:  input data size
+ * @outdata: reference to output data
+ * @outsize: reference to output data size
+ *
+ * This function processes the spectral config command
+ * and appropriate handlers are invoked.
+ *
+ * Return: 0 success else failure
+ */
+int spectral_control_cmn(
+	struct wlan_objmgr_pdev *pdev,
+	u_int id,
+	void *indata,
+	u_int32_t insize,
+	void *outdata, u_int32_t *outsize);
+
+/**
+ * spectral_get_spectral_ctx_from_pdev() - API to get spectral context object
+ *                                         from pdev
+ * @pdev : Reference to pdev global object
+ *
+ * This API used to get spectral context object from global pdev reference.
+ * Null check should be done before invoking this inline function.
+ *
+ * Return : Reference to spectral_context object
+ */
+static inline
+struct spectral_context *spectral_get_spectral_ctx_from_pdev(
+	struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+	struct spectral_context *sc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (psoc) {
+		sc = wlan_objmgr_psoc_get_comp_private_obj(
+			psoc,
+			WLAN_UMAC_COMP_SPECTRAL);
+	}
+
+	return sc;
+}
+
+#endif /* _SPECTRAL_CMN_API_I_H_*/
+
diff --git a/spectral/core/spectral_common.c b/spectral/core/spectral_common.c
new file mode 100644
index 0000000..c3e2303
--- /dev/null
+++ b/spectral/core/spectral_common.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "spectral_cmn_api_i.h"
+#include "spectral_da_api_i.h"
+#include "spectral_ol_api_i.h"
+#include <qdf_mem.h>
+#include <qdf_types.h>
+#include <osif_private.h>
+#include <wlan_spectral_public_structs.h>
+#include <wlan_mlme_dispatcher.h>
+
+/**
+ * spectral_get_vdev() - Get pointer to vdev to be used for Spectral
+ * operations
+ * @pdev: Pointer to pdev
+ *
+ * Spectral operates on pdev. However, in order to retrieve some WLAN
+ * properties, a vdev is required. To facilitate this, the function returns the
+ * first vdev in our pdev. The caller should release the reference to the vdev
+ * once it is done using it. Additionally, the caller should ensure it has a
+ * reference to the pdev at the time of calling this function, and should
+ * release the pdev reference either after this function returns or at a later
+ * time when the caller is done using pdev.
+ * TODO:
+ *  - If the framework later provides an API to obtain the first active
+ *    vdev, then it would be preferable to use this API.
+ *  - Use a common get_vdev() handler for core and target_if using Rx ops. This
+ *    is deferred till details emerge on framework providing API to get first
+ *    active vdev.
+ *
+ * Return: Pointer to vdev on success, NULL on failure
+ */
+struct wlan_objmgr_vdev*
+spectral_get_vdev(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	qdf_assert_always(pdev);
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 0, WLAN_SPECTRAL_ID);
+
+	if (!vdev) {
+		qdf_print("%s: Unable to get first vdev of pdev.\n", __func__);
+		return NULL;
+	}
+
+	return vdev;
+}
+
+int spectral_control_cmn(
+	struct wlan_objmgr_pdev *pdev,
+	 u_int id,
+	 void *indata,
+	 u_int32_t insize,
+			 void *outdata, u_int32_t *outsize)
+{
+	int error = 0;
+	int temp_debug;
+	struct spectral_config sp_out;
+	struct spectral_config *sp_in;
+	struct spectral_config *spectralparams;
+	struct spectral_context *sc;
+	struct wlan_objmgr_vdev *vdev = NULL;
+	u_int8_t vdev_rxchainmask = 0;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL!\n");
+		error = -EINVAL;
+		goto bad;
+	}
+	sc = spectral_get_spectral_ctx_from_pdev(pdev);
+	if (!sc) {
+		spectral_err("atf context is NULL!\n");
+		error = -EINVAL;
+		goto bad;
+	}
+
+	switch (id) {
+	case SPECTRAL_SET_CONFIG:
+	{
+		if (insize < sizeof(struct spectral_config) || !indata) {
+			error = -EINVAL;
+			break;
+		}
+		sp_in = (struct spectral_config *)indata;
+		if (sp_in->ss_count != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_SCAN_COUNT,
+				sp_in->ss_count))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_fft_period != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_FFT_PERIOD,
+				sp_in->ss_fft_period))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_period != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_SCAN_PERIOD,
+				sp_in->ss_period))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_short_report != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_SHORT_REPORT,
+				(u_int32_t)(sp_in->ss_short_report ? 1 : 0)))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_spectral_pri != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_SPECT_PRI,
+				(u_int32_t)(sp_in->ss_spectral_pri)))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_fft_size != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_FFT_SIZE,
+				sp_in->ss_fft_size))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_gc_ena != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_GC_ENA,
+				sp_in->ss_gc_ena))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_restart_ena != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_RESTART_ENA,
+				sp_in->ss_restart_ena))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_noise_floor_ref != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_NOISE_FLOOR_REF,
+				sp_in->ss_noise_floor_ref))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_init_delay != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_INIT_DELAY,
+				sp_in->ss_init_delay))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_nb_tone_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_NB_TONE_THR,
+				sp_in->ss_nb_tone_thr))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_str_bin_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_STR_BIN_THR,
+				sp_in->ss_str_bin_thr))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_wb_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_WB_RPT_MODE,
+				sp_in->ss_wb_rpt_mode))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_rssi_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_RSSI_RPT_MODE,
+				sp_in->ss_rssi_rpt_mode))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_rssi_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_RSSI_THR,
+				sp_in->ss_rssi_thr))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_pwr_format != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_PWR_FORMAT,
+				sp_in->ss_pwr_format))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_RPT_MODE,
+				sp_in->ss_rpt_mode))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_bin_scale != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_BIN_SCALE,
+				sp_in->ss_bin_scale))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_dBm_adj != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			if (!sc->sptrlc_set_spectral_config(
+				pdev,
+				SPECTRAL_PARAM_DBM_ADJ,
+				sp_in->ss_dBm_adj))
+				error = -EINVAL;
+		}
+
+		if (sp_in->ss_chn_mask != SPECTRAL_PHYERR_PARAM_NOVAL) {
+			/* Check if any of the inactive Rx antenna chains is
+			 * set active in
+			 * spectral chainmask
+			 */
+			vdev = spectral_get_vdev(pdev);
+			if (!vdev) {
+				error = -ENOENT;
+				break;
+			}
+
+			vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
+			wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+			if (!(sp_in->ss_chn_mask & vdev_rxchainmask)) {
+				qdf_print("Invalid Spectral Chainmask - "
+					  "Inactive Rx antenna chain cannot "
+					  "be an active spectral chain\n");
+				error = -EINVAL;
+				break;
+			} else if (!sc->sptrlc_set_spectral_config(pdev,
+				SPECTRAL_PARAM_CHN_MASK, sp_in->ss_chn_mask)) {
+				error = -EINVAL;
+			}
+		}
+	}
+	break;
+
+	case SPECTRAL_GET_CONFIG:
+	{
+		if (!outdata || !outsize || (*outsize < sizeof(
+			struct spectral_config))) {
+			error = -EINVAL;
+			break;
+		}
+		*outsize = sizeof(struct spectral_config);
+		sc->sptrlc_get_spectral_config(pdev, &sp_out);
+		spectralparams = (struct spectral_config *)outdata;
+		spectralparams->ss_fft_period      = sp_out.ss_fft_period;
+		spectralparams->ss_period          = sp_out.ss_period;
+		spectralparams->ss_count           = sp_out.ss_count;
+		spectralparams->ss_short_report    = sp_out.ss_short_report;
+		spectralparams->ss_spectral_pri    = sp_out.ss_spectral_pri;
+		spectralparams->ss_fft_size        = sp_out.ss_fft_size;
+		spectralparams->ss_gc_ena          = sp_out.ss_gc_ena;
+		spectralparams->ss_restart_ena     = sp_out.ss_restart_ena;
+		spectralparams->ss_noise_floor_ref = sp_out.ss_noise_floor_ref;
+		spectralparams->ss_init_delay      = sp_out.ss_init_delay;
+		spectralparams->ss_nb_tone_thr     = sp_out.ss_nb_tone_thr;
+		spectralparams->ss_str_bin_thr     = sp_out.ss_str_bin_thr;
+		spectralparams->ss_wb_rpt_mode     = sp_out.ss_wb_rpt_mode;
+		spectralparams->ss_rssi_rpt_mode   = sp_out.ss_rssi_rpt_mode;
+		spectralparams->ss_rssi_thr        = sp_out.ss_rssi_thr;
+		spectralparams->ss_pwr_format      = sp_out.ss_pwr_format;
+		spectralparams->ss_rpt_mode        = sp_out.ss_rpt_mode;
+		spectralparams->ss_bin_scale       = sp_out.ss_bin_scale;
+		spectralparams->ss_dBm_adj         = sp_out.ss_dBm_adj;
+		spectralparams->ss_chn_mask        = sp_out.ss_chn_mask;
+	}
+	break;
+
+	case SPECTRAL_IS_ACTIVE:
+	{
+		if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) {
+			error = -EINVAL;
+			break;
+		}
+		*outsize = sizeof(u_int32_t);
+		*((u_int32_t *)outdata) =
+			(u_int32_t)sc->sptrlc_is_spectral_active(pdev);
+	}
+	break;
+
+	case SPECTRAL_IS_ENABLED:
+	{
+		if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) {
+			error = -EINVAL;
+			break;
+		}
+		*outsize = sizeof(u_int32_t);
+		*((u_int32_t *)outdata) =
+			(u_int32_t)sc->sptrlc_is_spectral_enabled(pdev);
+	}
+	break;
+
+	case SPECTRAL_SET_DEBUG_LEVEL:
+	{
+		if (insize < sizeof(u_int32_t) || !indata) {
+			error = -EINVAL;
+			break;
+		}
+		temp_debug = *(u_int32_t *)indata;
+		sc->sptrlc_set_debug_level(pdev, temp_debug);
+	}
+	break;
+
+	case SPECTRAL_ACTIVATE_SCAN:
+	{
+		sc->sptrlc_start_spectral_scan(pdev);
+	}
+	break;
+
+	case SPECTRAL_STOP_SCAN:
+	{
+		sc->sptrlc_stop_spectral_scan(pdev);
+	}
+	break;
+
+	case SPECTRAL_GET_CAPABILITY_INFO:
+	{
+		if (!outdata || !outsize ||
+		    *outsize < sizeof(struct spectral_caps)) {
+			error = -EINVAL;
+			break;
+		}
+		*outsize = sizeof(struct spectral_caps);
+		sc->sptrlc_get_spectral_capinfo(pdev, outdata);
+	}
+	break;
+
+	case SPECTRAL_GET_DIAG_STATS:
+	{
+		if (!outdata || !outsize ||
+		    (*outsize < sizeof(struct spectral_diag_stats))) {
+		error = -EINVAL;
+		break;
+		}
+		*outsize = sizeof(struct spectral_diag_stats);
+		sc->sptrlc_get_spectral_diagstats(pdev, outdata);
+	}
+	break;
+
+	case SPECTRAL_GET_CHAN_WIDTH:
+	{
+		u_int32_t chan_width;
+
+		vdev = spectral_get_vdev(pdev);
+		if (!vdev)
+			return -ENOENT;
+
+		chan_width = wlan_vdev_get_ch_width(vdev);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+		if (!outdata || !outsize ||
+		    *outsize < sizeof(chan_width)) {
+			error = -EINVAL;
+			break;
+		}
+		*outsize = sizeof(chan_width);
+		*((u_int32_t *)outdata) = (u_int32_t)chan_width;
+	}
+	break;
+
+	default:
+	error = -EINVAL;
+	break;
+	}
+
+bad:
+	return error;
+}
+
+static void spectral_ctx_deinit(struct spectral_context *sc)
+{
+	if (sc) {
+		sc->sptrlc_ucfg_phyerr_config     = NULL;
+		sc->sptrlc_pdev_spectral_init     = NULL;
+		sc->sptrlc_pdev_spectral_deinit   = NULL;
+		sc->sptrlc_set_spectral_config    = NULL;
+		sc->sptrlc_get_spectral_config    = NULL;
+		sc->sptrlc_start_spectral_scan    = NULL;
+		sc->sptrlc_stop_spectral_scan     = NULL;
+		sc->sptrlc_is_spectral_active     = NULL;
+		sc->sptrlc_is_spectral_enabled    = NULL;
+		sc->sptrlc_set_debug_level        = NULL;
+		sc->sptrlc_get_debug_level        = NULL;
+		sc->sptrlc_get_spectral_capinfo   = NULL;
+		sc->sptrlc_get_spectral_diagstats = NULL;
+	}
+}
+
+QDF_STATUS
+wlan_spectral_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
+{
+	struct spectral_context *sc = NULL;
+
+	if (!psoc) {
+		spectral_err("PSOC is NULL\n");
+		return QDF_STATUS_E_FAILURE;
+	}
+	sc = (struct spectral_context *)qdf_mem_malloc(
+		sizeof(struct spectral_context));
+	if (!sc) {
+		spectral_err("Failed to allocate spectral_ctx object\n");
+		return QDF_STATUS_E_NOMEM;
+	}
+	qdf_mem_zero(sc, sizeof(struct spectral_context));
+	sc->psoc_obj = psoc;
+	if (wlan_objmgr_psoc_get_dev_type(psoc) == WLAN_DEV_DA)
+		spectral_ctx_init_da(sc);
+	else if (wlan_objmgr_psoc_get_dev_type(psoc) == WLAN_DEV_OL)
+		spectral_ctx_init_ol(sc);
+	wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_UMAC_COMP_SPECTRAL,
+					      (void *)sc, QDF_STATUS_SUCCESS);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_spectral_psoc_obj_destroy_handler(
+	struct wlan_objmgr_psoc *psoc,
+	 void *arg)
+{
+	struct spectral_context *sc = NULL;
+
+	if (!psoc) {
+		spectral_err("PSOC is NULL\n");
+		return QDF_STATUS_E_FAILURE;
+	}
+	sc = wlan_objmgr_psoc_get_comp_private_obj(
+		psoc,
+		 WLAN_UMAC_COMP_SPECTRAL);
+	if (sc) {
+		wlan_objmgr_psoc_component_obj_detach(
+			psoc,
+			 WLAN_UMAC_COMP_SPECTRAL,
+						      (void *)sc);
+		/* Deinitilise function pointers from spectral context */
+		spectral_ctx_deinit(sc);
+		qdf_mem_free(sc);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_spectral_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
+{
+	struct pdev_spectral *ps = NULL;
+	struct spectral_context *sc = NULL;
+	void *target_handle = NULL;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL\n");
+		return QDF_STATUS_E_FAILURE;
+	}
+	ps = (struct pdev_spectral *)qdf_mem_malloc(
+		sizeof(struct pdev_spectral));
+	if (!ps) {
+		spectral_err("Failed to allocate pdev_spectral object\n");
+		return QDF_STATUS_E_NOMEM;
+	}
+	sc = spectral_get_spectral_ctx_from_pdev(pdev);
+	if (!sc) {
+		spectral_err("Spectral context is NULL!\n");
+		goto cleanup;
+	}
+
+	qdf_mem_zero(ps, sizeof(struct pdev_spectral));
+	ps->psptrl_pdev = pdev;
+	if (sc->sptrlc_pdev_spectral_init) {
+		target_handle = sc->sptrlc_pdev_spectral_init(pdev);
+		if (!target_handle) {
+			spectral_err("Spectral lmac object is NULL!\n");
+			goto cleanup;
+		}
+		ps->psptrl_target_handle = target_handle;
+	}
+	wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_SPECTRAL,
+					      (void *)ps, QDF_STATUS_SUCCESS);
+
+	return QDF_STATUS_SUCCESS;
+cleanup:
+	qdf_mem_free(ps);
+	return QDF_STATUS_E_FAILURE;
+}
+
+QDF_STATUS
+wlan_spectral_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg)
+{
+	struct pdev_spectral *ps = NULL;
+	struct spectral_context *sc = NULL;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL\n");
+		return QDF_STATUS_E_FAILURE;
+	}
+	sc = spectral_get_spectral_ctx_from_pdev(pdev);
+	if (!sc) {
+		spectral_err("Spectral context is NULL!\n");
+		return QDF_STATUS_E_FAILURE;
+	}
+	ps = wlan_objmgr_pdev_get_comp_private_obj(
+		pdev,
+		 WLAN_UMAC_COMP_SPECTRAL);
+	if (ps) {
+		if (sc->sptrlc_pdev_spectral_deinit)
+			sc->sptrlc_pdev_spectral_deinit(pdev);
+		ps->psptrl_target_handle = NULL;
+		wlan_objmgr_pdev_component_obj_detach(
+			pdev,
+			 WLAN_UMAC_COMP_SPECTRAL,
+						      (void *)ps);
+		qdf_mem_free(ps);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
diff --git a/spectral/core/spectral_da_api_i.h b/spectral/core/spectral_da_api_i.h
new file mode 100644
index 0000000..c0dca87
--- /dev/null
+++ b/spectral/core/spectral_da_api_i.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SPECTRAL_DA_API_I_H_
+#define _SPECTRAL_DA_API_I_H_
+
+#include "spectral_defs_i.h"
+
+/**
+ * spectral_ctx_init_da() - Internal function to initialise spectral context
+ * with direct attach specific functions
+ * @sc : spectral context
+ *
+ * Return : void
+ */
+void spectral_ctx_init_da(struct spectral_context *sc);
+
+#endif /* _SPECTRAL_DA_API_I_H_ */
diff --git a/spectral/core/spectral_defs_i.h b/spectral/core/spectral_defs_i.h
new file mode 100644
index 0000000..6c6bd7b
--- /dev/null
+++ b/spectral/core/spectral_defs_i.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SPECTRAL_DEFS_I_H_
+#define _SPECTRAL_DEFS_I_H_
+
+#include <wlan_objmgr_cmn.h>
+#include <wlan_objmgr_global_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <qdf_list.h>
+#include <qdf_timer.h>
+#include <qdf_util.h>
+#include <wlan_spectral_public_structs.h>
+#include <if_athioctl.h>
+#include <spectral_ioctl.h>
+
+#define spectral_log(level, args...) \
+QDF_PRINT_INFO(QDF_PRINT_IDX_SHARED, QDF_MODULE_ID_SPECTRAL, level, ## args)
+
+#define spectral_logfl(level, format, args...) \
+	spectral_log(level, FL(format), ## args)
+
+#define spectral_fatal(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args)
+#define spectral_err(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_ERROR, format, ## args)
+#define spectral_warn(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_WARN, format, ## args)
+#define spectral_info(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_INFO, format, ## args)
+#define spectral_debug(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args)
+
+/**
+ * struct pdev_spectral - Radio specific spectral object
+ * @psptrl_pdev:          Back-pointer to struct wlan_objmgr_pdev
+ * @psptrl_nl_sock:       Spectral Netlink socket for sending samples to
+ *                        applications
+ * @psptrl_target_handle: reference to spectral lmac object
+ */
+struct pdev_spectral {
+	struct wlan_objmgr_pdev    *psptrl_pdev;
+	struct sock                *psptrl_nl_sock;
+	void                       *psptrl_target_handle;
+};
+
+/**
+ * struct spectral_context : spectral global context
+ *
+ * @psoc_obj:                      Reference to psoc global object
+ *
+ * Call back functions to invoke independent of OL/DA
+ * @sptrlc_ucfg_phyerr_config:     ucfg handler for phyerr
+ * @sptrlc_pdev_spectral_init:     Init spectral
+ * @sptrlc_pdev_spectral_deinit:   Deinit spectral
+ * @sptrlc_set_spectral_config:    Set spectral configurations
+ * @sptrlc_get_spectral_config:    Get spectral configurations
+ * @sptrlc_start_spectral_scan:    Start spectral scan
+ * @sptrlc_stop_spectral_scan:     Stop spectral scan
+ * @sptrlc_is_spectral_active:     Check if spectral scan is active
+ * @sptrlc_is_spectral_enabled:    Check if spectral is enabled
+ * @sptrlc_set_debug_level:        Set debug level
+ * @sptrlc_get_debug_level:        Get debug level
+ * @sptrlc_get_spectral_capinfo:   Get spectral capability info
+ * @sptrlc_get_spectral_diagstats: Get spectral diag status
+ */
+struct spectral_context {
+	struct wlan_objmgr_psoc *psoc_obj;
+	int (*sptrlc_spectral_control)(struct wlan_objmgr_pdev *pdev, u_int id,
+				       void *indata, u_int32_t insize,
+		void *outdata, u_int32_t *outsize);
+	int (*sptrlc_ucfg_phyerr_config)(struct wlan_objmgr_pdev *pdev,
+					 struct ath_diag *ad);
+	void * (*sptrlc_pdev_spectral_init)(struct wlan_objmgr_pdev *pdev);
+	void (*sptrlc_pdev_spectral_deinit)(struct wlan_objmgr_pdev *pdev);
+	int (*sptrlc_set_spectral_config)(
+		struct wlan_objmgr_pdev *pdev,
+		const u_int32_t threshtype, const u_int32_t value);
+	void (*sptrlc_get_spectral_config)(
+		struct wlan_objmgr_pdev *pdev,
+		struct spectral_config *sptrl_config);
+	int (*sptrlc_start_spectral_scan)(struct wlan_objmgr_pdev *pdev);
+	void (*sptrlc_stop_spectral_scan)(struct wlan_objmgr_pdev *pdev);
+	bool (*sptrlc_is_spectral_active)(struct wlan_objmgr_pdev *pdev);
+	bool (*sptrlc_is_spectral_enabled)(struct wlan_objmgr_pdev *pdev);
+	int (*sptrlc_set_debug_level)(struct wlan_objmgr_pdev *pdev,
+				      u_int32_t debug_level);
+	u_int32_t (*sptrlc_get_debug_level)(struct wlan_objmgr_pdev *pdev);
+	void (*sptrlc_get_spectral_capinfo)(struct wlan_objmgr_pdev *pdev,
+					    void *outdata);
+	void (*sptrlc_get_spectral_diagstats)(struct wlan_objmgr_pdev *pdev,
+					      void *outdata);
+};
+
+#endif /* _SPECTRAL_DEFS_I_H_ */
+
diff --git a/spectral/core/spectral_direct_attach.c b/spectral/core/spectral_direct_attach.c
new file mode 100644
index 0000000..58ab4d7
--- /dev/null
+++ b/spectral/core/spectral_direct_attach.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "spectral_cmn_api_i.h"
+
+int spectral_control_da(struct wlan_objmgr_pdev *pdev, u_int id, void *indata,
+			u_int32_t insize, void *outdata, u_int32_t *outsize)
+{
+	struct spectral_context *sc;
+	int error = 0;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL!\n");
+		return -EPERM;
+	}
+	sc = spectral_get_spectral_ctx_from_pdev(pdev);
+	if (!sc) {
+		spectral_err("spectral context is NULL!\n");
+		return -EPERM;
+	}
+	switch (id) {
+#if ATH_SUPPORT_RAW_ADC_CAPTURE
+	case SPECTRAL_ADC_ENABLE_TEST_ADDAC_MODE:
+		error = spectral_enter_raw_capture_mode(dev, indata);
+		break;
+	case SPECTRAL_ADC_DISABLE_TEST_ADDAC_MODE:
+		error = spectral_exit_raw_capture_mode(dev);
+		break;
+	case SPECTRAL_ADC_RETRIEVE_DATA:
+		error = spectral_retrieve_raw_capture(dev, outdata, outsize);
+		break;
+#endif
+	default:
+		error = spectral_control_cmn(
+			pdev,
+			 id,
+			 indata,
+			 insize,
+			 outdata,
+			 outsize);
+		break;
+	}
+	return error;
+}
+
+static void *pdev_spectral_init_da(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_pdev_spectral_init(
+		pdev);
+}
+
+static void pdev_spectral_deinit_da(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_pdev_spectral_deinit(pdev);
+}
+
+static int set_spectral_config_da(
+	struct wlan_objmgr_pdev *pdev,
+	const u_int32_t threshtype, const u_int32_t value)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_set_spectral_config(
+		pdev,
+		threshtype,
+		value);
+}
+
+static void get_spectral_config_da(struct wlan_objmgr_pdev *pdev,
+				   struct spectral_config *sptrl_config)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_get_spectral_config(pdev,
+			sptrl_config);
+}
+
+static int start_spectral_scan_da(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_start_spectral_scan(
+		pdev);
+}
+
+static void stop_spectral_scan_da(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_stop_spectral_scan(pdev);
+}
+
+static bool is_spectral_active_da(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_is_spectral_active(
+		pdev);
+}
+
+static bool is_spectral_enabled_da(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_is_spectral_enabled(
+		pdev);
+}
+
+static int set_debug_level_da(struct wlan_objmgr_pdev *pdev,
+			      u_int32_t debug_level)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_set_debug_level(pdev,
+			debug_level);
+}
+
+static u_int32_t get_debug_level_da(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_get_debug_level(pdev);
+}
+
+static void get_spectral_capinfo_da(struct wlan_objmgr_pdev *pdev,
+				    void *outdata)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_get_spectral_capinfo(
+		pdev,
+		 outdata);
+}
+
+static void get_spectral_diagstats_da(struct wlan_objmgr_pdev *pdev,
+				      void *outdata)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_get_spectral_diagstats(
+		pdev,
+		 outdata);
+}
+
+void spectral_ctx_init_da(struct spectral_context *sc)
+{
+	if (!sc) {
+		spectral_err("spectral context is null!\n");
+		return;
+	}
+	sc->sptrlc_spectral_control       = spectral_control_da;
+	sc->sptrlc_pdev_spectral_init     = pdev_spectral_init_da;
+	sc->sptrlc_pdev_spectral_deinit   = pdev_spectral_deinit_da;
+	sc->sptrlc_set_spectral_config    = set_spectral_config_da;
+	sc->sptrlc_get_spectral_config    = get_spectral_config_da;
+	sc->sptrlc_start_spectral_scan    = start_spectral_scan_da;
+	sc->sptrlc_stop_spectral_scan     = stop_spectral_scan_da;
+	sc->sptrlc_is_spectral_active     = is_spectral_active_da;
+	sc->sptrlc_is_spectral_enabled    = is_spectral_enabled_da;
+	sc->sptrlc_set_debug_level        = set_debug_level_da;
+	sc->sptrlc_get_debug_level        = get_debug_level_da;
+	sc->sptrlc_get_spectral_capinfo   = get_spectral_capinfo_da;
+	sc->sptrlc_get_spectral_diagstats = get_spectral_diagstats_da;
+}
+
diff --git a/spectral/core/spectral_module.c b/spectral/core/spectral_module.c
new file mode 100644
index 0000000..ce42e63
--- /dev/null
+++ b/spectral/core/spectral_module.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include<linux/module.h>
+#include <wlan_spectral_utils_api.h>
+#include <qdf_types.h>
+#include<wlan_global_lmac_if_api.h>
+
+/**
+ * spectral_init_module() - Initialize Spectral module
+ *
+ * Return: None
+ */
+static int __init
+spectral_init_module(void)
+{
+	qdf_print("qca_spectral module loaded\n");
+	wlan_spectral_init();
+	/* register spectral rxops*/
+	wlan_lmac_if_sptrl_set_rx_ops_register_cb(
+		wlan_lmac_if_sptrl_register_rx_ops);
+	return 0;
+}
+
+/**
+ * spectral_exit_module() - De-initialize and exit Spectral module
+ *
+ * Return: None
+ */
+static void __exit
+spectral_exit_module(void)
+{
+	wlan_spectral_deinit();
+	qdf_print("qca_spectral module unloaded\n");
+}
+
+module_init(spectral_init_module);
+module_exit(spectral_exit_module);
+
diff --git a/spectral/core/spectral_offload.c b/spectral/core/spectral_offload.c
new file mode 100644
index 0000000..b4a352a
--- /dev/null
+++ b/spectral/core/spectral_offload.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "spectral_cmn_api_i.h"
+
+int spectral_control_ol(
+	struct wlan_objmgr_pdev *pdev,
+	 u_int id,
+	 void *indata,
+	 u_int32_t insize,
+			void *outdata, u_int32_t *outsize)
+{
+	struct spectral_context *sc;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL!\n");
+		return -EPERM;
+	}
+	sc = spectral_get_spectral_ctx_from_pdev(pdev);
+	if (!sc) {
+		spectral_err("spectral context is NULL!\n");
+		return -EPERM;
+	}
+	return spectral_control_cmn(pdev, id, indata, insize, outdata, outsize);
+}
+
+static void *pdev_spectral_init_ol(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_pdev_spectral_init(
+		pdev);
+}
+
+static void pdev_spectral_deinit_ol(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_pdev_spectral_deinit(pdev);
+}
+
+static int set_spectral_config_ol(
+	struct wlan_objmgr_pdev *pdev,
+	const u_int32_t threshtype, const u_int32_t value)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_set_spectral_config(
+		pdev,
+			threshtype, value);
+}
+
+static void get_spectral_config_ol(struct wlan_objmgr_pdev *pdev,
+				   struct spectral_config *sptrl_config)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_get_spectral_config(pdev,
+			sptrl_config);
+}
+
+static int start_spectral_scan_ol(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_start_spectral_scan(
+		pdev);
+}
+
+static void stop_spectral_scan_ol(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_stop_spectral_scan(pdev);
+}
+
+static bool is_spectral_active_ol(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_is_spectral_active(
+		pdev);
+}
+
+static bool is_spectral_enabled_ol(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_is_spectral_enabled(
+		pdev);
+}
+
+static int  set_debug_level_ol(struct wlan_objmgr_pdev *pdev,
+			       u_int32_t debug_level)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_set_debug_level(pdev,
+			debug_level);
+}
+
+static u_int32_t get_debug_level_ol(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_get_debug_level(pdev);
+}
+
+static void get_spectral_capinfo_ol(struct wlan_objmgr_pdev *pdev,
+				    void *outdata)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_get_spectral_capinfo(
+		pdev,
+		 outdata);
+}
+
+static void get_spectral_diagstats_ol(struct wlan_objmgr_pdev *pdev,
+				      void *outdata)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_get_spectral_diagstats(
+		pdev,
+		 outdata);
+}
+
+void spectral_ctx_init_ol(struct spectral_context *sc)
+{
+	if (!sc) {
+		spectral_err("spectral context is null!\n");
+		return;
+	}
+	sc->sptrlc_spectral_control       = spectral_control_ol;
+	sc->sptrlc_pdev_spectral_init     = pdev_spectral_init_ol;
+	sc->sptrlc_pdev_spectral_deinit   = pdev_spectral_deinit_ol;
+	sc->sptrlc_set_spectral_config    = set_spectral_config_ol;
+	sc->sptrlc_get_spectral_config    = get_spectral_config_ol;
+	sc->sptrlc_start_spectral_scan    = start_spectral_scan_ol;
+	sc->sptrlc_stop_spectral_scan     = stop_spectral_scan_ol;
+	sc->sptrlc_is_spectral_active     = is_spectral_active_ol;
+	sc->sptrlc_is_spectral_enabled    = is_spectral_enabled_ol;
+	sc->sptrlc_set_debug_level        = set_debug_level_ol;
+	sc->sptrlc_get_debug_level        = get_debug_level_ol;
+	sc->sptrlc_get_spectral_capinfo   = get_spectral_capinfo_ol;
+	sc->sptrlc_get_spectral_diagstats = get_spectral_diagstats_ol;
+}
+
diff --git a/spectral/core/spectral_ol_api_i.h b/spectral/core/spectral_ol_api_i.h
new file mode 100644
index 0000000..6541654
--- /dev/null
+++ b/spectral/core/spectral_ol_api_i.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SPECTRAL_OL_API_I_H_
+#define _SPECTRAL_OL_API_I_H_
+
+#include "spectral_defs_i.h"
+
+/**
+ * spectral_ctx_init_ol() - Internal function to initialise spectral context
+ * with offload specific functions
+ * @sc : spectral context
+ *
+ * Return : void
+ */
+void spectral_ctx_init_ol(struct spectral_context *sc);
+
+#endif /* _SPECTRAL_OL_API_I_H_ */
diff --git a/spectral/dispatcher/inc/wlan_spectral_public_structs.h b/spectral/dispatcher/inc/wlan_spectral_public_structs.h
new file mode 100644
index 0000000..c6fe1d8
--- /dev/null
+++ b/spectral/dispatcher/inc/wlan_spectral_public_structs.h
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <qdf_types.h>
+#include "wlan_dfs_ioctl.h"
+
+#ifndef _WLAN_SPECTRAL_PUBLIC_STRUCTS_H_
+#define _WLAN_SPECTRAL_PUBLIC_STRUCTS_H_
+
+#ifdef WIN32
+#pragma pack(push, spectral, 1)
+#define __ATTRIB_PACKED
+#else
+#ifndef __ATTRIB_PACKED
+#define __ATTRIB_PACKED __attribute__ ((packed))
+#endif
+#endif
+
+#ifndef AH_MAX_CHAINS
+#define AH_MAX_CHAINS 3
+#endif
+
+#define MAX_NUM_CHANNELS             255
+#define MAX_SPECTRAL_CHAINS          3
+#define MAX_NUM_BINS                 520
+#define SPECTRAL_PHYERR_PARAM_NOVAL  65535
+/* 5 categories x (lower + upper) bands */
+#define MAX_INTERF                   10
+
+/* ioctl parameter types */
+#define SPECTRAL_PARAM_FFT_PERIOD        (1)
+#define SPECTRAL_PARAM_SCAN_PERIOD       (2)
+#define SPECTRAL_PARAM_SCAN_COUNT        (3)
+#define SPECTRAL_PARAM_SHORT_REPORT      (4)
+#define SPECTRAL_PARAM_SPECT_PRI         (5)
+#define SPECTRAL_PARAM_FFT_SIZE          (6)
+#define SPECTRAL_PARAM_GC_ENA            (7)
+#define SPECTRAL_PARAM_RESTART_ENA       (8)
+#define SPECTRAL_PARAM_NOISE_FLOOR_REF   (9)
+#define SPECTRAL_PARAM_INIT_DELAY        (10)
+#define SPECTRAL_PARAM_NB_TONE_THR       (11)
+#define SPECTRAL_PARAM_STR_BIN_THR       (12)
+#define SPECTRAL_PARAM_WB_RPT_MODE       (13)
+#define SPECTRAL_PARAM_RSSI_RPT_MODE     (14)
+#define SPECTRAL_PARAM_RSSI_THR          (15)
+#define SPECTRAL_PARAM_PWR_FORMAT        (16)
+#define SPECTRAL_PARAM_RPT_MODE          (17)
+#define SPECTRAL_PARAM_BIN_SCALE         (18)
+#define SPECTRAL_PARAM_DBM_ADJ           (19)
+#define SPECTRAL_PARAM_CHN_MASK          (20)
+#define SPECTRAL_PARAM_ACTIVE            (21)
+#define SPECTRAL_PARAM_STOP              (22)
+#define SPECTRAL_PARAM_ENABLE            (23)
+
+#ifdef ATH_SPECTRAL_USE_EMU_DEFAULTS
+/* Use defaults from emulation */
+#define SPECTRAL_SCAN_ACTIVE_DEFAULT           (0x0)
+#define SPECTRAL_SCAN_ENABLE_DEFAULT           (0x0)
+#define SPECTRAL_SCAN_COUNT_DEFAULT            (0x0)
+#define SPECTRAL_SCAN_PERIOD_DEFAULT           (250)
+#define SPECTRAL_SCAN_PRIORITY_DEFAULT         (0x1)
+#define SPECTRAL_SCAN_FFT_SIZE_DEFAULT         (0x7)
+#define SPECTRAL_SCAN_GC_ENA_DEFAULT           (0x1)
+#define SPECTRAL_SCAN_RESTART_ENA_DEFAULT      (0x0)
+#define SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT  (0xa0)
+#define SPECTRAL_SCAN_INIT_DELAY_DEFAULT       (0x50)
+#define SPECTRAL_SCAN_NB_TONE_THR_DEFAULT      (0xc)
+#define SPECTRAL_SCAN_STR_BIN_THR_DEFAULT      (0x7)
+#define SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT      (0x0)
+#define SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT    (0x1)
+#define SPECTRAL_SCAN_RSSI_THR_DEFAULT         (0xf)
+#define SPECTRAL_SCAN_PWR_FORMAT_DEFAULT       (0x1)
+#define SPECTRAL_SCAN_RPT_MODE_DEFAULT         (0x2)
+#define SPECTRAL_SCAN_BIN_SCALE_DEFAULT        (0x1)
+#define SPECTRAL_SCAN_DBM_ADJ_DEFAULT          (0x0)
+#define SPECTRAL_SCAN_CHN_MASK_DEFAULT         (0x1)
+#else
+/* Static default values for spectral state and configuration.
+ * These definitions should be treated as temporary. Ideally,
+ * we should get the defaults from firmware - this will be discussed.
+ *
+ * Use defaults from Spectral Hardware Micro-Architecture
+ * document (v1.0)
+ */
+#define SPECTRAL_SCAN_ACTIVE_DEFAULT           (0)
+#define SPECTRAL_SCAN_ENABLE_DEFAULT           (0)
+#define SPECTRAL_SCAN_COUNT_DEFAULT            (0)
+#define SPECTRAL_SCAN_PERIOD_DEFAULT           (35)
+#define SPECTRAL_SCAN_PRIORITY_DEFAULT         (1)
+#define SPECTRAL_SCAN_FFT_SIZE_DEFAULT         (7)
+#define SPECTRAL_SCAN_GC_ENA_DEFAULT           (1)
+#define SPECTRAL_SCAN_RESTART_ENA_DEFAULT      (0)
+#define SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT  (-96)
+#define SPECTRAL_SCAN_INIT_DELAY_DEFAULT       (80)
+#define SPECTRAL_SCAN_NB_TONE_THR_DEFAULT      (12)
+#define SPECTRAL_SCAN_STR_BIN_THR_DEFAULT      (8)
+#define SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT      (0)
+#define SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT    (0)
+#define SPECTRAL_SCAN_RSSI_THR_DEFAULT         (0xf0)
+#define SPECTRAL_SCAN_PWR_FORMAT_DEFAULT       (0)
+#define SPECTRAL_SCAN_RPT_MODE_DEFAULT         (2)
+#define SPECTRAL_SCAN_BIN_SCALE_DEFAULT        (1)
+#define SPECTRAL_SCAN_DBM_ADJ_DEFAULT          (1)
+#define SPECTRAL_SCAN_CHN_MASK_DEFAULT         (1)
+#endif /* ATH_SPECTRAL_USE_EMU_DEFAULTS */
+
+/* The below two definitions apply only to pre-11ac chipsets */
+#define SPECTRAL_SCAN_SHORT_REPORT_DEFAULT     (1)
+#define SPECTRAL_SCAN_FFT_PERIOD_DEFAULT       (1)
+
+/**
+ * enum spectral_debug - Spectral debug level
+ * @ATH_DEBUG_SPECTRAL:  Minimal SPECTRAL debug
+ * @ATH_DEBUG_SPECTRAL1: Normal SPECTRAL debug
+ * @ATH_DEBUG_SPECTRAL2: Maximal SPECTRAL debug
+ * @ATH_DEBUG_SPECTRAL3: Matched filterID display
+ * @ATH_DEBUG_SPECTRAL4: One time dump of FFT report
+ */
+enum spectral_debug {
+	ATH_DEBUG_SPECTRAL       = 0x00000100,
+	ATH_DEBUG_SPECTRAL1      = 0x00000200,
+	ATH_DEBUG_SPECTRAL2      = 0x00000400,
+	ATH_DEBUG_SPECTRAL3      = 0x00000800,
+	ATH_DEBUG_SPECTRAL4      = 0x00001000,
+};
+
+/**
+ * enum SPECTRAL_CAPABILITY_TYPE - Spectral capability type
+ * @SPECTRAL_CAP_PHYDIAG:              Phydiag capability
+ * @SPECTRAL_CAP_RADAR:                Radar detection capability
+ * @SPECTRAL_CAP_SPECTRAL_SCAN:        Spectral capability
+ * @SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN: Advanced spectral capability
+ */
+typedef enum {
+	SPECTRAL_CAP_PHYDIAG,
+	SPECTRAL_CAP_RADAR,
+	SPECTRAL_CAP_SPECTRAL_SCAN,
+	SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN,
+} SPECTRAL_CAPABILITY_TYPE;
+
+/**
+ * struct spectral_chan_stats - channel status info
+ * @cycle_count:         Cycle count
+ * @channel_load:        Channel load
+ * @per:                 Period
+ * @noisefloor:          Noise floor
+ * @comp_usablity:       Computed usability
+ * @maxregpower:         Maximum allowed regulatory power
+ * @comp_usablity_sec80: Computed usability of secondary 80 Mhz
+ * @maxregpower_sec80:   Max regulatory power of secondary 80 Mhz
+ */
+struct spectral_chan_stats {
+	int          cycle_count;
+	int          channel_load;
+	int          per;
+	int          noisefloor;
+	u_int16_t    comp_usablity;
+	int8_t       maxregpower;
+	u_int16_t    comp_usablity_sec80;
+	int8_t       maxregpower_sec80;
+};
+
+/**
+ * struct spectral_diag_stats - spectral diag stats
+ * @spectral_mismatch:             Spectral TLV signature mismatches
+ * @spectral_sec80_sfft_insufflen: Insufficient length when parsing for
+ *                                 Secondary 80 Search FFT report
+ * @spectral_no_sec80_sfft:        Secondary 80 Search FFT report
+ *                                 TLV not found
+ * @spectral_vhtseg1id_mismatch:   VHT Operation Segment 1 ID
+ *                                 mismatches in Search FFT report
+ * @spectral_vhtseg2id_mismatch:   VHT Operation Segment 2 ID
+ *                                 mismatches in Search FFT report
+ */
+struct spectral_diag_stats {
+	u_int64_t spectral_mismatch;
+	u_int64_t spectral_sec80_sfft_insufflen;
+	u_int64_t spectral_no_sec80_sfft;
+	u_int64_t spectral_vhtseg1id_mismatch;
+	u_int64_t spectral_vhtseg2id_mismatch;
+};
+
+/**
+ * struct spectral_caps - Spectral capabilities structure
+ * @phydiag_cap:         Phydiag capability
+ * @radar_cap:           Radar detection capability
+ * @spectral_cap:        Spectral capability
+ * @advncd_spectral_cap: Advanced spectral capability
+ */
+struct spectral_caps {
+	u_int8_t phydiag_cap;
+	u_int8_t radar_cap;
+	u_int8_t spectral_cap;
+	u_int8_t advncd_spectral_cap;
+};
+
+/**
+ * struct spectral_config
+ * @ss_fft_period:        Skip interval for FFT reports
+ * @ss_period:            Spectral scan period
+ * @ss_count:             # of reports to return from ss_active
+ * @ss_short_report:      Set to report only 1 set of FFT results
+ * @radar_bin_thresh_sel: Select threshold to classify strong bin for FFT
+ * @ss_spectral_pri:      Priority, and are we doing a noise power cal ?
+ * @ss_fft_size:          Defines the number of FFT data points to compute,
+ *                        defined as a log index num_fft_pts =
+ *                        2^ss_fft_size
+ * @ss_gc_ena:            Set, to enable targeted gain change before
+ *                        starting the spectral scan FFT
+ * @ss_restart_ena:       Set, to enable abort of receive frames when in high
+ *                        priority and a spectral scan is queued
+ * @ss_noise_floor_ref:   Noise floor reference number (signed) for the
+ *                        calculation of bin power (dBm) Though stored as an
+ *                        unsigned this should be treated as a signed 8-bit int.
+ * @ss_init_delay:        Disallow spectral scan triggers after tx/rx packets
+ *                        by setting this delay value to roughly SIFS time
+ *                        period or greater Delay timer count in units of 0.25us
+ * @ss_nb_tone_thr:       Number of strong bins (inclusive) per sub-channel,
+ *                        below which a signal is declared a narrowband tone
+ * @ss_str_bin_thr:       Bin/max_bin ratio threshold over which a bin is
+ *                        declared strong (for spectral scan bandwidth analysis)
+ * @ss_wb_rpt_mode:       Set this bit to report spectral scans as EXT_BLOCKER
+ *                        (phy_error=36), if none of the sub-channels are
+ *                        deemed narrowband
+ * @ss_rssi_rpt_mode:     Set this bit to report spectral scans as EXT_BLOCKER
+ *                        (phy_error=36), if the ADC RSSI is below the
+ *                        threshold ss_rssi_thr
+ * @ss_rssi_thr:          ADC RSSI must be greater than or equal to this
+ *                        threshold (signed Db) to ensure spectral scan
+ *                        reporting with normal phy error codes (please see
+ *                        ss_rssi_rpt_mode above).Though stored as an unsigned
+ *                        value, this should be treated as a signed 8-bit int
+ * @ss_pwr_format:        Format of frequency bin magnitude for spectral scan
+ *                        triggered FFTs 0: linear magnitude
+ *                        1: log magnitude (20*log10(lin_mag), 1/2 dB step size)
+ * @ss_rpt_mode:          Format of per-FFT reports to software for spectral
+ *                        scan triggered FFTs
+ *                        0: No FFT report (only pulse end summary)
+ *                        1: 2-dword summary of metrics for each completed FFT
+ *                        2: 2-dword summary + 1x-oversampled bins(in-band) per
+ *                           FFT
+ *                        3: 2-dword summary + 2x-oversampled bins (all) per FFT
+ * @ss_bin_scale:         Number of LSBs to shift out to scale the FFT bins
+ *                        for spectral scan triggered FFTs
+ * @ss_dBm_adj:           Set (with ss_pwr_format=1), to report bin
+ *                        magnitudes
+ *                        converted to dBm power using the noisefloor
+ *                        calibration results
+ * @ss_chn_mask:          Per chain enable mask to select input ADC for search
+ *                        FFT
+ * @ss_nf_cal:            nf calibrated values for ctl+ext
+ * @ss_nf_pwr:            nf pwr values for ctl+ext
+ * @ss_nf_temp_data:      temperature data taken during nf scan
+ */
+struct spectral_config {
+	u_int16_t   ss_fft_period;
+	u_int16_t   ss_period;
+	u_int16_t   ss_count;
+	u_int16_t   ss_short_report;
+	u_int8_t    radar_bin_thresh_sel;
+	u_int16_t   ss_spectral_pri;
+	u_int16_t   ss_fft_size;
+	u_int16_t   ss_gc_ena;
+	u_int16_t   ss_restart_ena;
+	u_int16_t   ss_noise_floor_ref;
+	u_int16_t   ss_init_delay;
+	u_int16_t   ss_nb_tone_thr;
+	u_int16_t   ss_str_bin_thr;
+	u_int16_t   ss_wb_rpt_mode;
+	u_int16_t   ss_rssi_rpt_mode;
+	u_int16_t   ss_rssi_thr;
+	u_int16_t   ss_pwr_format;
+	u_int16_t   ss_rpt_mode;
+	u_int16_t   ss_bin_scale;
+	u_int16_t   ss_dBm_adj;
+	u_int16_t   ss_chn_mask;
+	int8_t      ss_nf_cal[AH_MAX_CHAINS * 2];
+	int8_t      ss_nf_pwr[AH_MAX_CHAINS * 2];
+	int32_t     ss_nf_temp_data;
+};
+
+/**
+ * struct spectral_caps - Spectral capabilities structure
+ * @phydiag_cap:         Phydiag capability
+ * @radar_cap:           Radar detection capability
+ * @spectral_cap:        Spectral capability
+ * @advncd_spectral_cap: Advanced spectral capability
+ */
+typedef enum _dcs_int_type {
+	SPECTRAL_DCS_INT_NONE,
+	SPECTRAL_DCS_INT_CW,
+	SPECTRAL_DCS_INT_WIFI
+} DCS_INT_TYPE;
+
+/**
+ * struct INTERF_RSP - Interference record
+ * @interf_type:         eINTERF_TYPE giving type of interference
+ * @interf_min_freq:     Minimum frequency in MHz at which interference has been
+ * found
+ * @interf_max_freq:     Maximum frequency in MHz at which interference has been
+ * found
+ * @advncd_spectral_cap: Advanced spectral capability
+ */
+struct INTERF_RSP {
+	u_int8_t  interf_type;
+	u_int16_t interf_min_freq;
+	u_int16_t interf_max_freq;
+} __ATTRIB_PACKED;
+
+/**
+ * struct INTERF_SRC_RSP - List of interference sources
+ * @count: Number of interference records
+ * @interf: Array of interference records
+ */
+struct INTERF_SRC_RSP {
+	u_int16_t count;
+	struct INTERF_RSP interf[MAX_INTERF];
+} __ATTRIB_PACKED;
+
+/**
+ * struct spectral_classifier_params -
+ * @spectral_20_40_mode:  Is AP in 20/40 mode?
+ * @spectral_dc_index:    DC index
+ * @spectral_dc_in_mhz:   DC in MHz
+ * @upper_chan_in_mhz:    Upper channel in MHz
+ * @lower_chan_in_mhz:    Lower channel in MHz
+ */
+typedef struct spectral_classifier_params {
+	int spectral_20_40_mode;
+	int spectral_dc_index;
+	int spectral_dc_in_mhz;
+	int upper_chan_in_mhz;
+	int lower_chan_in_mhz;
+} __ATTRIB_PACKED SPECTRAL_CLASSIFIER_PARAMS;
+
+/**
+ * struct spectral_samp_data - Spectral Analysis Messaging Protocol Data format
+ * @spectral_data_len:        Indicates the bin size
+ * @spectral_data_len_sec80:  Indicates the bin size for secondary 80 segment
+ * @spectral_rssi:            Indicates RSSI
+ * @spectral_rssi_sec80:      Indicates RSSI for secondary 80 segment
+ * @spectral_combined_rssi:   Indicates combined RSSI from all antennas
+ * @spectral_upper_rssi:      Indicates RSSI of upper band
+ * @spectral_lower_rssi:      Indicates RSSI of lower band
+ * @spectral_chain_ctl_rssi:  RSSI for control channel, for all antennas
+ * @spectral_chain_ext_rssi:  RSSI for extension channel, for all antennas
+ * @spectral_max_scale:       Indicates scale factor
+ * @spectral_bwinfo:          Indicates bandwidth info
+ * @spectral_tstamp:          Indicates timestamp
+ * @spectral_max_index:       Indicates the index of max magnitude
+ * @spectral_max_index_sec80: Indicates the index of max magnitude for secondary
+ *                            80 segment
+ * @spectral_max_mag:         Indicates the maximum magnitude
+ * @spectral_max_mag_sec80:   Indicates the maximum magnitude for secondary 80
+ *                            segment
+ * @spectral_max_exp:         Indicates the max exp
+ * @spectral_last_tstamp:     Indicates the last time stamp
+ * @spectral_upper_max_index: Indicates the index of max mag in upper band
+ * @spectral_lower_max_index: Indicates the index of max mag in lower band
+ * @spectral_nb_upper:        Not Used
+ * @spectral_nb_lower:        Not Used
+ * @classifier_params:        Indicates classifier parameters
+ * @bin_pwr_count:            Indicates the number of FFT bins
+ * @lb_edge_extrabins:        Number of extra bins on left band edge
+ * @rb_edge_extrabins:        Number of extra bins on right band edge
+ * @bin_pwr_count_sec80:      Indicates the number of FFT bins in secondary 80
+ *                            segment
+ * @bin_pwr:                  Contains FFT magnitudes
+ * @bin_pwr_sec80:            Contains FFT magnitudes for the secondary 80
+ *                            segment
+ * @interf_list:              List of interfernce sources
+ * @noise_floor:              Indicates the current noise floor
+ * @noise_floor_sec80:        Indicates the current noise floor for secondary 80
+ *                            segment
+ * @ch_width:                 Channel width 20/40/80/160 MHz
+ */
+typedef struct spectral_samp_data {
+	int16_t                              spectral_data_len;
+	int16_t                              spectral_data_len_sec80;
+	int16_t                              spectral_rssi;
+	int16_t                              spectral_rssi_sec80;
+	int8_t                               spectral_combined_rssi;
+	int8_t                               spectral_upper_rssi;
+	int8_t                               spectral_lower_rssi;
+	int8_t  spectral_chain_ctl_rssi[MAX_SPECTRAL_CHAINS];
+	int8_t  spectral_chain_ext_rssi[MAX_SPECTRAL_CHAINS];
+	u_int8_t                             spectral_max_scale;
+	int16_t                              spectral_bwinfo;
+	int32_t                              spectral_tstamp;
+	int16_t                              spectral_max_index;
+	int16_t                              spectral_max_index_sec80;
+	int16_t                              spectral_max_mag;
+	int16_t                              spectral_max_mag_sec80;
+	u_int8_t                             spectral_max_exp;
+	int32_t                              spectral_last_tstamp;
+	int16_t                              spectral_upper_max_index;
+	int16_t                              spectral_lower_max_index;
+	u_int8_t                             spectral_nb_upper;
+	u_int8_t                             spectral_nb_lower;
+	struct spectral_classifier_params    classifier_params;
+	u_int16_t                            bin_pwr_count;
+	/* For 11ac chipsets prior to AR900B version 2.0, a max of 512 bins are
+	 * delivered.  However, there can be additional bins reported for
+	 * AR900B version 2.0 and QCA9984 as described next:
+	 *
+	 * AR900B version 2.0: An additional tone is processed on the right
+	 * hand side in order to facilitate detection of radar pulses out to
+	 * the extreme band-edge of the channel frequency.
+	 * Since the HW design processes four tones at a time,
+	 * this requires one additional Dword to be added to the
+	 * search FFT report.
+	 *
+	 * QCA9984: When spectral_scan_rpt_mode=2, i.e 2-dword summary +
+	 * 1x-oversampled bins (in-band) per FFT,
+	 * then 8 more bins (4 more on left side and 4 more on right side)
+	 * are added.
+	 */
+	u_int8_t                             lb_edge_extrabins;
+	u_int8_t                             rb_edge_extrabins;
+	u_int16_t                            bin_pwr_count_sec80;
+	u_int8_t                             bin_pwr[MAX_NUM_BINS];
+	u_int8_t                             bin_pwr_sec80[MAX_NUM_BINS];
+	struct INTERF_SRC_RSP                interf_list;
+	int16_t                              noise_floor;
+	int16_t                              noise_floor_sec80;
+	u_int32_t                            ch_width;
+} __ATTRIB_PACKED SPECTRAL_SAMP_DATA;
+
+/**
+ * struct spectral_samp_msg - Spectral SAMP message
+ * @signature:          Validates the SAMP message
+ * @freq:               Operating frequency in MHz
+ * @vhtop_ch_freq_seg1: VHT Segment 1 centre frequency in MHz
+ * @vhtop_ch_freq_seg2: VHT Segment 2 centre frequency in MHz
+ * @freq_loading:       How busy was the channel
+ * @dcs_enabled:        Whether DCS is enabled
+ * @int_type:           Interference type indicated by DCS
+ * @macaddr:            Indicates the device interface
+ * @samp_data:          SAMP Data
+ */
+typedef struct spectral_samp_msg {
+	u_int32_t             signature;
+	u_int16_t             freq;
+	u_int16_t             vhtop_ch_freq_seg1;
+	u_int16_t             vhtop_ch_freq_seg2;
+	u_int16_t             freq_loading;
+	u_int16_t             dcs_enabled;
+	DCS_INT_TYPE          int_type;
+	u_int8_t              macaddr[6];
+	SPECTRAL_SAMP_DATA    samp_data;
+} __ATTRIB_PACKED SPECTRAL_SAMP_MSG;
+
+#ifdef WIN32
+#pragma pack(pop, spectral)
+#endif
+#ifdef __ATTRIB_PACKED
+#undef __ATTRIB_PACKED
+#endif
+
+#endif /* _WLAN_SPECTRAL_PUBLIC_STRUCTS_H_ */
+
diff --git a/spectral/dispatcher/inc/wlan_spectral_tgt_api.h b/spectral/dispatcher/inc/wlan_spectral_tgt_api.h
new file mode 100644
index 0000000..86f2972
--- /dev/null
+++ b/spectral/dispatcher/inc/wlan_spectral_tgt_api.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WLAN_SPECTRAL_TGT_API_H_
+#define _WLAN_SPECTRAL_TGT_API_H_
+
+#include <wlan_objmgr_cmn.h>
+#include <qdf_types.h>
+
+/**
+ * tgt_send_phydata() - Send Spectral PHY data over netlink
+ * @pdev: Pointer to pdev
+ * @sock: Netlink socket to use
+ * @nbuf: Network buffer containing PHY data to send
+ *
+ * Return: 0 on success, negative value on failure
+ */
+int tgt_send_phydata(struct wlan_objmgr_pdev *pdev,
+		     struct sock *sock, qdf_nbuf_t nbuf);
+
+/**
+ * tgt_get_target_handle() - Get handle to target_if internal Spectral data
+ * @pdev: Pointer to pdev
+ *
+ * Return: Handle to target_if internal Spectral data on success, NULL on
+ * failure
+ */
+void *tgt_get_target_handle(struct wlan_objmgr_pdev *pdev);
+
+#endif /* _WLAN_SPECTRAL_TGT_API_H_*/
diff --git a/spectral/dispatcher/inc/wlan_spectral_ucfg_api.h b/spectral/dispatcher/inc/wlan_spectral_ucfg_api.h
new file mode 100644
index 0000000..0400494
--- /dev/null
+++ b/spectral/dispatcher/inc/wlan_spectral_ucfg_api.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WLAN_SPECTRAL_UCFG_API_H_
+#define _WLAN_SPECTRAL_UCFG_API_H_
+
+#include <wlan_objmgr_cmn.h>
+#include <wlan_spectral_public_structs.h>
+
+/* Spectral specific UCFG set operations */
+
+/**
+ * ucfg_spectral_control() - Carry out Spectral control get/set operations
+ * @pdev: Pointer to pdev
+ * @id: Spectral operation ID
+ * @indata: Pointer to input data
+ * @insize: Size of indata buffer
+ * @outdata: Pointer to buffer where the output should be stored
+ * @outsize: Size of outdata buffer
+ *
+ * Return: 0 on success, negative value on failure
+ */
+int ucfg_spectral_control(
+	struct wlan_objmgr_pdev *pdev,
+	 u_int id,
+	 void *indata,
+	 u_int32_t insize,
+			  void *outdata, u_int32_t *outsize);
+
+#endif /* _WLAN_SPECTRAL_UCFG_API_H_*/
diff --git a/spectral/dispatcher/inc/wlan_spectral_utils_api.h b/spectral/dispatcher/inc/wlan_spectral_utils_api.h
new file mode 100644
index 0000000..26825fa
--- /dev/null
+++ b/spectral/dispatcher/inc/wlan_spectral_utils_api.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WLAN_SPECTRAL_UTILS_API_H_
+#define _WLAN_SPECTRAL_UTILS_API_H_
+
+#include <wlan_objmgr_cmn.h>
+#include <wlan_lmac_if_def.h>
+
+/**
+ * wlan_spectral_init(): API to init spectral component
+ *
+ * This API is invoked from dispatcher init during all component init.
+ * This API will register all required handlers for pdev and peer object
+ * create/delete notification.
+ *
+ * Return: SUCCESS,
+ *         Failure
+ */
+QDF_STATUS wlan_spectral_init(void);
+
+/**
+ * wlan_spectral_deinit(): API to deinit spectral component
+ *
+ * This API is invoked from dispatcher deinit during all component deinit.
+ * This API will unregister all registered handlers for pdev and peer object
+ * create/delete notification.
+ *
+ * Return: SUCCESS,
+ *         Failure
+ */
+QDF_STATUS wlan_spectral_deinit(void);
+
+/**
+ * wlan_lmac_if_sptrl_register_rx_ops(): Register lmac interface Rx operations
+ * @rx_ops: Pointer to lmac interface Rx operations structure
+ *
+ * Return: None
+ */
+void wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops);
+
+#endif /* _WLAN_SPECTRAL_UTILS_API_H_*/
diff --git a/spectral/dispatcher/src/wlan_spectral_tgt_api.c b/spectral/dispatcher/src/wlan_spectral_tgt_api.c
new file mode 100644
index 0000000..a3fa5bc
--- /dev/null
+++ b/spectral/dispatcher/src/wlan_spectral_tgt_api.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <wlan_spectral_tgt_api.h>
+#include "../../core/spectral_cmn_api_i.h"
+
+int tgt_send_phydata(struct wlan_objmgr_pdev *pdev,
+		     struct sock *sock, qdf_nbuf_t nbuf)
+{
+	return netlink_broadcast(sock, nbuf, 0, 1, GFP_ATOMIC);
+}
+
+void *tgt_get_target_handle(struct wlan_objmgr_pdev *pdev)
+{
+	struct pdev_spectral *ps;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL!\n");
+		return NULL;
+	}
+	ps = wlan_objmgr_pdev_get_comp_private_obj(
+		pdev,
+		 WLAN_UMAC_COMP_SPECTRAL);
+	if (!ps) {
+		spectral_err("PDEV SPECTRAL object is NULL!\n");
+		return NULL;
+	}
+	return ps->psptrl_target_handle;
+}
diff --git a/spectral/dispatcher/src/wlan_spectral_ucfg_api.c b/spectral/dispatcher/src/wlan_spectral_ucfg_api.c
new file mode 100644
index 0000000..b063f9d
--- /dev/null
+++ b/spectral/dispatcher/src/wlan_spectral_ucfg_api.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <wlan_spectral_ucfg_api.h>
+#include "../../core/spectral_cmn_api_i.h"
+#include <wlan_spectral_utils_api.h>
+
+int ucfg_spectral_control(
+	struct wlan_objmgr_pdev *pdev,
+	u_int id,
+	void *indata,
+	u_int32_t insize,
+	void *outdata, u_int32_t *outsize)
+{
+	struct spectral_context *sc;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL!\n");
+		return -EPERM;
+	}
+	sc = spectral_get_spectral_ctx_from_pdev(pdev);
+	if (!sc) {
+		spectral_err("spectral context is NULL!\n");
+		return -EPERM;
+	}
+	return sc->sptrlc_spectral_control(
+		pdev,
+		 id,
+		 indata,
+		 insize,
+		 outdata,
+		 outsize);
+}
+EXPORT_SYMBOL(ucfg_spectral_control);
diff --git a/spectral/dispatcher/src/wlan_spectral_utils_api.c b/spectral/dispatcher/src/wlan_spectral_utils_api.c
new file mode 100644
index 0000000..d65a9cd
--- /dev/null
+++ b/spectral/dispatcher/src/wlan_spectral_utils_api.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <wlan_spectral_utils_api.h>
+#include <qdf_module.h>
+#include "../../core/spectral_cmn_api_i.h"
+#include <wlan_spectral_tgt_api.h>
+
+QDF_STATUS wlan_spectral_init(void)
+{
+	if (wlan_objmgr_register_psoc_create_handler(
+		WLAN_UMAC_COMP_SPECTRAL,
+		wlan_spectral_psoc_obj_create_handler,
+		NULL) != QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (wlan_objmgr_register_psoc_destroy_handler(
+		WLAN_UMAC_COMP_SPECTRAL,
+		wlan_spectral_psoc_obj_destroy_handler,
+		NULL) != QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (wlan_objmgr_register_pdev_create_handler(
+		WLAN_UMAC_COMP_SPECTRAL,
+		wlan_spectral_pdev_obj_create_handler,
+		NULL) != QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (wlan_objmgr_register_pdev_destroy_handler(
+		WLAN_UMAC_COMP_SPECTRAL,
+		wlan_spectral_pdev_obj_destroy_handler,
+		NULL) != QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_spectral_deinit(void)
+{
+	if (wlan_objmgr_unregister_psoc_create_handler(
+		WLAN_UMAC_COMP_SPECTRAL,
+		wlan_spectral_psoc_obj_create_handler,
+		NULL) != QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (wlan_objmgr_unregister_psoc_destroy_handler(
+		WLAN_UMAC_COMP_SPECTRAL,
+		wlan_spectral_psoc_obj_destroy_handler,
+		NULL) != QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (wlan_objmgr_unregister_pdev_create_handler(
+		WLAN_UMAC_COMP_SPECTRAL,
+		wlan_spectral_pdev_obj_create_handler,
+		NULL) != QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (wlan_objmgr_unregister_pdev_destroy_handler(
+		WLAN_UMAC_COMP_SPECTRAL,
+		wlan_spectral_pdev_obj_destroy_handler,
+		NULL) != QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+void wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
+{
+	struct wlan_lmac_if_sptrl_rx_ops *sptrl_rx_ops = &rx_ops->sptrl_rx_ops;
+
+	/* Spectral rx ops */
+	sptrl_rx_ops->sptrlro_send_phydata = tgt_send_phydata;
+	sptrl_rx_ops->sptrlro_get_target_handle = tgt_get_target_handle;
+}
diff --git a/target_if/spectral/target_if_spectral.c b/target_if/spectral/target_if_spectral.c
new file mode 100644
index 0000000..5c02c50
--- /dev/null
+++ b/target_if/spectral/target_if_spectral.c
@@ -0,0 +1,2509 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <wlan_tgt_def_config.h>
+#include <hif.h>
+#include <hif_hw_version.h>
+#include <wmi_unified_api.h>
+#include <target_if_spectral.h>
+#include <wlan_lmac_if_def.h>
+#include <wlan_osif_priv.h>
+#include <reg_services_public_struct.h>
+#include <wlan_mlme_dispatcher.h>
+#include <target_if_spectral_sim.h>
+
+/**
+ * @spectral_ops - Spectral function table, holds the Spectral functions that
+ * depend on whether the architecture is Direct Attach or Offload. This is used
+ * to populate the actual Spectral function table present in the Spectral
+ * module.
+ */
+struct target_if_spectral_ops spectral_ops;
+
+/**
+ * target_if_spectral_get_vdev() - Get pointer to vdev to be used for Spectral
+ * operations
+ * @spectral: Pointer to Spectral target_if internal private data
+ *
+ * Spectral operates on pdev. However, in order to retrieve some WLAN
+ * properties, a vdev is required. To facilitate this, the function returns the
+ * first vdev in our pdev. The caller should release the reference to the vdev
+ * once it is done using it.
+ * TODO: If the framework later provides an API to obtain the first active
+ * vdev, then it would be preferable to use this API.
+ *
+ * Return: Pointer to vdev on success, NULL on failure
+ */
+struct wlan_objmgr_vdev *
+target_if_spectral_get_vdev(struct target_if_spectral *spectral)
+{
+	struct wlan_objmgr_pdev *pdev = NULL;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	qdf_assert_always(spectral);
+	pdev = spectral->pdev_obj;
+	qdf_assert_always(pdev);
+
+	if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_SPECTRAL_ID) !=
+		QDF_STATUS_SUCCESS) {
+		qdf_print("%s: Unable to get pdev reference.\n", __func__);
+		return NULL;
+	}
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 0, WLAN_SPECTRAL_ID);
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
+
+	if (!vdev) {
+		qdf_print("%s: Unable to get first vdev of pdev.\n", __func__);
+		return NULL;
+	}
+
+	return vdev;
+}
+
+/**
+ * wmi_send_vdev_spectral_configure_cmd() - Send WMI command to configure
+ * Spectral parameters
+ * @spectral: Pointer to Spectral target_if internal private data
+ * @param: Pointer to spectral_config giving the Spectral configuration
+ *
+ * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
+ */
+int wmi_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral,
+					 struct spectral_config *param)
+{
+	struct ol_ath_softc_net80211 *scn = NULL;
+	struct pdev_osif_priv *osif_priv = NULL;
+	struct vdev_spectral_configure_params sparam;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	qdf_assert_always(spectral && param);
+
+	pdev = spectral->pdev_obj;
+
+	qdf_assert_always(pdev);
+
+	osif_priv = wlan_pdev_get_ospriv(pdev);
+	scn = (struct ol_ath_softc_net80211 *)osif_priv->legacy_osif_priv;
+
+	vdev = target_if_spectral_get_vdev(spectral);
+	if (!vdev)
+		return QDF_STATUS_E_NOENT;
+
+	qdf_mem_set(&sparam, sizeof(sparam), 0);
+
+	sparam.vdev_id = wlan_vdev_get_id(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+	sparam.count = param->ss_count;
+	sparam.period = param->ss_period;
+	sparam.spectral_pri = param->ss_spectral_pri;
+	sparam.fft_size = param->ss_fft_size;
+	sparam.gc_enable = param->ss_gc_ena;
+	sparam.restart_enable = param->ss_restart_ena;
+	sparam.noise_floor_ref = param->ss_noise_floor_ref;
+	sparam.init_delay = param->ss_init_delay;
+	sparam.nb_tone_thr = param->ss_nb_tone_thr;
+	sparam.str_bin_thr = param->ss_str_bin_thr;
+	sparam.wb_rpt_mode = param->ss_wb_rpt_mode;
+	sparam.rssi_rpt_mode = param->ss_rssi_rpt_mode;
+	sparam.rssi_thr = param->ss_rssi_thr;
+	sparam.pwr_format = param->ss_pwr_format;
+	sparam.rpt_mode = param->ss_rpt_mode;
+	sparam.bin_scale = param->ss_bin_scale;
+	sparam.dBm_adj = param->ss_dBm_adj;
+	sparam.chn_mask = param->ss_chn_mask;
+
+	return scn->wmi_spectral_configure_cmd_send(scn->wmi_handle, &sparam);
+}
+
+/**
+ * wmi_send_vdev_spectral_enable_cmd() - Send WMI command to enable/disable
+ * Spectral
+ * @spectral: Pointer to Spectral target_if internal private data
+ * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is
+ * valid
+ * @is_spectral_active: Value of spectral activate
+ * @is_spectral_enabled_valid: Flag to indicate if spectral enable is valid
+ * @is_spectral_enabled: Value of spectral enable
+ *
+ * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
+ */
+int wmi_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral,
+				      u_int8_t is_spectral_active_valid,
+				      u_int8_t is_spectral_active,
+				      u_int8_t is_spectral_enabled_valid,
+				      u_int8_t is_spectral_enabled)
+{
+	struct vdev_spectral_enable_params param;
+	struct ol_ath_softc_net80211 *scn = NULL;
+	struct pdev_osif_priv *osif_priv = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	qdf_assert_always(spectral);
+
+	pdev = spectral->pdev_obj;
+
+	qdf_assert_always(pdev);
+
+	osif_priv = wlan_pdev_get_ospriv(pdev);
+	scn = (struct ol_ath_softc_net80211 *)osif_priv->legacy_osif_priv;
+
+	vdev = target_if_spectral_get_vdev(spectral);
+	if (!vdev)
+		return QDF_STATUS_E_NOENT;
+
+	qdf_mem_set(&param, sizeof(param), 0);
+
+	param.vdev_id = wlan_vdev_get_id(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+	param.active_valid = is_spectral_active_valid;
+	param.enabled_valid = is_spectral_enabled_valid;
+	param.active = is_spectral_active;
+	param.enabled = is_spectral_enabled;
+
+	return scn->wmi_spectral_enable_cmd_send(scn->wmi_handle, &param);
+}
+
+/**
+ * target_if_spectral_info_init_defaults() - Helper function to load defaults
+ * for Spectral information (parameters and state) into cache.
+ * @spectral: Pointer to Spectral target_if internal private data
+ *
+ * It is assumed that the caller has obtained the requisite lock if applicable.
+ * Note that this is currently treated as a temporary function.  Ideally, we
+ * would like to get defaults from the firmware.
+ *
+ * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
+ */
+int target_if_spectral_info_init_defaults(struct target_if_spectral *spectral)
+{
+	struct target_if_spectral_param_state_info *info = &spectral->ol_info;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	/* State */
+	info->osps_cache.osc_spectral_active =
+	SPECTRAL_SCAN_ACTIVE_DEFAULT;
+
+	info->osps_cache.osc_spectral_enabled =
+	SPECTRAL_SCAN_ENABLE_DEFAULT;
+
+	/* Parameters */
+	info->osps_cache.osc_params.ss_count =
+	SPECTRAL_SCAN_COUNT_DEFAULT;
+
+	info->osps_cache.osc_params.ss_period =
+	SPECTRAL_SCAN_PERIOD_DEFAULT;
+
+	info->osps_cache.osc_params.ss_spectral_pri =
+	SPECTRAL_SCAN_PRIORITY_DEFAULT;
+
+	info->osps_cache.osc_params.ss_fft_size =
+	SPECTRAL_SCAN_FFT_SIZE_DEFAULT;
+
+	info->osps_cache.osc_params.ss_gc_ena =
+	SPECTRAL_SCAN_GC_ENA_DEFAULT;
+
+	info->osps_cache.osc_params.ss_restart_ena =
+	SPECTRAL_SCAN_RESTART_ENA_DEFAULT;
+
+	info->osps_cache.osc_params.ss_noise_floor_ref =
+	SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT;
+
+	info->osps_cache.osc_params.ss_init_delay =
+	SPECTRAL_SCAN_INIT_DELAY_DEFAULT;
+
+	info->osps_cache.osc_params.ss_nb_tone_thr =
+	SPECTRAL_SCAN_NB_TONE_THR_DEFAULT;
+
+	info->osps_cache.osc_params.ss_str_bin_thr =
+	SPECTRAL_SCAN_STR_BIN_THR_DEFAULT;
+
+	info->osps_cache.osc_params.ss_wb_rpt_mode =
+	SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT;
+
+	info->osps_cache.osc_params.ss_rssi_rpt_mode =
+	SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT;
+
+	info->osps_cache.osc_params.ss_rssi_thr =
+	SPECTRAL_SCAN_RSSI_THR_DEFAULT;
+
+	info->osps_cache.osc_params.ss_pwr_format =
+	SPECTRAL_SCAN_PWR_FORMAT_DEFAULT;
+
+	info->osps_cache.osc_params.ss_rpt_mode =
+	SPECTRAL_SCAN_RPT_MODE_DEFAULT;
+
+	info->osps_cache.osc_params.ss_bin_scale =
+	SPECTRAL_SCAN_BIN_SCALE_DEFAULT;
+
+	info->osps_cache.osc_params.ss_dBm_adj =
+	SPECTRAL_SCAN_DBM_ADJ_DEFAULT;
+
+	vdev = target_if_spectral_get_vdev(spectral);
+	if (!vdev)
+		return QDF_STATUS_E_NOENT;
+
+	info->osps_cache.osc_params.ss_chn_mask =
+			wlan_vdev_mlme_get_rxchainmask(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+	/* The cache is now valid */
+	info->osps_cache.osc_is_valid = 1;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * ol_spectral_info_read() - Read Spectral parameters or the desired state
+ * information from the cache.
+ * @spectral: Pointer to Spectral target_if internal private data
+ * @specifier: ol_spectral_info_spec enumeration specifying which information is
+ * required
+ * @output: Void output pointer into which the information will be read
+ * @output_len: size of object pointed to by output pointer
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int ol_spectral_info_read(struct target_if_spectral *spectral,
+			  enum ol_spectral_info_spec specifier,
+				void *output,
+				int output_len)
+{
+	/* Note: This function is designed to be able to accommodate
+	 * WMI reads for defaults, non-cacheable information, etc
+	 * if required.
+	 */
+	struct target_if_spectral_param_state_info *info = &spectral->ol_info;
+	int is_cacheable = 0;
+	int init_def_retval = 0;
+
+	if (!output)
+		return -EINVAL;
+
+	switch (specifier) {
+	case OL_SPECTRAL_INFO_SPEC_ACTIVE:
+		if (output_len !=
+			sizeof(info->osps_cache.osc_spectral_active))
+			return -EINVAL;
+		is_cacheable = 1;
+		break;
+
+	case OL_SPECTRAL_INFO_SPEC_ENABLED:
+		if (output_len !=
+			sizeof(info->osps_cache.osc_spectral_enabled))
+			return -EINVAL;
+		is_cacheable = 1;
+		break;
+
+	case OL_SPECTRAL_INFO_SPEC_PARAMS:
+		if (output_len != sizeof(info->osps_cache.osc_params))
+			return -EINVAL;
+		is_cacheable = 1;
+		break;
+
+	default:
+		qdf_print("%s: Unknown ol_spectral_info_spec specifier\n",
+			  __func__);
+		return -EINVAL;
+	}
+
+	qdf_spin_lock(&info->osps_lock);
+
+	if (is_cacheable) {
+		if (info->osps_cache.osc_is_valid) {
+			switch (specifier) {
+			case OL_SPECTRAL_INFO_SPEC_ACTIVE:
+				qdf_mem_copy(
+				 output,
+				 &info->osps_cache.osc_spectral_active,
+				 sizeof(info->osps_cache.osc_spectral_active));
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+				qdf_print("%s: OL_SPECTRAL_INFO_SPEC_ACTIVE. "
+					  "Returning val=%u\n",
+					  __func__,
+					  *((unsigned char *)output));
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+				break;
+
+			case OL_SPECTRAL_INFO_SPEC_ENABLED:
+				qdf_mem_copy(
+				output,
+				&info->osps_cache.osc_spectral_enabled,
+				sizeof(info->osps_cache.osc_spectral_enabled));
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+				qdf_print("%s: OL_SPECTRAL_INFO_SPEC_ENABLED. "
+					  "Returning val=%u\n",
+					  __func__,
+					  *((unsigned char *)output));
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+
+				break;
+
+			case OL_SPECTRAL_INFO_SPEC_PARAMS:
+				qdf_mem_copy(
+					output,
+					&info->osps_cache.osc_params,
+					sizeof(info->osps_cache.osc_params));
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+			{
+				struct spectral_config *pparam =
+					(struct spectral_config *)output;
+
+				qdf_print("%s: OL_SPECTRAL_INFO_SPEC_PARAMS. "
+						"Returning following params:\n"
+						"ss_count = %u\n"
+						"ss_period = %u\n"
+						"ss_spectral_pri = %u\n"
+						"ss_fft_size = %u\n"
+						"ss_gc_ena = %u\n"
+						"ss_restart_ena = %u\n"
+						"ss_noise_floor_ref = %d\n"
+						"ss_init_delay = %u\n"
+						"ss_nb_tone_thr = %u\n"
+						"ss_str_bin_thr = %u\n"
+						"ss_wb_rpt_mode = %u\n"
+						"ss_rssi_rpt_mode = %u\n"
+						"ss_rssi_thr = %d\n"
+						"ss_pwr_format = %u\n"
+						"ss_rpt_mode = %u\n"
+						"ss_bin_scale = %u\n"
+						"ss_dBm_adj = %u\n"
+						"ss_chn_mask = %u\n\n",
+						__func__,
+						pparam->ss_count,
+						pparam->ss_period,
+						pparam->ss_spectral_pri,
+						pparam->ss_fft_size,
+						pparam->ss_gc_ena,
+						pparam->ss_restart_ena,
+					(int8_t)pparam->ss_noise_floor_ref,
+						pparam->ss_init_delay,
+						pparam->ss_nb_tone_thr,
+						pparam->ss_str_bin_thr,
+						pparam->ss_wb_rpt_mode,
+						pparam->ss_rssi_rpt_mode,
+						(int8_t)pparam->ss_rssi_thr,
+						pparam->ss_pwr_format,
+						pparam->ss_rpt_mode,
+						pparam->ss_bin_scale,
+						pparam->ss_dBm_adj,
+						pparam->ss_chn_mask);
+			}
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+			break;
+
+			default:
+				/* We can't reach this point */
+				break;
+			}
+			qdf_spin_unlock(&info->osps_lock);
+			return 0;
+		}
+	}
+
+	/* Cache is invalid */
+
+	/* If WMI Reads are implemented to fetch defaults/non-cacheable info,
+	 * then the below implementation will change
+	 */
+	init_def_retval = target_if_spectral_info_init_defaults(spectral);
+	if (init_def_retval != QDF_STATUS_SUCCESS) {
+		if (init_def_retval == QDF_STATUS_E_NOENT)
+			return -ENOENT;
+		else
+			return -EINVAL;
+	}
+	/* target_if_spectral_info_init_defaults() has set cache to valid */
+
+	switch (specifier) {
+	case OL_SPECTRAL_INFO_SPEC_ACTIVE:
+		qdf_mem_copy(output,
+			     &info->osps_cache.osc_spectral_active,
+			     sizeof(info->osps_cache.osc_spectral_active));
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+		qdf_print("%s: OL_SPECTRAL_INFO_SPEC_ACTIVE on "
+				"initial cache validation\n"
+				"Returning val=%u\n",
+				__func__,
+			*((unsigned char *)output));
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+		break;
+
+	case OL_SPECTRAL_INFO_SPEC_ENABLED:
+		qdf_mem_copy(output,
+			     &info->osps_cache.osc_spectral_enabled,
+			     sizeof(info->osps_cache.osc_spectral_enabled));
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+		qdf_print("%s: OL_SPECTRAL_INFO_SPEC_ENABLED on "
+				"initial cache validation\n"
+				"Returning val=%u\n",
+				__func__,
+			*((unsigned char *)output));
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+		break;
+
+	case OL_SPECTRAL_INFO_SPEC_PARAMS:
+		qdf_mem_copy(output,
+			     &info->osps_cache.osc_params,
+			     sizeof(info->osps_cache.osc_params));
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+		{
+		struct spectral_config *pparam =
+			(struct spectral_config *)output;
+
+		qdf_print("%s: OL_SPECTRAL_INFO_SPEC_PARAMS on "
+				"initial cache validation\n"
+				"Returning following params:\n"
+				"ss_count = %u\n"
+				"ss_period = %u\n"
+				"ss_spectral_pri = %u\n"
+				"ss_fft_size = %u\n"
+				"ss_gc_ena = %u\n"
+				"ss_restart_ena = %u\n"
+				"ss_noise_floor_ref = %d\n"
+				"ss_init_delay = %u\n"
+				"ss_nb_tone_thr = %u\n"
+				"ss_str_bin_thr = %u\n"
+				"ss_wb_rpt_mode = %u\n"
+				"ss_rssi_rpt_mode = %u\n"
+				"ss_rssi_thr = %d\n"
+				"ss_pwr_format = %u\n"
+				"ss_rpt_mode = %u\n"
+				"ss_bin_scale = %u\n"
+				"ss_dBm_adj = %u\n"
+				"ss_chn_mask = %u\n\n",
+				__func__,
+				pparam->ss_count,
+				pparam->ss_period,
+				pparam->ss_spectral_pri,
+				pparam->ss_fft_size,
+				pparam->ss_gc_ena,
+				pparam->ss_restart_ena,
+				(int8_t)pparam->ss_noise_floor_ref,
+				pparam->ss_init_delay,
+				pparam->ss_nb_tone_thr,
+				pparam->ss_str_bin_thr,
+				pparam->ss_wb_rpt_mode,
+				pparam->ss_rssi_rpt_mode,
+				(int8_t)pparam->ss_rssi_thr,
+				pparam->ss_pwr_format,
+				pparam->ss_rpt_mode,
+				pparam->ss_bin_scale,
+				pparam->ss_dBm_adj,
+				pparam->ss_chn_mask);
+		}
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+
+		break;
+
+	default:
+		/* We can't reach this point */
+		break;
+	}
+
+	qdf_spin_unlock(&info->osps_lock);
+
+	return 0;
+}
+
+/**
+ * ol_spectral_info_write() - Write Spectral parameters or the desired state
+ * information to the firmware, and update cache
+ * @spectral: Pointer to Spectral target_if internal private data
+ * @specifier: ol_spectral_info_spec enumeration specifying which information is
+ * involved
+ * @input: void input pointer containing the information to be written
+ * @input_len: size of object pointed to by input pointer
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int ol_spectral_info_write(struct target_if_spectral *spectral,
+			   enum ol_spectral_info_spec specifier,
+				void *input,
+				int input_len)
+{
+	struct target_if_spectral_param_state_info *info = &spectral->ol_info;
+	int ret;
+	u_int8_t *pval = NULL;
+	struct spectral_config *param = NULL;
+
+	if (!input)
+		return -EINVAL;
+
+		switch (specifier) {
+		case OL_SPECTRAL_INFO_SPEC_ACTIVE:
+			if (input_len !=
+				sizeof(info->osps_cache.osc_spectral_active))
+				return -EINVAL;
+
+			pval = (u_int8_t *)input;
+
+			qdf_spin_lock(&info->osps_lock);
+			ret = wmi_send_vdev_spectral_enable_cmd(
+				spectral,
+				 1,
+				 *pval,
+				 0,
+				 0);
+
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+			qdf_print("%s: OL_SPECTRAL_INFO_SPEC_ACTIVE with "
+					"val=%u status=%d\n",
+					__func__,
+				*pval,
+					ret);
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+
+			if (ret < 0) {
+				qdf_print(
+				  "%s: wmi_send_vdev_spectral_enable_cmd "
+				  "failed with error=%d\n",
+				  __func__,
+				  ret);
+				qdf_spin_unlock(&info->osps_lock);
+				return ret;
+			}
+
+			info->osps_cache.osc_spectral_active = *pval;
+			qdf_spin_unlock(&info->osps_lock);
+			break;
+
+		case OL_SPECTRAL_INFO_SPEC_ENABLED:
+			if (input_len !=
+				sizeof(info->osps_cache.osc_spectral_enabled))
+				return -EINVAL;
+
+			pval = (u_int8_t *)input;
+
+			qdf_spin_lock(&info->osps_lock);
+			ret = wmi_send_vdev_spectral_enable_cmd(
+				spectral,
+				 0,
+				 0,
+				 1,
+				 *pval);
+
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+			qdf_print("%s: OL_SPECTRAL_INFO_SPEC_ENABLED with "
+					"val=%u status=%d\n",
+					__func__,
+				*pval,
+					ret);
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+
+			if (ret < 0) {
+				qdf_print(
+				  "%s: wmi_send_vdev_spectral_enable_cmd "
+				  "failed with error=%d\n",
+				  __func__,
+				  ret);
+				qdf_spin_unlock(&info->osps_lock);
+				return ret;
+			}
+
+			info->osps_cache.osc_spectral_enabled = *pval;
+			qdf_spin_unlock(&info->osps_lock);
+			break;
+
+		case OL_SPECTRAL_INFO_SPEC_PARAMS:
+			if (input_len != sizeof(info->osps_cache.osc_params))
+				return -EINVAL;
+
+			param = (struct spectral_config *)input;
+
+			qdf_spin_lock(&info->osps_lock);
+			ret = wmi_send_vdev_spectral_configure_cmd(
+				spectral,
+				 param);
+
+#ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS
+			qdf_print("%s: OL_SPECTRAL_INFO_SPEC_PARAMS. "
+					"Params:\n"
+					"ss_count = %u\n"
+					"ss_period = %u\n"
+					"ss_spectral_pri = %u\n"
+					"ss_fft_size = %u\n"
+					"ss_gc_ena = %u\n"
+					"ss_restart_ena = %u\n"
+					"ss_noise_floor_ref = %d\n"
+					"ss_init_delay = %u\n"
+					"ss_nb_tone_thr = %u\n"
+					"ss_str_bin_thr = %u\n"
+					"ss_wb_rpt_mode = %u\n"
+					"ss_rssi_rpt_mode = %u\n"
+					"ss_rssi_thr = %d\n"
+					"ss_pwr_format = %u\n"
+					"ss_rpt_mode = %u\n"
+					"ss_bin_scale = %u\n"
+					"ss_dBm_adj = %u\n"
+					"ss_chn_mask = %u\n"
+					"status = %d\n\n",
+					__func__,
+					param->ss_count,
+					param->ss_period,
+					param->ss_spectral_pri,
+					param->ss_fft_size,
+					param->ss_gc_ena,
+					param->ss_restart_ena,
+					(int8_t)param->ss_noise_floor_ref,
+					param->ss_init_delay,
+					param->ss_nb_tone_thr,
+					param->ss_str_bin_thr,
+					param->ss_wb_rpt_mode,
+					param->ss_rssi_rpt_mode,
+					(int8_t)param->ss_rssi_thr,
+					param->ss_pwr_format,
+					param->ss_rpt_mode,
+					param->ss_bin_scale,
+					param->ss_dBm_adj,
+					param->ss_chn_mask,
+					ret);
+#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */
+
+			if (ret < 0) {
+				qdf_print(
+				  "%s: wmi_send_vdev_spectral_configure_cmd "
+				  "failed with error=%d\n",
+				  __func__,
+				  ret);
+				qdf_spin_unlock(&info->osps_lock);
+				return ret;
+			}
+
+			qdf_mem_copy(&info->osps_cache.osc_params,
+				     param,
+				     sizeof(info->osps_cache.osc_params));
+			qdf_spin_unlock(&info->osps_lock);
+			break;
+
+		default:
+			qdf_print("%s: Unknown OL_SPECTRAL_INFO_SPEC_T "
+				  "specifier\n",
+				  __func__);
+			return -EINVAL;
+		}
+
+	return 0;
+}
+
+/**
+ * target_if_spectral_get_tsf64() - Get the last TSF received in WMI buffer
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * Return: TSF value
+ */
+static u_int64_t target_if_spectral_get_tsf64(void *arg)
+{
+	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
+
+	return spectral->tsf64;
+}
+
+/**
+ * target_if_spectral_get_capability() - Get whether a given Spectral hardware
+ * capability is available
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ * @type: Spectral hardware capability type
+ *
+ * Return: True if the capability is available, false if the capability is not
+ * available
+ */
+u_int32_t target_if_spectral_get_capability(
+	void *arg,
+	 SPECTRAL_CAPABILITY_TYPE type)
+{
+	int status = STATUS_FAIL;
+
+	switch (type) {
+	case SPECTRAL_CAP_PHYDIAG:
+	case SPECTRAL_CAP_RADAR:
+	case SPECTRAL_CAP_SPECTRAL_SCAN:
+	case SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN:
+		status = STATUS_PASS;
+		break;
+	default:
+		status = STATUS_FAIL;
+	}
+	return status;
+}
+
+/**
+ * target_if_spectral_set_rxfilter() - Set the RX Filter before Spectral start
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ * @rxfilter: Rx filter to be used
+ *
+ * Note: This is only a placeholder function. It is not currently required since
+ * FW should be taking care of setting the required filters.
+ *
+ * Return: 0
+ */
+u_int32_t target_if_spectral_set_rxfilter(void *arg, int rxfilter)
+{
+	/* Will not be required since enabling of spectral in firmware
+	 * will take care of this
+	 */
+	return 0;
+}
+
+/**
+ * target_if_spectral_get_rxfilter() - Get the current RX Filter settings
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * Note: This is only a placeholder function. It is not currently required since
+ * FW should be taking care of setting the required filters.
+ *
+ * Return: 0
+ */
+u_int32_t target_if_spectral_get_rxfilter(void *arg)
+{
+	/* Will not be required since enabling of spectral in firmware
+	 * will take care of this
+	 */
+	return 0;
+}
+
+/**
+ * tgt_if_is_spectral_active() - Get whether Spectral is active
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * Return: True if Spectral is active, false if Spectral is not active
+ */
+u_int32_t tgt_if_is_spectral_active(void *arg)
+{
+	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
+	u_int8_t val = 0;
+	int ret;
+
+	ret = ol_spectral_info_read(spectral,
+				    OL_SPECTRAL_INFO_SPEC_ACTIVE,
+					&val,
+					sizeof(val));
+
+	if (ret != 0) {
+		/* Could not determine if Spectral is active.
+		 * Return false as a safe value.
+		 * XXX: Consider changing the function prototype
+		 * to be able to indicate failure to fetch value.
+		 */
+		return 0;
+	}
+
+	return val;
+}
+
+/**
+ * tgt_if_is_spectral_enabled() - Get whether Spectral is enabled
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * Return: True if Spectral is enabled, false if Spectral is not enabled
+ */
+u_int32_t tgt_if_is_spectral_enabled(void *arg)
+{
+	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
+	u_int8_t val = 0;
+	int ret;
+
+	ret = ol_spectral_info_read(spectral,
+				    OL_SPECTRAL_INFO_SPEC_ENABLED,
+					&val,
+					sizeof(val));
+
+	if (ret != 0) {
+		/* Could not determine if Spectral is enabled.
+		 * Return false as a safe value.
+		 * XXX: Consider changing the function prototype
+		 * to be able to indicate failure to fetch value.
+		 */
+		return 0;
+	}
+
+	return val;
+}
+
+/**
+ * tgt_if_start_spectral_scan() - Start Spectral scan
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * Return: 1 on success, 0 on failure
+ */
+u_int32_t tgt_if_start_spectral_scan(void *arg)
+{
+	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
+	u_int8_t val = 1;
+	u_int8_t enabled = 0;
+	int ret;
+
+	ret = ol_spectral_info_read(spectral,
+				    OL_SPECTRAL_INFO_SPEC_ENABLED,
+					&enabled,
+					sizeof(enabled));
+
+	if (ret != 0) {
+		/* Could not determine if Spectral is enabled. Assume we need
+		 * to enable it
+		 */
+		enabled = 0;
+	}
+
+	if (!enabled) {
+		ret = ol_spectral_info_write(spectral,
+					     OL_SPECTRAL_INFO_SPEC_ENABLED,
+							&val,
+							sizeof(val));
+
+		if (ret != 0)
+			return 0;
+	}
+
+	ret = ol_spectral_info_write(spectral,
+				     OL_SPECTRAL_INFO_SPEC_ACTIVE,
+						&val,
+						sizeof(val));
+
+	if (ret != 0)
+		return 0;
+
+	return 1;
+}
+
+/**
+ * tgt_if_stop_spectral_scan() - Stop Spectral scan
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * Return: 1 on success, 0 on failure
+ */
+u_int32_t tgt_if_stop_spectral_scan(void *arg)
+{
+	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
+	u_int8_t val = 0;
+	int tempret, ret = 1;
+
+	tempret = ol_spectral_info_write(spectral,
+					 OL_SPECTRAL_INFO_SPEC_ACTIVE,
+						&val,
+						sizeof(val));
+
+	if (tempret != 0)
+		ret = 0;
+
+	tempret = ol_spectral_info_write(spectral,
+					 OL_SPECTRAL_INFO_SPEC_ENABLED,
+						&val,
+						sizeof(val));
+
+	if (tempret != 0)
+		ret = 0;
+
+	return ret;
+}
+
+/**
+ * target_if_spectral_get_extension_channel() - Get the current Extension
+ *                                              channel (in MHz)
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * Return: Current Extension channel (in MHz) on success, 0 on failure or if
+ * extension channel is not present.
+ */
+u_int32_t target_if_spectral_get_extension_channel(void *arg)
+{
+	/* XXX: Once we expand to use cases where Spectral could be activated
+	 * without a channel being set to VDEV, we need to consider returning a
+	 * negative value in case of failure and having all callers handle this.
+	 */
+
+	struct target_if_spectral *spectral = NULL;
+	struct wlan_objmgr_vdev *vdev = NULL;
+	u_int16_t sec20chan_freq = 0;
+
+	qdf_assert_always(arg);
+	spectral = (struct target_if_spectral *)arg;
+
+	vdev = target_if_spectral_get_vdev(spectral);
+	if (!vdev)
+		return 0;
+
+	if (wlan_vdev_get_sec20chan_freq_mhz(vdev, &sec20chan_freq) < 0) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+		return 0;
+	}
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+	return sec20chan_freq;
+}
+
+/**
+ * target_if_spectral_get_current_channel() - Get the current channel (in MHz)
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * Return: Current channel (in MHz) on success, 0 on failure
+ */
+u_int32_t target_if_spectral_get_current_channel(void *arg)
+{
+	/* XXX: Once we expand to use cases where Spectral could be activated
+	 * without a channel being set to VDEV, we need to consider returning a
+	 * negative value in case of failure and having all callers handle this.
+	 */
+
+	struct target_if_spectral *spectral = NULL;
+	int16_t chan_freq = 0;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	qdf_assert_always(arg);
+	spectral = (struct target_if_spectral *)arg;
+
+	vdev = target_if_spectral_get_vdev(spectral);
+	if (!vdev)
+		return 0;
+
+	chan_freq = wlan_vdev_get_chan_freq(vdev);
+	if (chan_freq < 0) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+		return 0;
+	}
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+	return chan_freq;
+}
+
+/**
+ * target_if_spectral_reset_hw() - Reset the hardware
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * This is only a placeholder since it is not currently required in the offload
+ * case.
+ *
+ * Return: 0
+ */
+u_int32_t target_if_spectral_reset_hw(void *arg)
+{
+	not_yet_implemented();
+	return 0;
+}
+
+/**
+ * target_if_spectral_get_chain_noise_floor() - Get the Chain noise floor from
+ * Noisefloor history buffer
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ * @nf_buf: Pointer to buffer into which chain Noise Floor data should be copied
+ *
+ * This is only a placeholder since it is not currently required in the offload
+ * case.
+ *
+ * Return: 0
+ */
+u_int32_t target_if_spectral_get_chain_noise_floor(void *arg, int16_t *nf_buf)
+{
+	not_yet_implemented();
+	return 0;
+}
+
+/**
+ * target_if_spectral_get_ext_noisefloor() - Get the extension channel
+ * noisefloor
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * This is only a placeholder since it is not currently required in the offload
+ * case.
+ *
+ * Return: 0
+ */
+int8_t target_if_spectral_get_ext_noisefloor(void *arg)
+{
+	not_yet_implemented();
+	return 0;
+}
+
+/**
+ * target_if_spectral_get_ctl_noisefloor() - Get the control channel noisefloor
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * This is only a placeholder since it is not currently required in the offload
+ * case.
+ *
+ * Return: 0
+ */
+int8_t target_if_spectral_get_ctl_noisefloor(void *arg)
+{
+	not_yet_implemented();
+	return 0;
+}
+
+/**
+ * target_if_spectral_configure_params() - Configure user supplied Spectral
+ *                                         parameters
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ * @params: Spectral parameters
+ *
+ * Return: 1 on success, 0 on failure.
+ */
+u_int32_t target_if_spectral_configure_params(
+	void *arg,
+	 struct spectral_config *params)
+{
+	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
+	int ret;
+
+	ret = ol_spectral_info_write(spectral,
+				     OL_SPECTRAL_INFO_SPEC_PARAMS,
+						params,
+						sizeof(*params));
+
+	if (ret != 0)
+		return 0;
+
+	return 1;
+}
+
+/**
+ * target_if_spectral_get_params() - Get user configured Spectral parameters
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ * @params: Pointer to buffer into which Spectral parameters should be copied
+ *
+ * Return: 1 on success, 0 on failure.
+ */
+u_int32_t target_if_spectral_get_params(
+	void *arg,
+	 struct spectral_config *params)
+{
+	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
+	int ret;
+
+	ret = ol_spectral_info_read(spectral,
+				    OL_SPECTRAL_INFO_SPEC_PARAMS,
+					params,
+					sizeof(*params));
+
+	if (ret != 0)
+		return 0;
+
+	return 1;
+}
+
+/**
+ * target_if_spectral_get_ent_mask() - Get enterprise mask
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ *
+ * This is only a placeholder since it is not currently required in the offload
+ * case.
+ *
+ * Return: 0
+ */
+static u_int32_t target_if_spectral_get_ent_mask(void *arg)
+{
+	not_yet_implemented();
+	return 0;
+}
+
+/**
+ * target_if_spectral_get_macaddr() - Get radio MAC address
+ * @arg: Pointer to handle for Spectral target_if internal private data
+ * @addr: Pointer to buffer into which MAC address should be copied
+ *
+ * Return: 0 on success, -1 on failure
+ */
+static u_int32_t target_if_spectral_get_macaddr(void *arg, char *addr)
+{
+	uint8_t *myaddr = NULL;
+	struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
+	struct wlan_objmgr_pdev *pdev = NULL;
+
+	pdev = spectral->pdev_obj;
+
+	wlan_pdev_obj_lock(pdev);
+	myaddr = wlan_pdev_get_hw_macaddr(pdev);
+	wlan_pdev_obj_unlock(pdev);
+	qdf_mem_copy(addr, myaddr, IEEE80211_ADDR_LEN);
+
+	return 0;
+}
+
+/**
+ * init_spectral_capability() - Initialize Spectral capability
+ * @spectral: Pointer to Spectral target_if internal private data
+ *
+ * This is a workaround.
+ *
+ * Return: None
+ */
+void init_spectral_capability(struct target_if_spectral *spectral)
+{
+	struct spectral_caps *pcap = &spectral->capability;
+
+	/* XXX : Workaround: Set Spectral capability */
+	pcap = &spectral->capability;
+	pcap->phydiag_cap = 1;
+	pcap->radar_cap = 1;
+	pcap->spectral_cap = 1;
+	pcap->advncd_spectral_cap = 1;
+}
+
+/**
+ * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal
+ * operations common to all Spectral chipset generations
+ *
+ * Return: None
+ */
+void target_if_init_spectral_ops_common(void)
+{
+	struct target_if_spectral_ops *p_sops = &spectral_ops;
+
+	p_sops->get_tsf64               = target_if_spectral_get_tsf64;
+	p_sops->get_capability          = target_if_spectral_get_capability;
+	p_sops->set_rxfilter            = target_if_spectral_set_rxfilter;
+	p_sops->get_rxfilter            = target_if_spectral_get_rxfilter;
+#if QCA_SUPPORT_SPECTRAL_SIMULATION
+	/* Spectral simulation is currently intended for platform transitions
+	 * where underlying HW support may not be available for some time.
+	 * Hence, we do not currently provide a runtime switch to turn the
+	 * simulation on or off.
+	 * In case of future requirements where runtime switches are required,
+	 * this can be added. But it is suggested to use application layer
+	 * simulation as far as possible in such cases, since the main
+	 * use of record and replay of samples would concern higher
+	 * level sample processing rather than lower level delivery.
+	 */
+	p_sops->is_spectral_enabled     = tif_spectral_sim_is_spectral_enabled;
+	p_sops->is_spectral_active      = tif_spectral_sim_is_spectral_active;
+	p_sops->start_spectral_scan     = tif_spectral_sim_start_spectral_scan;
+	p_sops->stop_spectral_scan      = tif_spectral_sim_stop_spectral_scan;
+	p_sops->configure_spectral      = tif_spectral_sim_configure_params;
+	p_sops->get_spectral_config     = tif_spectral_sim_get_params;
+#else
+	p_sops->is_spectral_enabled     = tgt_if_is_spectral_enabled;
+	p_sops->is_spectral_active      = tgt_if_is_spectral_active;
+	p_sops->start_spectral_scan     = tgt_if_start_spectral_scan;
+	p_sops->stop_spectral_scan      = tgt_if_stop_spectral_scan;
+	p_sops->configure_spectral      = target_if_spectral_configure_params;
+	p_sops->get_spectral_config     = target_if_spectral_get_params;
+#endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */
+	p_sops->get_extension_channel   =
+		target_if_spectral_get_extension_channel;
+	p_sops->get_ctl_noisefloor      =
+		target_if_spectral_get_ctl_noisefloor;
+	p_sops->get_ext_noisefloor      =
+		target_if_spectral_get_ext_noisefloor;
+	p_sops->get_ent_spectral_mask   = target_if_spectral_get_ent_mask;
+	p_sops->get_mac_address         = target_if_spectral_get_macaddr;
+	p_sops->get_current_channel     =
+		target_if_spectral_get_current_channel;
+	p_sops->reset_hw                = target_if_spectral_reset_hw;
+	p_sops->get_chain_noise_floor   =
+		target_if_spectral_get_chain_noise_floor;
+}
+
+/**
+ * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal
+ * operations specific to Spectral chipset generation 2.
+ *
+ * Return: None
+ */
+void target_if_init_spectral_ops_gen2(void)
+{
+	struct target_if_spectral_ops *p_sops = &spectral_ops;
+
+	p_sops->spectral_process_phyerr = spectral_process_phyerr_gen2;
+}
+
+/**
+ * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal
+ * operations specific to Spectral chipset generation 3.
+ *
+ * Return: None
+ */
+void target_if_init_spectral_ops_gen3(void)
+{
+	struct target_if_spectral_ops *p_sops = &spectral_ops;
+
+	p_sops->spectral_process_phyerr = spectral_process_phyerr_gen3;
+}
+
+/**
+ * target_if_init_spectral_ops() - Initialize target_if internal Spectral
+ * operations.
+ * @spectral: Pointer to Spectral target_if internal private data
+ *
+ * Return: None
+ */
+void target_if_init_spectral_ops(struct target_if_spectral *spectral)
+{
+	target_if_init_spectral_ops_common();
+	if (spectral->spectral_gen == SPECTRAL_GEN2)
+		target_if_init_spectral_ops_gen2();
+	else if (spectral->spectral_gen == SPECTRAL_GEN3)
+		target_if_init_spectral_ops_gen3();
+	else
+		qdf_print("Invalid spetral generation\n");
+}
+
+/*
+ * Dummy Functions:
+ * These functions are initially registered to avoid any crashes due to
+ * invocation of spectral functions before they are registered.
+ */
+
+static u_int64_t null_get_tsf64(void *arg)
+{
+	spectral_ops_not_registered("get_tsf64");
+	return 0;
+}
+
+static u_int32_t null_get_capability(void *arg, SPECTRAL_CAPABILITY_TYPE type)
+{
+	/*
+	 * TODO : We should have conditional compilation to get the capability
+	 *      : We have not yet attahced ATH layer here, so there is no
+	 *      : way to check the HAL capbalities
+	 */
+	spectral_ops_not_registered("get_capability");
+
+	/* TODO : For the time being, we are returning TRUE */
+	return true;
+}
+
+static u_int32_t null_set_rxfilter(void *arg, int rxfilter)
+{
+	spectral_ops_not_registered("set_rxfilter");
+	return 1;
+}
+
+static u_int32_t null_get_rxfilter(void *arg)
+{
+	spectral_ops_not_registered("get_rxfilter");
+	return 0;
+}
+
+static u_int32_t null_is_spectral_active(void *arg)
+{
+	spectral_ops_not_registered("is_spectral_active");
+	return 1;
+}
+
+static u_int32_t null_is_spectral_enabled(void *arg)
+{
+	spectral_ops_not_registered("is_spectral_enabled");
+	return 1;
+}
+
+static u_int32_t null_start_spectral_scan(void *arg)
+{
+	spectral_ops_not_registered("start_spectral_scan");
+	return 1;
+}
+
+static u_int32_t null_stop_spectral_scan(void *arg)
+{
+	spectral_ops_not_registered("stop_spectral_scan");
+	return 1;
+}
+
+static u_int32_t null_get_extension_channel(void *arg)
+{
+	spectral_ops_not_registered("get_extension_channel");
+	return 1;
+}
+
+static int8_t null_get_ctl_noisefloor(void *arg)
+{
+	spectral_ops_not_registered("get_ctl_noisefloor");
+	return 1;
+}
+
+static int8_t null_get_ext_noisefloor(void *arg)
+{
+	spectral_ops_not_registered("get_ext_noisefloor");
+	return 0;
+}
+
+static u_int32_t null_configure_spectral(
+	void *arg,
+	 struct spectral_config *params)
+{
+	spectral_ops_not_registered("configure_spectral");
+	return 0;
+}
+
+static u_int32_t null_get_spectral_config(
+	void *arg,
+	 struct spectral_config *params)
+{
+	spectral_ops_not_registered("get_spectral_config");
+	return 0;
+}
+
+static u_int32_t null_get_ent_spectral_mask(void *arg)
+{
+	spectral_ops_not_registered("get_ent_spectral_mask");
+	return 0;
+}
+
+static u_int32_t null_get_mac_address(void *arg, char *addr)
+{
+	spectral_ops_not_registered("get_mac_address");
+	return 0;
+}
+
+static u_int32_t null_get_current_channel(void *arg)
+{
+	spectral_ops_not_registered("get_current_channel");
+	return 0;
+}
+
+static u_int32_t null_reset_hw(void *arg)
+{
+	spectral_ops_not_registered("get_current_channel");
+	return 0;
+}
+
+static u_int32_t null_get_chain_noise_floor(void *arg, int16_t *nf_buf)
+{
+	spectral_ops_not_registered("get_chain_noise_floor");
+	return 0;
+}
+
+static int null_spectral_process_phyerr(
+	struct target_if_spectral *spectral,
+	u_int8_t *data,
+	u_int32_t datalen,
+	struct target_if_spectral_rfqual_info *p_rfqual,
+	struct target_if_spectral_chan_info *p_chaninfo,
+	u_int64_t tsf64,
+	struct target_if_spectral_acs_stats *acs_stats)
+{
+	spectral_ops_not_registered("spectral_process_phyerr");
+	return 0;
+}
+
+/**
+ * target_if_spectral_init_dummy_function_table() -
+ * Initialize target_if internal
+ * Spectral operations to dummy functions
+ * @ps: Pointer to Spectral target_if internal private data
+ *
+ * Return: None
+ */
+void target_if_spectral_init_dummy_function_table(
+	struct target_if_spectral *ps)
+{
+	struct target_if_spectral_ops *p_sops = GET_TIF_SPECTRAL_OPS(ps);
+
+	p_sops->get_tsf64               = null_get_tsf64;
+	p_sops->get_capability          = null_get_capability;
+	p_sops->set_rxfilter            = null_set_rxfilter;
+	p_sops->get_rxfilter            = null_get_rxfilter;
+	p_sops->is_spectral_enabled     = null_is_spectral_enabled;
+	p_sops->is_spectral_active      = null_is_spectral_active;
+	p_sops->start_spectral_scan     = null_start_spectral_scan;
+	p_sops->stop_spectral_scan      = null_stop_spectral_scan;
+	p_sops->get_extension_channel   = null_get_extension_channel;
+	p_sops->get_ctl_noisefloor      = null_get_ctl_noisefloor;
+	p_sops->get_ext_noisefloor      = null_get_ext_noisefloor;
+	p_sops->configure_spectral      = null_configure_spectral;
+	p_sops->get_spectral_config     = null_get_spectral_config;
+	p_sops->get_ent_spectral_mask   = null_get_ent_spectral_mask;
+	p_sops->get_mac_address         = null_get_mac_address;
+	p_sops->get_current_channel     = null_get_current_channel;
+	p_sops->reset_hw                = null_reset_hw;
+	p_sops->get_chain_noise_floor   = null_get_chain_noise_floor;
+	p_sops->spectral_process_phyerr = null_spectral_process_phyerr;
+}
+
+/**
+ * target_if_spectral_register_funcs() - Initialize target_if internal Spectral
+ * operations
+ * @spectral: Pointer to Spectral target_if internal private data
+ * @p: Pointer to Spectral function table
+ *
+ * Return: None
+ */
+void target_if_spectral_register_funcs(
+	struct target_if_spectral *spectral,
+	 struct target_if_spectral_ops *p)
+{
+	struct target_if_spectral_ops *p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+
+	p_sops->get_tsf64               = p->get_tsf64;
+	p_sops->get_capability          = p->get_capability;
+	p_sops->set_rxfilter            = p->set_rxfilter;
+	p_sops->get_rxfilter            = p->get_rxfilter;
+	p_sops->is_spectral_enabled     = p->is_spectral_enabled;
+	p_sops->is_spectral_active      = p->is_spectral_active;
+	p_sops->start_spectral_scan     = p->start_spectral_scan;
+	p_sops->stop_spectral_scan      = p->stop_spectral_scan;
+	p_sops->get_extension_channel   = p->get_extension_channel;
+	p_sops->get_ctl_noisefloor      = p->get_ctl_noisefloor;
+	p_sops->get_ext_noisefloor      = p->get_ext_noisefloor;
+	p_sops->configure_spectral      = p->configure_spectral;
+	p_sops->get_spectral_config     = p->get_spectral_config;
+	p_sops->get_ent_spectral_mask   = p->get_ent_spectral_mask;
+	p_sops->get_mac_address         = p->get_mac_address;
+	p_sops->get_current_channel     = p->get_current_channel;
+	p_sops->reset_hw                = p->reset_hw;
+	p_sops->get_chain_noise_floor   = p->get_chain_noise_floor;
+	p_sops->spectral_process_phyerr = p->spectral_process_phyerr;
+}
+
+/**
+ * target_if_spectral_clear_stats() - Clear Spectral stats
+ * @spectral: Pointer to Spectral target_if internal private data
+ *
+ * Return: None
+ */
+void target_if_spectral_clear_stats(struct target_if_spectral *spectral)
+{
+	struct target_if_spectral_ops *p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+
+	qdf_mem_zero(
+		&spectral->ath_spectral_stats,
+		 sizeof(struct target_if_spectral_stats));
+	spectral->ath_spectral_stats.last_reset_tstamp =
+		p_sops->get_tsf64(spectral);
+}
+
+/**
+ * target_if_spectral_check_hw_capability() - Check whether HW supports spectral
+ * @spectral: Pointer to Spectral target_if internal private data
+ *
+ * Return: True if HW supports Spectral, false if HW does not support Spectral
+ */
+int target_if_spectral_check_hw_capability(struct target_if_spectral *spectral)
+{
+	struct target_if_spectral_ops *p_sops = NULL;
+	struct spectral_caps *pcap  = NULL;
+	int is_spectral_supported = true;
+
+	p_sops      = GET_TIF_SPECTRAL_OPS(spectral);
+	pcap        = &spectral->capability;
+
+	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) {
+		is_spectral_supported = false;
+		qdf_print("SPECTRAL : No PHYDIAG support\n");
+		return is_spectral_supported;
+	}
+		pcap->phydiag_cap = 1;
+
+	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) {
+		is_spectral_supported = false;
+		qdf_print("SPECTRAL : No RADAR support\n");
+		return is_spectral_supported;
+	}
+		pcap->radar_cap = 1;
+
+	if (
+		p_sops->get_capability(spectral,
+		 SPECTRAL_CAP_SPECTRAL_SCAN) == false) {
+		is_spectral_supported = false;
+		qdf_print("SPECTRAL : No SPECTRAL SUPPORT\n");
+		return is_spectral_supported;
+	}
+		pcap->spectral_cap = 1;
+
+	if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN)
+				== false) {
+		qdf_print("SPECTRAL : No ADVANCED SPECTRAL SUPPORT\n");
+	} else {
+		pcap->advncd_spectral_cap = 1;
+	}
+
+	return is_spectral_supported;
+}
+
+/**
+ * target_if_pdev_spectral_init() - Initialize Spectral parameter defaults
+ * @spectral: Pointer to Spectral target_if internal private data
+ *
+ * It is the caller's responsibility to ensure that the Spectral parameters
+ * structure passed as part of Spectral target_if internal private data is
+ * valid.
+ *
+ * Return: None
+ */
+static void target_if_spectral_init_param_defaults(
+	struct target_if_spectral *spectral)
+{
+	struct spectral_config *params = &spectral->params;
+
+	params->ss_count = SPECTRAL_SCAN_COUNT_DEFAULT;
+	params->ss_period = SPECTRAL_SCAN_PERIOD_DEFAULT;
+	params->ss_spectral_pri = SPECTRAL_SCAN_PRIORITY_DEFAULT;
+	params->ss_fft_size = SPECTRAL_SCAN_FFT_SIZE_DEFAULT;
+	params->ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT;
+	params->ss_restart_ena = SPECTRAL_SCAN_RESTART_ENA_DEFAULT;
+	params->ss_noise_floor_ref = SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT;
+	params->ss_init_delay = SPECTRAL_SCAN_INIT_DELAY_DEFAULT;
+	params->ss_nb_tone_thr = SPECTRAL_SCAN_NB_TONE_THR_DEFAULT;
+	params->ss_str_bin_thr = SPECTRAL_SCAN_STR_BIN_THR_DEFAULT;
+	params->ss_wb_rpt_mode = SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT;
+	params->ss_rssi_rpt_mode = SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT;
+	params->ss_rssi_thr = SPECTRAL_SCAN_RSSI_THR_DEFAULT;
+	params->ss_pwr_format = SPECTRAL_SCAN_PWR_FORMAT_DEFAULT;
+	params->ss_rpt_mode = SPECTRAL_SCAN_RPT_MODE_DEFAULT;
+	params->ss_bin_scale = SPECTRAL_SCAN_BIN_SCALE_DEFAULT;
+	params->ss_dBm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT;
+	/*
+	 * XXX
+	 * SPECTRAL_SCAN_CHN_MASK_DEFAULT (0x1) specifies that chain 0 is to be
+	 * used
+	 * for Spectral. This is expected to be an optimal configuration for
+	 * most chipsets considering aspects like power save. But this can later
+	 * optionally be changed to be set to the default system Rx chainmask
+	 * advertised by FW (if required for some purpose), once the Convergence
+	 * framework supports such retrieval at pdev attach time.
+	 */
+	params->ss_chn_mask = SPECTRAL_SCAN_CHN_MASK_DEFAULT;
+	params->ss_short_report = SPECTRAL_SCAN_SHORT_REPORT_DEFAULT;
+	params->ss_fft_period = SPECTRAL_SCAN_FFT_PERIOD_DEFAULT;
+}
+
+/**
+ * target_if_spectral_detach() - De-initialize target_if Spectral
+ * @pdev: Pointer to pdev object
+ *
+ * Return: None
+ */
+static void target_if_spectral_detach(struct target_if_spectral *spectral)
+{
+	qdf_print("spectral detach\n");
+	qdf_spinlock_destroy(&spectral->ol_info.osps_lock);
+
+#if QCA_SUPPORT_SPECTRAL_SIMULATION
+	target_if_spectral_sim_detach(spectral);
+#endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */
+
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+	target_if_spectral_destroy_netlink(spectral);
+#endif
+
+	qdf_spinlock_destroy(&spectral->ath_spectral_lock);
+	qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock);
+
+	if (spectral) {
+		qdf_mem_free(spectral);
+		spectral = NULL;
+	}
+}
+
+/**
+ * target_if_pdev_spectral_init() - Initialize target_if Spectral
+ * functionality for the given pdev
+ * @pdev: Pointer to pdev object
+ *
+ * Return: On success, pointer to Spectral target_if internal private data, on
+ * failure, NULL
+ */
+void *target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral_ops *p_sops = NULL;
+	struct target_if_spectral *spectral = NULL;
+	struct ol_ath_softc_net80211 *scn = NULL;
+	struct pdev_osif_priv *osif_priv = NULL;
+
+	osif_priv = wlan_pdev_get_ospriv(pdev);
+	scn = (struct ol_ath_softc_net80211 *)osif_priv->legacy_osif_priv;
+	if (!scn) {
+		qdf_print("%s: scn is NULL!\n", __func__);
+		return NULL;
+	}
+
+	spectral = (struct target_if_spectral *)qdf_mem_malloc(
+			sizeof(struct target_if_spectral));
+	if (!spectral) {
+		qdf_print("SPECTRAL : Memory allocation failed\n");
+		return spectral;
+	}
+	qdf_mem_zero(spectral, sizeof(struct target_if_spectral));
+	/* Store pdev in Spectral */
+	spectral->pdev_obj = pdev;
+
+	/* init the function ptr table */
+	target_if_spectral_init_dummy_function_table(spectral);
+
+	/* get spectral function table */
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+	/* TODO : Should this be called here of after ath_attach ? */
+	if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG))
+		qdf_print(KERN_INFO "HAL_CAP_PHYDIAG : Capable\n");
+
+	SPECTRAL_TODO("Need to fix the capablity check for RADAR");
+	if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR))
+		qdf_print(KERN_INFO "HAL_CAP_RADAR   : Capable\n");
+
+	SPECTRAL_TODO("Need to fix the capablity check for SPECTRAL\n");
+	/* TODO : Should this be called here of after ath_attach ? */
+	if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN))
+		qdf_print(KERN_INFO "HAL_CAP_SPECTRAL_SCAN : Capable\n");
+
+	qdf_spinlock_create(&spectral->ath_spectral_lock);
+	qdf_spinlock_create(&spectral->noise_pwr_reports_lock);
+	target_if_spectral_clear_stats(spectral);
+
+	qdf_spinlock_create(&spectral->spectral_skbqlock);
+	STAILQ_INIT(&spectral->spectral_skbq);
+
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+	target_if_spectral_init_netlink(spectral);
+#endif
+
+	/* Set the default values for spectral parameters */
+	target_if_spectral_init_param_defaults(spectral);
+
+	if ((scn->soc->target_type == TARGET_TYPE_QCA8074) || (
+		scn->soc->target_type == TARGET_TYPE_QCA6290)) {
+		spectral->spectral_gen = SPECTRAL_GEN3;
+		spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3;
+		spectral->tag_sscan_summary_exp =
+			TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3;
+		spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3;
+		spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3;
+	} else {
+		 spectral->spectral_gen = SPECTRAL_GEN2;
+		 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2;
+		 spectral->tag_sscan_summary_exp =
+			TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2;
+		 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2;
+		 spectral->tlvhdr_size = sizeof(SPECTRAL_PHYERR_TLV_GEN2);
+	}
+
+#if QCA_SUPPORT_SPECTRAL_SIMULATION
+	if (target_if_spectral_sim_attach(spectral)) {
+		qdf_mem_free(spectral);
+		return NULL;
+	}
+#endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */
+	target_if_init_spectral_ops(spectral);
+
+	qdf_spinlock_create(&spectral->ol_info.osps_lock);
+	spectral->ol_info.osps_cache.osc_is_valid = 0;
+
+	target_if_spectral_register_funcs(spectral, &spectral_ops);
+
+	if (target_if_spectral_check_hw_capability(spectral) == false) {
+		target_if_spectral_detach(spectral);
+		spectral = NULL;
+	} else {
+		/* TODO: Once the driver architecture transitions to chipset
+		 * versioning based checks, reflect this here.
+		 */
+		spectral->is_160_format = false;
+		spectral->is_lb_edge_extrabins_format = false;
+		spectral->is_rb_edge_extrabins_format = false;
+
+		if (scn->soc->target_type == TARGET_TYPE_QCA9984 ||
+		    scn->soc->target_type == TARGET_TYPE_QCA9888) {
+			spectral->is_160_format = true;
+			spectral->is_lb_edge_extrabins_format = true;
+			spectral->is_rb_edge_extrabins_format = true;
+		} else  if ((scn->soc->target_type == TARGET_TYPE_AR900B) &&
+			    (scn->soc->target_revision == AR900B_REV_2)) {
+			spectral->is_rb_edge_extrabins_format = true;
+		}
+
+		if (scn->soc->target_type == TARGET_TYPE_QCA9984 ||
+		    scn->soc->target_type == TARGET_TYPE_QCA9888)
+			spectral->is_sec80_rssi_war_required = true;
+	}
+
+	return spectral;
+}
+
+/**
+ * target_if_pdev_spectral_init() - De-initialize target_if Spectral
+ * functionality for the given pdev
+ * @pdev: Pointer to pdev object
+ *
+ * Return: None
+ */
+static void target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		qdf_print("SPECTRAL : Module doesn't exist\n");
+		return;
+	}
+	target_if_spectral_detach(spectral);
+}
+
+/**
+ * target_if_set_spectral_config() - Set spectral config
+ * @pdev:       Pointer to pdev object
+ * @threshtype: config type
+ * @value:      config value
+ *
+ * API to set spectral configurations
+ *
+ * Return: 1 on success, 0 on failure
+ */
+static int target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev,
+					 const u_int32_t threshtype,
+						const u_int32_t value)
+{
+	struct spectral_config params;
+	struct target_if_spectral_ops *p_sops = NULL;
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+	if (!spectral) {
+		qdf_print("%s: spectral object is NULL\n", __func__);
+		return 0;
+	}
+
+	switch (threshtype) {
+	case SPECTRAL_PARAM_FFT_PERIOD:
+		spectral->params.ss_fft_period = value;
+		break;
+	case SPECTRAL_PARAM_SCAN_PERIOD:
+		spectral->params.ss_period = value;
+		break;
+	case SPECTRAL_PARAM_SCAN_COUNT:
+		spectral->params.ss_count = value;
+		break;
+	case SPECTRAL_PARAM_SHORT_REPORT:
+		spectral->params.ss_short_report = (!!value) ? true : false;
+		break;
+	case SPECTRAL_PARAM_SPECT_PRI:
+		spectral->params.ss_spectral_pri = (!!value) ? true : false;
+		break;
+	case SPECTRAL_PARAM_FFT_SIZE:
+		spectral->params.ss_fft_size = value;
+		break;
+	case SPECTRAL_PARAM_GC_ENA:
+		spectral->params.ss_gc_ena = !!value;
+		break;
+	case SPECTRAL_PARAM_RESTART_ENA:
+		spectral->params.ss_restart_ena = !!value;
+		break;
+	case SPECTRAL_PARAM_NOISE_FLOOR_REF:
+		spectral->params.ss_noise_floor_ref = value;
+		break;
+	case SPECTRAL_PARAM_INIT_DELAY:
+		spectral->params.ss_init_delay = value;
+		break;
+	case SPECTRAL_PARAM_NB_TONE_THR:
+		spectral->params.ss_nb_tone_thr = value;
+		break;
+	case SPECTRAL_PARAM_STR_BIN_THR:
+		spectral->params.ss_str_bin_thr = value;
+		break;
+	case SPECTRAL_PARAM_WB_RPT_MODE:
+		spectral->params.ss_wb_rpt_mode = !!value;
+		break;
+	case SPECTRAL_PARAM_RSSI_RPT_MODE:
+		spectral->params.ss_rssi_rpt_mode = !!value;
+		break;
+	case SPECTRAL_PARAM_RSSI_THR:
+		spectral->params.ss_rssi_thr = value;
+		break;
+	case SPECTRAL_PARAM_PWR_FORMAT:
+		spectral->params.ss_pwr_format = !!value;
+		break;
+	case SPECTRAL_PARAM_RPT_MODE:
+		spectral->params.ss_rpt_mode = value;
+		break;
+	case SPECTRAL_PARAM_BIN_SCALE:
+		spectral->params.ss_bin_scale = value;
+		break;
+	case SPECTRAL_PARAM_DBM_ADJ:
+		spectral->params.ss_dBm_adj = !!value;
+		break;
+	case SPECTRAL_PARAM_CHN_MASK:
+		spectral->params.ss_chn_mask = value;
+		break;
+	}
+
+	p_sops->configure_spectral(spectral, &spectral->params);
+	/* only to validate the writes */
+	p_sops->get_spectral_config(spectral, &params);
+	/* print_spectral_params(&spectral->params); */
+	return 1;
+}
+
+static int get_fft_bin_count(int fft_len)
+{
+	int bin_count = 0;
+
+	switch (fft_len) {
+	case 5:
+	bin_count = 16;
+	break;
+	case 6:
+	bin_count = 32;
+	break;
+	case 7:
+	bin_count = 64;
+	break;
+	case 8:
+	bin_count = 128;
+	break;
+	case 9:
+	bin_count = 256;
+	break;
+	default:
+	break;
+	}
+
+	return bin_count;
+}
+
+static void init_upper_lower_flags(struct target_if_spectral *spectral)
+{
+	int current_channel = 0;
+	int ext_channel = 0;
+	struct target_if_spectral_ops *p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+
+	current_channel = p_sops->get_current_channel(spectral);
+	ext_channel     = p_sops->get_extension_channel(spectral);
+
+	if ((current_channel == 0) || (ext_channel == 0))
+		return;
+
+	if (spectral->sc_spectral_20_40_mode) {
+		/* HT40 mode */
+		if (ext_channel < current_channel) {
+			spectral->lower_is_extension = 1;
+			spectral->upper_is_control   = 1;
+			spectral->lower_is_control   = 0;
+			spectral->upper_is_extension = 0;
+		} else {
+			spectral->lower_is_extension = 0;
+			spectral->upper_is_control   = 0;
+			spectral->lower_is_control   = 1;
+			spectral->upper_is_extension = 1;
+		}
+	} else {
+		/* HT20 mode, lower is always control */
+		spectral->lower_is_extension = 0;
+		spectral->upper_is_control   = 0;
+		spectral->lower_is_control   = 1;
+		spectral->upper_is_extension = 0;
+	}
+}
+
+/**
+ * target_if_get_spectral_config() - Get spectral configuration
+ * @pdev: Pointer to pdev object
+ * @param: Pointer to spectral_config structure in which the configuration
+ * should be returned
+ *
+ * API to get the current spectral configuration
+ *
+ * Return: 1 on success, 0 on failure.
+ */
+static void target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev,
+					  struct spectral_config *param)
+{
+	struct target_if_spectral_ops *p_sops = NULL;
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+
+	qdf_mem_zero(param, sizeof(struct spectral_config));
+	p_sops->get_spectral_config(spectral, param);
+}
+
+/**
+ * target_if_spectral_scan_enable_params() - Enable use of desired Spectral
+ *                                           parameters
+ * @spectral: Pointer to Spectral target_if internal private data
+ * @spectral_params: Pointer to Spectral parameters
+ *
+ * Enable use of desired Spectral parameters by configuring them into HW, and
+ * starting Spectral scan
+ *
+ * Return: 0 on success, 1 on failure
+ */
+static int target_if_spectral_scan_enable_params(
+	struct target_if_spectral *spectral,
+	struct spectral_config *spectral_params)
+{
+	int extension_channel   = 0;
+	int current_channel     = 0;
+	struct target_if_spectral_ops *p_sops    = NULL;
+	struct ol_ath_softc_net80211 *scn = NULL;
+	struct pdev_osif_priv *osif_priv = NULL;
+	struct wlan_objmgr_pdev *pdev = spectral->pdev_obj;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	osif_priv = wlan_pdev_get_ospriv(pdev);
+	scn = (struct ol_ath_softc_net80211 *)osif_priv->legacy_osif_priv;
+
+	if (!spectral) {
+		qdf_print("SPECTRAL : Spectral is NULL\n");
+		return 1;
+	}
+
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+
+	if (!p_sops) {
+		qdf_print("SPECTRAL : p_sops is NULL\n");
+		return 1;
+	}
+
+	spectral->sc_spectral_noise_pwr_cal =
+		spectral_params->ss_spectral_pri ? 1 : 0;
+
+	/* check if extension channel is present */
+	extension_channel   = p_sops->get_extension_channel(spectral);
+	current_channel     = p_sops->get_current_channel(spectral);
+
+	vdev = target_if_spectral_get_vdev(spectral);
+	if (!vdev)
+		return 1;
+
+	spectral->ch_width  = wlan_vdev_get_ch_width(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+	if (spectral->ch_width == CH_WIDTH_INVALID)
+		return 1;
+
+	if (spectral->capability.advncd_spectral_cap) {
+		spectral->lb_edge_extrabins = 0;
+		spectral->rb_edge_extrabins = 0;
+
+		if (spectral->is_lb_edge_extrabins_format &&
+		    spectral->params.ss_rpt_mode == 2) {
+			spectral->lb_edge_extrabins = 4;
+		}
+
+		if (spectral->is_rb_edge_extrabins_format &&
+		    spectral->params.ss_rpt_mode == 2) {
+			spectral->rb_edge_extrabins = 4;
+		}
+
+		if (spectral->ch_width == IEEE80211_CWM_WIDTH20) {
+			/* qdf_print("SPECTRAL : (11AC) 20MHz Channel Width
+			 * (Channel = %d)\n", current_channel);
+			 */
+			spectral->sc_spectral_20_40_mode    = 0;
+
+			spectral->spectral_numbins  =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			spectral->spectral_fft_len  =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			spectral->spectral_data_len =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			/* Initialize classifier params to be sent to user
+			 * space classifier
+			 */
+			spectral->classifier_params.lower_chan_in_mhz =
+				current_channel;
+			spectral->classifier_params.upper_chan_in_mhz = 0;
+
+		} else if (spectral->ch_width == IEEE80211_CWM_WIDTH40) {
+			/* qdf_print("SPECTRAL : (11AC) 40MHz Channel Width
+			 * (Channel = %d)\n", current_channel);
+			 */
+			spectral->sc_spectral_20_40_mode    =
+				1;    /* TODO : Remove this variable */
+			spectral->spectral_numbins  =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			spectral->spectral_fft_len  =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			spectral->spectral_data_len =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+
+			/* Initialize classifier params to be sent to user
+			 * space classifier
+			 */
+			if (extension_channel < current_channel) {
+				spectral->classifier_params.lower_chan_in_mhz =
+					extension_channel;
+				spectral->classifier_params.upper_chan_in_mhz =
+					current_channel;
+			} else {
+				spectral->classifier_params.lower_chan_in_mhz =
+					current_channel;
+				spectral->classifier_params.upper_chan_in_mhz =
+					extension_channel;
+			}
+
+		} else if (spectral->ch_width == IEEE80211_CWM_WIDTH80) {
+			/* qdf_print("SPECTRAL : (11AC) 80MHz Channel Width
+			 * (Channel = %d)\n", current_channel);
+			 */
+			/* Set the FFT Size */
+			spectral->sc_spectral_20_40_mode    =
+				0;    /* TODO : Remove this variable */
+			spectral->spectral_numbins  =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			spectral->spectral_fft_len  =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			spectral->spectral_data_len =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+
+			/* Initialize classifier params to be sent to user
+			 * space classifier
+			 */
+			spectral->classifier_params.lower_chan_in_mhz =
+				current_channel;
+			spectral->classifier_params.upper_chan_in_mhz = 0;
+
+			/* Initialize classifier params to be sent to user
+			 * space classifier
+			 */
+			if (extension_channel < current_channel) {
+				spectral->classifier_params.lower_chan_in_mhz =
+					extension_channel;
+				spectral->classifier_params.upper_chan_in_mhz =
+					current_channel;
+			} else {
+				spectral->classifier_params.lower_chan_in_mhz =
+					current_channel;
+				spectral->classifier_params.upper_chan_in_mhz =
+					extension_channel;
+			}
+
+		} else if (spectral->ch_width == IEEE80211_CWM_WIDTH160) {
+			/* qdf_print("SPECTRAL : (11AC) 160MHz Channel Width
+			 * (Channel = %d)\n", current_channel);
+			 */
+			/* Set the FFT Size */
+
+			/* The below applies to both 160 and 80+80 cases */
+
+			spectral->sc_spectral_20_40_mode    =
+				0;    /* TODO : Remove this variable */
+			spectral->spectral_numbins  =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			spectral->spectral_fft_len  =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+			spectral->spectral_data_len =
+			  get_fft_bin_count(spectral->params.ss_fft_size);
+
+			/* Initialize classifier params to be sent to user
+			 * space classifier
+			 */
+			spectral->classifier_params.lower_chan_in_mhz =
+				current_channel;
+			spectral->classifier_params.upper_chan_in_mhz = 0;
+
+			/* Initialize classifier params to be sent to user
+			 * space classifier
+			 */
+			if (extension_channel < current_channel) {
+				spectral->classifier_params.lower_chan_in_mhz =
+					extension_channel;
+				spectral->classifier_params.upper_chan_in_mhz =
+					current_channel;
+			} else {
+				spectral->classifier_params.lower_chan_in_mhz =
+					current_channel;
+				spectral->classifier_params.upper_chan_in_mhz =
+					extension_channel;
+			}
+		}
+
+		if (spectral->spectral_numbins) {
+			spectral->spectral_numbins +=
+				spectral->lb_edge_extrabins;
+			spectral->spectral_numbins +=
+				spectral->rb_edge_extrabins;
+		}
+
+		if (spectral->spectral_fft_len) {
+			spectral->spectral_fft_len +=
+				spectral->lb_edge_extrabins;
+			spectral->spectral_fft_len +=
+				spectral->rb_edge_extrabins;
+		}
+
+		if (spectral->spectral_data_len) {
+			spectral->spectral_data_len +=
+				spectral->lb_edge_extrabins;
+			spectral->spectral_data_len +=
+				spectral->rb_edge_extrabins;
+		}
+	} else {
+		/* qdf_print("SPECTRAL : Legacy (Non-11AC)\n"); */
+		/*
+		 * The decision to find 20/40 mode is found based on the
+		 * presence of extension channel
+		 * instead of channel width, as the channel width can
+		 * dynamically change
+		 */
+
+		if (extension_channel == 0) {
+			/* qdf_print("SPECTRAL : (Legacy) 20MHz Channel Width
+			 * (Channel = %d)\n", current_channel);
+			 */
+			spectral->spectral_numbins                  =
+				SPECTRAL_HT20_NUM_BINS;
+			spectral->spectral_dc_index                 =
+				SPECTRAL_HT20_DC_INDEX;
+			spectral->spectral_fft_len                  =
+				SPECTRAL_HT20_FFT_LEN;
+			spectral->spectral_data_len                 =
+				SPECTRAL_HT20_TOTAL_DATA_LEN;
+			spectral->spectral_lower_max_index_offset   =
+				-1; /* only valid in 20-40 mode */
+			spectral->spectral_upper_max_index_offset   =
+				-1; /* only valid in 20-40 mode */
+			spectral->spectral_max_index_offset         =
+				spectral->spectral_fft_len + 2;
+			spectral->sc_spectral_20_40_mode            = 0;
+
+			/* Initialize classifier params to be sent to user
+			 * space classifier
+			 */
+			spectral->classifier_params.lower_chan_in_mhz =
+				current_channel;
+			spectral->classifier_params.upper_chan_in_mhz = 0;
+
+		} else {
+			/* qdf_print("SPECTRAL : (Legacy) 40MHz Channel Width
+			 * (Channel = %d)\n", current_channel);
+			 */
+			spectral->spectral_numbins                  =
+				SPECTRAL_HT40_TOTAL_NUM_BINS;
+			spectral->spectral_fft_len                  =
+				SPECTRAL_HT40_FFT_LEN;
+			spectral->spectral_data_len                 =
+				SPECTRAL_HT40_TOTAL_DATA_LEN;
+			spectral->spectral_dc_index                 =
+				SPECTRAL_HT40_DC_INDEX;
+			spectral->spectral_max_index_offset         =
+				-1; /* only valid in 20 mode */
+			spectral->spectral_lower_max_index_offset   =
+				spectral->spectral_fft_len + 2;
+			spectral->spectral_upper_max_index_offset   =
+				spectral->spectral_fft_len + 5;
+			spectral->sc_spectral_20_40_mode            = 1;
+
+			/* Initialize classifier params to be sent to user
+			 * space classifier
+			 */
+			if (extension_channel < current_channel) {
+				spectral->classifier_params.lower_chan_in_mhz =
+					extension_channel;
+				spectral->classifier_params.upper_chan_in_mhz =
+					current_channel;
+			} else {
+				spectral->classifier_params.lower_chan_in_mhz =
+					current_channel;
+				spectral->classifier_params.upper_chan_in_mhz =
+					extension_channel;
+			}
+		}
+	}
+
+	spectral->send_single_packet                    = 0;
+	spectral->classifier_params.spectral_20_40_mode =
+		spectral->sc_spectral_20_40_mode;
+	spectral->classifier_params.spectral_dc_index   =
+		spectral->spectral_dc_index;
+	spectral->spectral_sent_msg                     = 0;
+	spectral->classify_scan                         = 0;
+	spectral->num_spectral_data                     = 0;
+
+	if (!p_sops->is_spectral_active(spectral)) {
+		p_sops->configure_spectral(spectral, spectral_params);
+		p_sops->start_spectral_scan(spectral);
+		/* qdf_print("Enabled spectral scan on channel %d\n",
+		 * p_sops->get_current_channel(spectral));
+		 */
+	} else {
+		/* qdf_print("Spectral scan is already ACTIVE on channel %d\n",
+		 * p_sops->get_current_channel(spectral));
+		 */
+	}
+
+	/* get current spectral configuration */
+	p_sops->get_spectral_config(spectral, &spectral->params);
+
+	init_upper_lower_flags(spectral);
+
+#ifdef SPECTRAL_CLASSIFIER_IN_KERNEL
+	init_classifier(sc);
+#endif
+	return 0;
+}
+
+/**
+ * target_if_start_spectral_scan() - Start spectral scan
+ * @pdev: Pointer to pdev object
+ *
+ * API to start spectral scan
+ *
+ * Return: 0 in case of success, -1 on failure
+ */
+static int target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral_ops *p_sops = NULL;
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		qdf_print("SPECTRAL : Spectral LMAC object is NUll  (%s)\n",
+			  __func__);
+		return -EPERM;
+	}
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+
+	qdf_spin_lock(&spectral->ath_spectral_lock);
+	target_if_spectral_scan_enable_params(spectral, &spectral->params);
+	qdf_spin_unlock(&spectral->ath_spectral_lock);
+
+	return 0;
+}
+
+/**
+ * target_if_stop_spectral_scan() - Stop spectral scan
+ * @pdev: Pointer to pdev object
+ *
+ * API to stop the current on-going spectral scan
+ *
+ * Return: None
+ */
+void target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral_ops *p_sops = NULL;
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		qdf_print("SPECTRAL : Spectral LMAC object is NUll  (%s)\n",
+			  __func__);
+		return;
+	}
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+
+	qdf_spin_lock(&spectral->ath_spectral_lock);
+	p_sops->stop_spectral_scan(spectral);
+	if (spectral->classify_scan) {
+		SPECTRAL_TODO("Check if this logic is necessary");
+		spectral->detects_control_channel   = 0;
+		spectral->detects_extension_channel = 0;
+		spectral->detects_above_dc          = 0;
+		spectral->detects_below_dc          = 0;
+		spectral->classify_scan             = 0;
+	}
+
+	spectral->send_single_packet        = 0;
+	spectral->sc_spectral_scan          = 0;
+	spectral->sc_spectral_noise_pwr_cal = 0;
+
+	/*
+	 * Reset the priority because it stops WLAN rx.
+	 * If it is needed to set, user has to set it explicitly
+	 *
+	 */
+	/* Reset Priority */
+	spectral->params.ss_spectral_pri    = 0;
+	qdf_spin_unlock(&spectral->ath_spectral_lock);
+}
+
+/**
+ * target_if_is_spectral_active() - Get whether Spectral is active
+ * @pdev: Pointer to pdev object
+ *
+ * Return: True if Spectral is active, false if Spectral is not active
+ */
+static bool target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral *spectral = NULL;
+	struct target_if_spectral_ops *p_sops = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+	return p_sops->is_spectral_active(spectral);
+}
+
+/**
+ * target_if_is_spectral_enabled() - Get whether Spectral is enabled
+ * @pdev: Pointer to pdev object
+ *
+ * Return: True if Spectral is enabled, false if Spectral is not enabled
+ */
+static bool target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral *spectral = NULL;
+	struct target_if_spectral_ops *p_sops = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+	return p_sops->is_spectral_enabled(spectral);
+}
+
+/**
+ * target_if_set_debug_level() - Set debug level for Spectral
+ * @pdev: Pointer to pdev object
+ * @debug_level: Debug level
+ *
+ * Return: 0 in case of success
+ */
+static int target_if_set_debug_level(struct wlan_objmgr_pdev *pdev,
+				     u_int32_t debug_level)
+{
+	spectral_debug_level = (ATH_DEBUG_SPECTRAL << debug_level);
+	return 0;
+}
+
+/**
+ * target_if_get_debug_level() - Get debug level for Spectral
+ * @pdev: Pointer to pdev object
+ *
+ * Return: Current debug level
+ */
+static u_int32_t target_if_get_debug_level(struct wlan_objmgr_pdev *pdev)
+{
+	qdf_print("target_if_get_debug_level is unimplemented\n");
+	return 0;
+}
+
+/**
+ * target_if_get_spectral_capinfo() - Get Spectral capability information
+ * @pdev: Pointer to pdev object
+ * @outdata: Buffer into which data should be copied
+ *
+ * Return: void
+ */
+static void target_if_get_spectral_capinfo(
+	struct wlan_objmgr_pdev *pdev,
+	 void *outdata)
+{
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	qdf_mem_copy(outdata, &spectral->capability,
+		     sizeof(struct spectral_caps));
+}
+
+/**
+ * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics
+ * @pdev:  Pointer to pdev object
+ * @outdata: Buffer into which data should be copied
+ *
+ * Return: void
+ */
+static void target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev,
+					     void *outdata)
+{
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	qdf_mem_copy(outdata, &spectral->diag_stats,
+		     sizeof(struct spectral_diag_stats));
+}
+
+/**
+ * target_if_sptrl_register_tx_ops() - Register Spectral target_if Tx Ops
+ * @tx_ops: Tx Ops
+ *
+ * Return: void
+ */
+void target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
+{
+	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init     =
+		target_if_pdev_spectral_init;
+	tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit   =
+		target_if_pdev_spectral_deinit;
+	tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config    =
+		target_if_set_spectral_config;
+	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config    =
+		target_if_get_spectral_config;
+	tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan    =
+		target_if_start_spectral_scan;
+	tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan     =
+		target_if_stop_spectral_scan;
+	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active     =
+		target_if_is_spectral_active;
+	tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled    =
+		target_if_is_spectral_enabled;
+	tx_ops->sptrl_tx_ops.sptrlto_set_debug_level        =
+		target_if_set_debug_level;
+	tx_ops->sptrl_tx_ops.sptrlto_get_debug_level        =
+		target_if_get_debug_level;
+	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo   =
+		target_if_get_spectral_capinfo;
+	tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats =
+		target_if_get_spectral_diagstats;
+}
+EXPORT_SYMBOL(target_if_sptrl_register_tx_ops);
+
+#ifdef HOST_OFFLOAD
+extern void
+atd_spectral_msg_send(
+	struct net_device *dev,
+	 SPECTRAL_SAMP_MSG * msg,
+	 uint16_t msg_len);
+#endif
+
+/**
+ * target_if_spectral_send_intf_found_msg() - Send message to application layer
+ * indicating that interference has been found
+ * @pdev: Pointer to pdev
+ * @cw_int: 1 if CW interference is found, 0 if WLAN interference is found
+ * @dcs_enabled: 1 if DCS is enabled, 0 if DCS is disabled
+ *
+ * Return: None
+ */
+void target_if_spectral_send_intf_found_msg(
+	struct wlan_objmgr_pdev *pdev,
+	u_int16_t cw_int, u_int32_t dcs_enabled)
+{
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+	SPECTRAL_SAMP_MSG *msg = NULL;
+	struct target_if_spectral_ops *p_sops   = NULL;
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+	target_if_spectral_prep_skb(spectral);
+	if (spectral->spectral_skb) {
+		spectral->spectral_nlh =
+			(struct nlmsghdr *)spectral->spectral_skb->data;
+		msg = (SPECTRAL_SAMP_MSG *)NLMSG_DATA(spectral->spectral_nlh);
+		msg->int_type = cw_int ?
+				SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI;
+		msg->dcs_enabled = dcs_enabled;
+		msg->signature = SPECTRAL_SIGNATURE;
+		p_sops->get_mac_address(spectral, msg->macaddr);
+		target_if_spectral_bcast_msg(spectral);
+	}
+#endif
+#ifdef HOST_OFFLOAD
+	{
+	SPECTRAL_SAMP_MSG *buf = NULL;
+
+	buf = (SPECTRAL_SAMP_MSG *)OS_MALLOC(spectral->ic->ic_osdev,
+					     sizeof(struct ath_spectral),
+					     GFP_KERNEL);
+	buf->int_type = cw_int ? SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI;
+	buf->dcs_enabled = dcs_enabled;
+	buf->signature = SPECTRAL_SIGNATURE;
+	p_sops->get_mac_address(spectral, buf->macaddr);
+	atd_spectral_msg_send(spectral->ic->ic_osdev->netdev,
+			      buf,
+					sizeof(SPECTRAL_SAMP_MSG));
+	OS_FREE(buf);
+	}
+#endif
+}
+EXPORT_SYMBOL(target_if_spectral_send_intf_found_msg);
+
diff --git a/target_if/spectral/target_if_spectral.h b/target_if/spectral/target_if_spectral.h
new file mode 100644
index 0000000..d916e90
--- /dev/null
+++ b/target_if/spectral/target_if_spectral.h
@@ -0,0 +1,982 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _TARGET_IF_SPECTRAL_H_
+#define _TARGET_IF_SPECTRAL_H_
+
+#include <wlan_objmgr_cmn.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <qdf_lock.h>
+#include <wlan_spectral_public_structs.h>
+#include <reg_services_public_struct.h>
+
+extern int spectral_debug_level;
+
+#ifdef WIN32
+#pragma pack(push, target_if_spectral, 1)
+#define __ATTRIB_PACK
+#else
+#ifndef __ATTRIB_PACK
+#define __ATTRIB_PACK __attribute__ ((packed))
+#endif
+#endif
+
+#define spectral_log(level, args...) \
+QDF_PRINT_INFO(QDF_PRINT_IDX_SHARED, QDF_MODULE_ID_SPECTRAL, level, ## args)
+
+#define spectral_logfl(level, format, args...) \
+		spectral_log(level, FL(format), ## args)
+
+#define spectral_fatal(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args)
+#define spectral_err(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_ERROR, format, ## args)
+#define spectral_warn(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_WARN, format, ## args)
+#define spectral_info(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_INFO, format, ## args)
+#define spectral_debug(format, args...) \
+	spectral_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args)
+
+#define STATUS_PASS       1
+#define STATUS_FAIL       0
+#define line()   \
+	qdf_print("----------------------------------------------------\n")
+#define SPECTRAL_TODO(str) \
+	qdf_print(KERN_INFO "SPECTRAL : %s (%s : %d)\n", \
+		  (str), __func__, __LINE__)
+#define spectral_ops_not_registered(str) \
+	qdf_print(KERN_INFO "SPECTRAL : %s not registered\n", (str))
+#define not_yet_implemented() \
+	qdf_print("SPECTRAL : %s : %d Not yet implemented\n", \
+		  __func__, __LINE__)
+
+#define SPECTRAL_HT20_NUM_BINS               56
+#define SPECTRAL_HT20_FFT_LEN                56
+#define SPECTRAL_HT20_DC_INDEX               (SPECTRAL_HT20_FFT_LEN / 2)
+#define SPECTRAL_HT20_DATA_LEN               60
+#define SPECTRAL_HT20_TOTAL_DATA_LEN         (SPECTRAL_HT20_DATA_LEN + 3)
+#define SPECTRAL_HT40_TOTAL_NUM_BINS         128
+#define SPECTRAL_HT40_DATA_LEN               135
+#define SPECTRAL_HT40_TOTAL_DATA_LEN         (SPECTRAL_HT40_DATA_LEN + 3)
+#define SPECTRAL_HT40_FFT_LEN                128
+#define SPECTRAL_HT40_DC_INDEX               (SPECTRAL_HT40_FFT_LEN / 2)
+
+/* Used for the SWAR to obtain approximate combined rssi
+ * in secondary 80Mhz segment
+ */
+#define OFFSET_CH_WIDTH_20	65
+#define OFFSET_CH_WIDTH_40	62
+#define OFFSET_CH_WIDTH_80	56
+#define OFFSET_CH_WIDTH_160	50
+
+#ifdef BIG_ENDIAN_HOST
+#define SPECTRAL_MSG_COPY_CHAR_ARRAY(destp, srcp, len)  do { \
+	int j; \
+	u_int32_t *src, *dest; \
+	src = (u_int32_t *)(srcp); \
+	dest = (u_int32_t *)(destp); \
+	for (j = 0; j < roundup((len), sizeof(u_int32_t)) / 4; j++) { \
+	*(dest + j) = qdf_le32_to_cpu(*(src + j)); \
+	} \
+	} while (0)
+#else
+#define SPECTRAL_MSG_COPY_CHAR_ARRAY(destp, srcp, len) \
+	OS_MEMCPY((destp), (srcp), (len));
+#endif
+
+/* 5 categories x (lower + upper) bands */
+#define MAX_INTERF                   10
+#define ATH_HOST_MAX_ANTENNA         3
+/* Mask for time stamp from descriptor */
+#define SPECTRAL_TSMASK              0xFFFFFFFF
+#define SPECTRAL_SIGNATURE           0xdeadbeef
+#define MAX_SPECTRAL_PAYLOAD         1500
+#ifndef NETLINK_ATHEROS
+#define NETLINK_ATHEROS              (NETLINK_GENERIC + 1)
+#endif
+
+/* START of spectral GEN II HW specific details */
+#define SPECTRAL_PHYERR_SIGNATURE_GEN2           0xbb
+#define TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2     0xF9
+#define TLV_TAG_ADC_REPORT_GEN2                  0xFA
+#define TLV_TAG_SEARCH_FFT_REPORT_GEN2           0xFB
+
+/**
+ * struct spectral_search_fft_info_gen2 - spectral search fft report for gen2
+ * @relpwr_db:       Total bin power in db
+ * @num_str_bins_ib: Number of strong bins
+ * @base_pwr:        Base power
+ * @total_gain_info: Total gain
+ * @fft_chn_idx:     FFT chain on which report is originated
+ * @avgpwr_db:       Average power in db
+ * @peak_mag:        Peak power seen in the bins
+ * @peak_inx:        Index of bin holding peak power
+ */
+typedef struct spectral_search_fft_info_gen2 {
+	uint32_t relpwr_db;
+	uint32_t num_str_bins_ib;
+	uint32_t base_pwr;
+	uint32_t total_gain_info;
+	uint32_t fft_chn_idx;
+	uint32_t avgpwr_db;
+	uint32_t peak_mag;
+	int16_t  peak_inx;
+} SPECTRAL_SEARCH_FFT_INFO_GEN2;
+
+/* XXX Check if we should be handling the endinness difference in some
+ * other way opaque to the host
+ */
+#ifdef BIG_ENDIAN_HOST
+
+/**
+ * struct spectral_phyerr_tlv_gen2 - phyerr tlv info for big endian host
+ * @signature: signature
+ * @tag:       tag
+ * @length:    length
+ */
+typedef  struct spectral_phyerr_tlv_gen2 {
+	u_int8_t  signature;
+	u_int8_t  tag;
+	u_int16_t length;
+} __ATTRIB_PACK SPECTRAL_PHYERR_TLV_GEN2;
+
+#else
+
+/**
+ * struct spectral_phyerr_tlv_gen2 - phyerr tlv info for little endian host
+ * @length:    length
+ * @tag:       tag
+ * @signature: signature
+ */
+typedef  struct spectral_phyerr_tlv_gen2 {
+	u_int16_t length;
+	u_int8_t  tag;
+	u_int8_t  signature;
+} __ATTRIB_PACK SPECTRAL_PHYERR_TLV_GEN2;
+
+#endif /* BIG_ENDIAN_HOST */
+
+/**
+ * struct spectral_phyerr_hdr_gen2 - phyerr header for gen2 HW
+ * @hdr_a: Header[0:31]
+ * @hdr_b: Header[32:63]
+ */
+typedef struct spectral_phyerr_hdr_gen2 {
+	u_int32_t hdr_a;
+	u_int32_t hdr_b;
+} SPECTRAL_PHYERR_HDR_GEN2;
+
+/* Segment ID information for 80+80.
+ *
+ * If the HW micro-architecture specification extends this DWORD for other
+ * purposes, then redefine+rename accordingly. For now, the specification
+ * mentions only segment ID (though this doesn't require an entire DWORD)
+ * without mention of any generic terminology for the DWORD, or any reservation.
+ * We use nomenclature accordingly.
+ */
+typedef u_int32_t SPECTRAL_SEGID_INFO;
+
+/**
+ * struct spectral_phyerr_fft_gen2 - fft info in phyerr event
+ * @buf: fft report
+ */
+typedef struct spectral_phyerr_fft_gen2 {
+	u_int8_t buf[0];
+} SPECTRAL_PHYERR_FFT_GEN2;
+/* END of spectral GEN II HW specific details */
+
+/* START of spectral GEN III HW specific details */
+
+#define get_bitfield(value, size, pos) \
+	(((value) >> (pos)) & ((1 << (size)) - 1))
+#define unsigned_to_signed(value, width) \
+	(((value) >= (1 << ((width) - 1))) ? \
+		(value - (1 << (width))) : (value))
+
+#define SPECTRAL_PHYERR_SIGNATURE_GEN3           (0xFA)
+#define TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3     (0x02)
+#define TLV_TAG_SEARCH_FFT_REPORT_GEN3           (0x03)
+#define SPECTRAL_PHYERR_TLVSIZE_GEN3             (4)
+
+#define PHYERR_HDR_SIG_POS    \
+	(offsetof(struct spectral_phyerr_fft_report_gen3, fft_hdr_sig))
+#define PHYERR_HDR_TAG_POS    \
+	(offsetof(struct spectral_phyerr_fft_report_gen3, fft_hdr_tag))
+#define SPECTRAL_FFT_BINS_POS \
+	(offsetof(struct spectral_phyerr_fft_report_gen3, buf))
+
+/**
+ * struct phyerr_info - spectral search fft report for gen3
+ * @data:       handle to phyerror buffer
+ * @datalen:    length of phyerror bufer
+ * @p_rfqual:   rf quality matrices
+ * @p_chaninfo: pointer to chaninfo
+ * @tsf64:      64 bit TSF
+ * @acs_stats:  acs stats
+ */
+struct phyerr_info {
+	u_int8_t *data;
+	u_int32_t datalen;
+	struct target_if_spectral_rfqual_info *p_rfqual;
+	struct target_if_spectral_chan_info *p_chaninfo;
+	u_int64_t tsf64;
+	struct target_if_spectral_acs_stats *acs_stats;
+};
+
+/**
+ * struct spectral_search_fft_info_gen3 - spectral search fft report for gen3
+ * @timestamp:           Timestamp at which fft report was generated
+ * @fft_detector_id:     Which radio generated this report
+ * @fft_num:             The FFT count number. Set to 0 for short FFT.
+ * @fft_radar_check:     NA for spectral
+ * @fft_peak_sidx:       Index of bin with maximum power
+ * @fft_chn_idx:         Rx chain index
+ * @fft_base_pwr_db:     Base power in dB
+ * @fft_total_gain_db:   Total gain in dB
+ * @fft_num_str_bins_ib: Number of strong bins in the report
+ * @fft_peak_mag:        Peak magnitude
+ * @fft_avgpwr_db:       Average power in dB
+ * @fft_relpwr_db:       Relative power in dB
+ */
+struct spectral_search_fft_info_gen3 {
+	uint32_t timestamp;
+	uint32_t fft_detector_id;
+	uint32_t fft_num;
+	uint32_t fft_radar_check;
+	int32_t  fft_peak_sidx;
+	uint32_t fft_chn_idx;
+	uint32_t fft_base_pwr_db;
+	uint32_t fft_total_gain_db;
+	uint32_t fft_num_str_bins_ib;
+	int32_t  fft_peak_mag;
+	uint32_t fft_avgpwr_db;
+	uint32_t fft_relpwr_db;
+};
+
+/**
+ * struct spectral_phyerr_sfftreport_gen3 - fft info in phyerr event
+ * @fft_timestamp:  Timestamp at which fft report was generated
+ * @fft_hdr_sig:    signature
+ * @fft_hdr_tag:    tag
+ * @fft_hdr_length: length
+ * @hdr_a:          Header[0:31]
+ * @hdr_b:          Header[32:63]
+ * @hdr_c:          Header[64:95]
+ * @resv:           Header[96:127]
+ * @buf:            fft bins
+ */
+struct spectral_phyerr_fft_report_gen3 {
+	u_int32_t fft_timestamp;
+#ifdef BIG_ENDIAN_HOST
+	u_int8_t  fft_hdr_sig;
+	u_int8_t  fft_hdr_tag;
+	u_int16_t fft_hdr_length;
+#else
+	u_int16_t fft_hdr_length;
+	u_int8_t  fft_hdr_tag;
+	u_int8_t  fft_hdr_sig;
+#endif /* BIG_ENDIAN_HOST */
+	u_int32_t hdr_a;
+	u_int32_t hdr_b;
+	u_int32_t hdr_c;
+	u_int32_t resv;
+	u_int8_t buf[0];
+} __ATTRIB_PACK;
+
+/* END of spectral GEN III HW specific details */
+
+typedef signed char pwr_dbm;
+
+/**
+ * enum spectral_gen - spectral hw generation
+ * @SPECTRAL_GEN1 : spectral hw gen 1
+ * @SPECTRAL_GEN2 : spectral hw gen 2
+ * @SPECTRAL_GEN3 : spectral hw gen 3
+ */
+enum spectral_gen {
+	SPECTRAL_GEN1,
+	SPECTRAL_GEN2,
+	SPECTRAL_GEN3,
+};
+
+#if ATH_PERF_PWR_OFFLOAD
+/**
+ * enum ol_spectral_info_spec - Enumerations for specifying which spectral
+ *                              information (among parameters and states)
+ *                              is desired.
+ * @OL_SPECTRAL_INFO_SPEC_ACTIVE:  Indicated whether spectral is active
+ * @OL_SPECTRAL_INFO_SPEC_ENABLED: Indicated whether spectral is enabled
+ * @OL_SPECTRAL_INFO_SPEC_PARAMS:  Config params
+ */
+enum ol_spectral_info_spec {
+	OL_SPECTRAL_INFO_SPEC_ACTIVE,
+	OL_SPECTRAL_INFO_SPEC_ENABLED,
+	OL_SPECTRAL_INFO_SPEC_PARAMS,
+};
+#endif /* ATH_PERF_PWR_OFFLOAD */
+
+/* forward declaration */
+struct target_if_spectral;
+
+/**
+ * struct target_if_spectral_chan_info - Channel information
+ * @center_freq1: center frequency 1 in MHz
+ * @center_freq2: center frequency 2 in MHz -valid only for
+ *		 11ACVHT 80PLUS80 mode
+ * @chan_width:   channel width in MHz
+ */
+struct target_if_spectral_chan_info {
+	u_int16_t    center_freq1;
+	u_int16_t    center_freq2;
+	u_int8_t     chan_width;
+};
+
+/**
+ * struct target_if_spectral_acs_stats - EACS stats from spectral samples
+ * @nfc_ctl_rssi: Control chan rssi
+ * @nfc_ext_rssi: Extension chan rssi
+ * @ctrl_nf:      Control chan Noise Floor
+ * @ext_nf:       Extension chan Noise Floor
+ */
+struct target_if_spectral_acs_stats {
+	int8_t nfc_ctl_rssi;
+	int8_t nfc_ext_rssi;
+	int8_t ctrl_nf;
+	int8_t ext_nf;
+};
+
+/**
+ * struct target_if_spectral_perchain_rssi_info - per chain rssi info
+ * @rssi_pri20: Rssi of primary 20 Mhz
+ * @rssi_sec20: Rssi of secondary 20 Mhz
+ * @rssi_sec40: Rssi of secondary 40 Mhz
+ * @rssi_sec80: Rssi of secondary 80 Mhz
+ */
+struct target_if_spectral_perchain_rssi_info {
+	int8_t    rssi_pri20;
+	int8_t    rssi_sec20;
+	int8_t    rssi_sec40;
+	int8_t    rssi_sec80;
+};
+
+/**
+ * struct target_if_spectral_rfqual_info - RF measurement information
+ * @rssi_comb:    RSSI Information
+ * @pc_rssi_info: XXX : For now, we know we are getting information
+ *                for only 4 chains at max. For future extensions
+ *                use a define
+ * @noise_floor:  Noise floor information
+ */
+struct target_if_spectral_rfqual_info {
+	int8_t    rssi_comb;
+	struct    target_if_spectral_perchain_rssi_info pc_rssi_info[4];
+	int16_t   noise_floor[4];
+};
+
+#define GET_TIF_SPECTRAL_OPS(spectral) \
+	((struct target_if_spectral_ops *)(&((spectral)->spectral_ops)))
+
+/**
+ * struct target_if_spectral_ops - spectral low level ops table
+ * @get_tsf64:               Get 64 bit TSF value
+ * @get_capability:          Get capability info
+ * @set_rxfilter:            Set rx filter
+ * @get_rxfilter:            Get rx filter
+ * @is_spectral_active:      Check whether icm is active
+ * @is_spectral_enabled:     Check whether spectral is enabled
+ * @start_spectral_scan:     Start spectral scan
+ * @stop_spectral_scan:      Stop spectral scan
+ * @get_extension_channel:   Get extension channel
+ * @get_ctl_noisefloor:      Get control noise floor
+ * @get_ext_noisefloor:      Get extension noise floor
+ * @configure_spectral:      Set spectral configurations
+ * @get_spectral_config:     Get spectral configurations
+ * @get_ent_spectral_mask:   Get spectral mask
+ * @get_mac_address:         Get mac address
+ * @get_current_channel:     Get current channel
+ * @reset_hw:                Reset HW
+ * @get_chain_noise_floor:   Get Channel noise floor
+ * @spectral_process_phyerr: Process phyerr event
+ */
+struct target_if_spectral_ops {
+	u_int64_t (*get_tsf64)(void *arg);
+	u_int32_t (*get_capability)(void *arg, SPECTRAL_CAPABILITY_TYPE type);
+	u_int32_t (*set_rxfilter)(void *arg, int rxfilter);
+	u_int32_t (*get_rxfilter)(void *arg);
+	u_int32_t (*is_spectral_active)(void *arg);
+	u_int32_t (*is_spectral_enabled)(void *arg);
+	u_int32_t (*start_spectral_scan)(void *arg);
+	u_int32_t (*stop_spectral_scan)(void *arg);
+	u_int32_t (*get_extension_channel)(void *arg);
+	int8_t    (*get_ctl_noisefloor)(void *arg);
+	int8_t    (*get_ext_noisefloor)(void *arg);
+	u_int32_t (*configure_spectral)(
+			void *arg,
+			struct spectral_config *params);
+	u_int32_t (*get_spectral_config)(
+			void *arg,
+			struct spectral_config *params);
+	u_int32_t (*get_ent_spectral_mask)(void *arg);
+	u_int32_t (*get_mac_address)(void *arg, char *addr);
+	u_int32_t (*get_current_channel)(void *arg);
+	u_int32_t (*reset_hw)(void *arg);
+	u_int32_t (*get_chain_noise_floor)(void *arg, int16_t *nf_buf);
+	int (*spectral_process_phyerr)(struct target_if_spectral *spectral,
+				       u_int8_t *data, u_int32_t datalen,
+			struct target_if_spectral_rfqual_info *p_rfqual,
+			struct target_if_spectral_chan_info *p_chaninfo,
+			u_int64_t tsf64,
+			struct target_if_spectral_acs_stats *acs_stats);
+};
+
+/**
+ * struct target_if_spectral_stats - spectral stats info
+ * @num_spectral_detects: Total num. of spectral detects
+ * @total_phy_errors:     Total number of phyerrors
+ * @owl_phy_errors:       Indicated phyerrors in old gen1 chipsets
+ * @pri_phy_errors:       Phyerrors in primary channel
+ * @ext_phy_errors:       Phyerrors in secondary channel
+ * @dc_phy_errors:        Phyerrors due to dc
+ * @early_ext_phy_errors: Early secondary channel phyerrors
+ * @bwinfo_errors:        Bandwidth info errors
+ * @datalen_discards:     Invalid data length errors, seen in gen1 chipsets
+ * @rssi_discards bw:     Indicates reports dropped due to RSSI threshold
+ * @last_reset_tstamp:    Last reset time stamp
+ */
+struct target_if_spectral_stats {
+	u_int32_t    num_spectral_detects;
+	u_int32_t    total_phy_errors;
+	u_int32_t    owl_phy_errors;
+	u_int32_t    pri_phy_errors;
+	u_int32_t    ext_phy_errors;
+	u_int32_t    dc_phy_errors;
+	u_int32_t    early_ext_phy_errors;
+	u_int32_t    bwinfo_errors;
+	u_int32_t    datalen_discards;
+	u_int32_t    rssi_discards;
+	u_int64_t    last_reset_tstamp;
+};
+
+/**
+ * struct target_if_spectral_event - spectral event structure
+ * @se_ts:        Original 15 bit recv timestamp
+ * @se_full_ts:   64-bit full timestamp from interrupt time
+ * @se_rssi:      Rssi of spectral event
+ * @se_bwinfo:    Rssi of spectral event
+ * @se_dur:       Duration of spectral pulse
+ * @se_chanindex: Channel of event
+ * @se_list:      List of spectral events
+ */
+struct target_if_spectral_event {
+	u_int32_t                       se_ts;
+	u_int64_t                       se_full_ts;
+	u_int8_t                        se_rssi;
+	u_int8_t                        se_bwinfo;
+	u_int8_t                        se_dur;
+	u_int8_t                        se_chanindex;
+
+	STAILQ_ENTRY(spectral_event)    se_list;
+};
+
+/**
+ * struct target_if_chain_noise_pwr_info - Noise power info for each channel
+ * @rptcount:        Count of reports in pwr array
+ * @un_cal_nf:       Uncalibrated noise floor
+ * @factory_cal_nf:  Noise floor as calibrated at the factory for module
+ * @median_pwr:      Median power (median of pwr array)
+ * @pwr:             Power reports
+ */
+struct target_if_chain_noise_pwr_info {
+	int        rptcount;
+	pwr_dbm    un_cal_nf;
+	pwr_dbm    factory_cal_nf;
+	pwr_dbm    median_pwr;
+	pwr_dbm    pwr[];
+} __ATTRIB_PACK;
+
+/**
+ * struct target_if_spectral_chan_stats - Channel information
+ * @cycle_count:         Cycle count
+ * @channel_load:        Channel load
+ * @per:                 Period
+ * @noisefloor:          Noise floor
+ * @comp_usablity:       Computed usability
+ * @maxregpower:         Maximum allowed regulatary power
+ * @comp_usablity_sec80: Computed usability of secondary 80 Mhz
+ * @maxregpower_sec80:   Max regulatory power in secondary 80 Mhz
+ */
+struct target_if_spectral_chan_stats {
+	int          cycle_count;
+	int          channel_load;
+	int          per;
+	int          noisefloor;
+	u_int16_t    comp_usablity;
+	int8_t       maxregpower;
+	u_int16_t    comp_usablity_sec80;
+	int8_t       maxregpower_sec80;
+};
+
+#if ATH_PERF_PWR_OFFLOAD
+/* Locking operations
+ * We have a separate set of definitions for offload to accommodate
+ * offload specific changes in the future.
+ */
+#define OL_SPECTRAL_LOCK_INIT(_lock)            qdf_spinlock_create((_lock))
+#define OL_SPECTRAL_LOCK_DESTROY(_lock)         qdf_spinlock_destroy((_lock))
+#define OL_SPECTRAL_LOCK(_lock)                 qdf_spin_lock((_lock))
+#define OL_SPECTRAL_UNLOCK(_lock)               qdf_spin_unlock((_lock))
+
+/**
+ * struct target_if_spectral_cache - Cache used to minimize WMI operations
+ *                             in offload architecture
+ * @osc_spectral_enabled: Whether Spectral is enabled
+ * @osc_spectral_active:  Whether spectral is active
+ *                        XXX: Ideally, we should NOT cache this
+ *                        since the hardware can self clear the bit,
+ *                        the firmware can possibly stop spectral due to
+ *                        intermittent off-channel activity, etc
+ *                        A WMI read command should be introduced to handle
+ *                        this This will be discussed.
+ * @osc_params:           Spectral parameters
+ * @osc_is_valid:         Whether the cache is valid
+ */
+struct target_if_spectral_cache {
+	u_int8_t                  osc_spectral_enabled;
+	u_int8_t                  osc_spectral_active;
+	struct spectral_config    osc_params;
+	u_int8_t                  osc_is_valid;
+};
+
+/**
+ * struct target_if_spectral_param_state_info - Structure used to represent and
+ *                                        manage spectral information
+ *                                        (parameters and states)
+ * @osps_lock:  Lock to synchronize accesses to information
+ * @osps_cache: Cacheable' information
+ */
+struct target_if_spectral_param_state_info {
+	qdf_spinlock_t               osps_lock;
+	struct target_if_spectral_cache    osps_cache;
+	/* XXX - Non-cacheable information goes here, in the future */
+};
+#endif /* ATH_PERF_PWR_OFFLOAD */
+
+/**
+ * struct target_if_spectral - main spectral structure
+ * @pdev: Pointer to pdev
+ * @spectral_ops: Target if internal Spectral low level operations table
+ * @capability: Spectral capabilities structure
+ * @ath_spectral_lock: Lock used for internal Spectral operations
+ * @spectral_curchan_radindex: Current channel spectral index
+ * @spectral_extchan_radindex: Extension channel spectral index
+ * @spectraldomain: Current Spectral domain
+ * @spectral_proc_phyerr:  Flags to process for PHY errors
+ * @spectral_defaultparams: Default PHY params per Spectral stat
+ * @ath_spectral_stats:  Spectral related stats
+ * @events:   Events structure
+ * @sc_spectral_ext_chan_ok:  Can spectral be detected on the extension channel?
+ * @sc_spectral_combined_rssi_ok:  Can use combined spectral RSSI?
+ * @sc_spectral_20_40_mode:  Is AP in 20-40 mode?
+ * @sc_spectral_noise_pwr_cal:  Noise power cal required?
+ * @sc_spectral_non_edma:  Is the spectral capable device Non-EDMA?
+ * @upper_is_control: Upper segment is primary
+ * @upper_is_extension: Upper segment is secondary
+ * @lower_is_control: Lower segment is primary
+ * @lower_is_extension: Lower segment is secondary
+ * @sc_spectraltest_ieeechan:  IEEE channel number to return to after a spectral
+ * mute test
+ * @spectral_numbins: Number of bins
+ * @spectral_fft_len: FFT length
+ * @spectral_data_len: Total phyerror report length
+ * @lb_edge_extrabins: Number of extra bins on left band edge
+ * @rb_edge_extrabins: Number of extra bins on right band edge
+ * @spectral_max_index_offset: Max FFT index offset (20 MHz mode)
+ * @spectral_upper_max_index_offset: Upper max FFT index offset (20/40 MHz mode)
+ * @spectral_lower_max_index_offset: Lower max FFT index offset (20/40 MHz mode)
+ * @spectral_dc_index: At which index DC is present
+ * @send_single_packet: Deprecated
+ * @spectral_sent_msg: Indicates whether we send report to upper layers
+ * @params: Spectral parameters
+ * @last_capture_time: Indicates timestamp of previouse report
+ * @num_spectral_data: Number of Spectral samples received in current session
+ * @total_spectral_data: Total number of Spectral samples received
+ * @max_rssi: Maximum RSSI
+ * @detects_control_channel: NA
+ * @detects_extension_channel: NA
+ * @detects_below_dc: NA
+ * @detects_above_dc: NA
+ * @sc_scanning: Indicates active wifi scan
+ * @sc_spectral_scan: Indicates active specral scan
+ * @sc_spectral_full_scan: Deprecated
+ * @scan_start_tstamp: Deprecated
+ * @last_tstamp: Deprecated
+ * @first_tstamp: Deprecated
+ * @spectral_samp_count: Deprecated
+ * @sc_spectral_samp_count: Deprecated
+ * @noise_pwr_reports_reqd: Number of noise power reports required
+ * @noise_pwr_reports_recv: Number of noise power reports received
+ * @noise_pwr_reports_lock: Lock used for Noise power report processing
+ * @noise_pwr_chain_ctl: Noise power report - control channel
+ * @noise_pwr_chain_ext: Noise power report - extension channel
+ * @chaninfo: Channel statistics
+ * @tsf64: Latest TSF Value
+ * @ol_info: Offload architecture Spectral parameter cache information
+ * @ch_width: Indicates Channel Width 20/40/80/160 MHz with values 0, 1, 2, 3
+ * respectively
+ * @diag_stats: Diagnostic statistics
+ * @is_160_format:  Indicates whether information provided by HW is in altered
+ * format for 802.11ac 160/80+80 MHz support (QCA9984 onwards)
+ * @is_lb_edge_extrabins_format:  Indicates whether information provided by
+ * HW has 4 extra bins, at left band edge, for report mode 2
+ * @is_rb_edge_extrabins_format:   Indicates whether information provided
+ * by HW has 4 extra bins, at right band edge, for report mode 2
+ * @is_sec80_rssi_war_required: Indicates whether the software workaround is
+ * required to obtain approximate combined RSSI for secondary 80Mhz segment
+ * @simctx: Spectral Simulation context
+ * @spectral_gen: Spectral hardware generation
+ * @hdr_sig_exp: Expected signature in PHYERR TLV header, for the given hardware
+ * generation
+ * @tag_sscan_summary_exp: Expected Spectral Scan Summary tag in PHYERR TLV
+ * header, for the given hardware generation
+ * @tag_sscan_fft_exp: Expected Spectral Scan FFT report tag in PHYERR TLV
+ * header, for the given hardware generation
+ * @tlvhdr_size: Expected PHYERR TLV header size, for the given hardware
+ * generation
+ */
+struct target_if_spectral {
+	struct wlan_objmgr_pdev *pdev_obj;
+	struct target_if_spectral_ops                 spectral_ops;
+	struct spectral_caps                    capability;
+	qdf_spinlock_t                          ath_spectral_lock;
+	int16_t                                 spectral_curchan_radindex;
+	int16_t                                 spectral_extchan_radindex;
+	u_int32_t                               spectraldomain;
+	u_int32_t                               spectral_proc_phyerr;
+	struct spectral_config                  spectral_defaultparams;
+	struct target_if_spectral_stats               ath_spectral_stats;
+	struct target_if_spectral_event *events;
+	unsigned int                            sc_spectral_ext_chan_ok:1,
+						sc_spectral_combined_rssi_ok:1,
+						sc_spectral_20_40_mode:1,
+						sc_spectral_noise_pwr_cal:1,
+						sc_spectral_non_edma:1;
+	int                                     upper_is_control;
+	int                                     upper_is_extension;
+	int                                     lower_is_control;
+	int                                     lower_is_extension;
+	u_int8_t                                sc_spectraltest_ieeechan;
+	struct sock *spectral_sock;
+	struct sk_buff *spectral_skb;
+	struct nlmsghdr *spectral_nlh;
+	u_int32_t                               spectral_pid;
+
+	STAILQ_HEAD(, target_if_spectral_skb_event)    spectral_skbq;
+	qdf_spinlock_t                          spectral_skbqlock;
+	int                                     spectral_numbins;
+	int                                     spectral_fft_len;
+	int                                     spectral_data_len;
+
+	/* For 11ac chipsets prior to AR900B version 2.0, a max of 512 bins are
+	 * delivered.  However, there can be additional bins reported for
+	 * AR900B version 2.0 and QCA9984 as described next:
+	 *
+	 * AR900B version 2.0: An additional tone is processed on the right
+	 * hand side in order to facilitate detection of radar pulses out to
+	 * the extreme band-edge of the channel frequency. Since the HW design
+	 * processes four tones at a time, this requires one additional Dword
+	 * to be added to the search FFT report.
+	 *
+	 * QCA9984: When spectral_scan_rpt_mode = 2, i.e 2-dword summary +
+	 * 1x-oversampled bins (in-band) per FFT, then 8 more bins
+	 * (4 more on left side and 4 more on right side)are added.
+	 */
+
+	int                                     lb_edge_extrabins;
+	int                                     rb_edge_extrabins;
+	int                                     spectral_max_index_offset;
+	int                                     spectral_upper_max_index_offset;
+	int                                     spectral_lower_max_index_offset;
+	int                                     spectral_dc_index;
+	int                                     send_single_packet;
+	int                                     spectral_sent_msg;
+	int                                     classify_scan;
+	os_timer_t                              classify_timer;
+	struct spectral_config                  params;
+	struct spectral_classifier_params       classifier_params;
+	int                                     last_capture_time;
+	int                                     num_spectral_data;
+	int                                     total_spectral_data;
+	int                                     max_rssi;
+	int                                     detects_control_channel;
+	int                                     detects_extension_channel;
+	int                                     detects_below_dc;
+	int                                     detects_above_dc;
+	int                                     sc_scanning;
+	int                                     sc_spectral_scan;
+	int                                     sc_spectral_full_scan;
+	u_int64_t                               scan_start_tstamp;
+	u_int32_t                               last_tstamp;
+	u_int32_t                               first_tstamp;
+	u_int32_t                               spectral_samp_count;
+	u_int32_t                               sc_spectral_samp_count;
+	int                                     noise_pwr_reports_reqd;
+	int                                     noise_pwr_reports_recv;
+	qdf_spinlock_t                          noise_pwr_reports_lock;
+	struct target_if_chain_noise_pwr_info
+		*noise_pwr_chain_ctl[ATH_HOST_MAX_ANTENNA];
+	struct target_if_chain_noise_pwr_info
+		*noise_pwr_chain_ext[ATH_HOST_MAX_ANTENNA];
+	u_int64_t                               tsf64;
+#if ATH_PERF_PWR_OFFLOAD
+	struct target_if_spectral_param_state_info    ol_info;
+#endif
+	u_int32_t                               ch_width;
+	struct spectral_diag_stats              diag_stats;
+	bool                                    is_160_format;
+	bool                                    is_lb_edge_extrabins_format;
+	bool                                    is_rb_edge_extrabins_format;
+	bool                                    is_sec80_rssi_war_required;
+#if QCA_SUPPORT_SPECTRAL_SIMULATION
+	void                                    *simctx;
+#endif
+	enum spectral_gen                       spectral_gen;
+	u_int8_t                                hdr_sig_exp;
+	u_int8_t                                tag_sscan_summary_exp;
+	u_int8_t                                tag_sscan_fft_exp;
+	u_int8_t                                tlvhdr_size;
+};
+
+/**
+ * struct target_if_spectral_skb_event - Used to broadcast FFT report to
+ *                                       applications
+ * @sp_skb:            Pointer to skb
+ * @sp_nlh:            Pointer to nl message header
+ * @spectral_skb_list: Linked list to manipulate the reports
+ */
+struct target_if_spectral_skb_event {
+	struct sk_buff *sp_skb;
+	struct nlmsghdr *sp_nlh;
+
+	STAILQ_ENTRY(target_if_spectral_skb_event)    spectral_skb_list;
+};
+
+/* TODO:COMMENTS */
+struct target_if_samp_msg_params {
+	int8_t      rssi;
+	int8_t      rssi_sec80;
+	int8_t      lower_rssi;
+	int8_t      upper_rssi;
+	int8_t      chain_ctl_rssi[ATH_HOST_MAX_ANTENNA];
+	int8_t      chain_ext_rssi[ATH_HOST_MAX_ANTENNA];
+	uint16_t    bwinfo;
+	uint16_t    datalen;
+	uint16_t    datalen_sec80;
+	uint32_t    tstamp;
+	uint32_t    last_tstamp;
+	uint16_t    max_mag;
+	uint16_t    max_mag_sec80;
+	uint16_t    max_index;
+	uint16_t    max_index_sec80;
+	uint8_t     max_exp;
+	int         peak;
+	int         pwr_count;
+	int         pwr_count_sec80;
+	int8_t      nb_lower;
+	int8_t      nb_upper;
+	uint16_t    max_lower_index;
+	uint16_t    max_upper_index;
+	u_int8_t    *bin_pwr_data;
+	u_int8_t    *bin_pwr_data_sec80;
+	u_int16_t   freq;
+	u_int16_t   vhtop_ch_freq_seg1;
+	u_int16_t   vhtop_ch_freq_seg2;
+	u_int16_t   freq_loading;
+	int16_t     noise_floor;
+	int16_t     noise_floor_sec80;
+	struct INTERF_SRC_RSP interf_list;
+	SPECTRAL_CLASSIFIER_PARAMS classifier_params;
+	struct ath_softc *sc;
+};
+
+/* NETLINK related declarations */
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+#if (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
+	void spectral_nl_data_ready(struct sock *sk, int len);
+#else
+	void spectral_nl_data_ready(struct sk_buff *skb);
+#endif /* VERSION CHECK */
+#endif /* SPECTRAL_USE_NETLINK_SOCKETS defined */
+
+void target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops);
+extern struct net init_net;
+int target_if_spectral_init_netlink(struct target_if_spectral *spectral);
+int target_if_spectral_destroy_netlink(struct target_if_spectral *spectral);
+void target_if_spectral_unicast_msg(struct target_if_spectral *spectral);
+void target_if_spectral_bcast_msg(struct target_if_spectral *spectral);
+void target_if_spectral_prep_skb(struct target_if_spectral *spectral);
+void target_if_spectral_skb_dequeue(unsigned long data);
+void target_if_spectral_create_samp_msg(
+	struct target_if_spectral *spectral,
+	struct target_if_samp_msg_params *params);
+int spectral_process_phyerr_gen3(
+	struct target_if_spectral *spectral,
+	u_int8_t *data,
+	u_int32_t datalen, struct target_if_spectral_rfqual_info *p_rfqual,
+	struct target_if_spectral_chan_info *p_chaninfo,
+	u_int64_t tsf64,
+	struct target_if_spectral_acs_stats *acs_stats);
+int spectral_process_phyerr_gen2(
+	struct target_if_spectral *spectral,
+	u_int8_t *data,
+	u_int32_t datalen, struct target_if_spectral_rfqual_info *p_rfqual,
+	struct target_if_spectral_chan_info *p_chaninfo,
+	u_int64_t tsf64,
+	struct target_if_spectral_acs_stats *acs_stats);
+void target_if_spectral_send_intf_found_msg(
+	struct wlan_objmgr_pdev *pdev,
+	u_int16_t cw_int, u_int32_t dcs_enabled);
+void target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev);
+struct wlan_objmgr_vdev *target_if_spectral_get_vdev(
+	struct target_if_spectral *spectral);
+
+int spectral_dump_header_gen2(SPECTRAL_PHYERR_HDR_GEN2 *phdr);
+int8_t get_combined_rssi_sec80_segment_gen2(
+	struct target_if_spectral *spectral,
+	SPECTRAL_SEARCH_FFT_INFO_GEN2 *p_sfft_sec80);
+int spectral_dump_tlv_gen2(SPECTRAL_PHYERR_TLV_GEN2 *ptlv, bool is_160_format);
+int spectral_dump_phyerr_data_gen2(
+	u_int8_t *data,
+	u_int32_t datalen,
+	bool is_160_format);
+int spectral_dump_fft_report_gen3(
+	struct spectral_phyerr_fft_report_gen3 *p_fft_report,
+	struct spectral_search_fft_info_gen3 *p_sfft);
+
+void target_if_dbg_print_SAMP_msg(SPECTRAL_SAMP_MSG *pmsg);
+
+/* START of spectral GEN III HW specific function declarations */
+/* [FIXME] fix the declaration */
+int process_search_fft_report_gen3(
+	struct spectral_phyerr_fft_report_gen3 *p_fft_report,
+	 struct spectral_search_fft_info_gen3 *p_fft_info);
+/* END of spectral GEN III HW specific function declarations */
+
+/**
+ * target_if_send_phydata() - Send Spectral PHY data over netlink
+ * @pdev: Pointer to pdev
+ * @sock: Netlink socket to use
+ * @nbuf: Network buffer containing PHY data to send
+ *
+ * Return: 0 on success, negative value on failure
+ */
+static inline uint32_t target_if_send_phydata(
+	struct wlan_objmgr_pdev *pdev,
+	struct sock *sock, qdf_nbuf_t nbuf)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	return psoc->soc_cb.rx_ops.sptrl_rx_ops.sptrlro_send_phydata(pdev,
+				sock, nbuf);
+}
+
+/**
+ * get_target_if_spectral_handle_from_pdev() - Get handle to target_if internal
+ * Spectral data
+ * @pdev: Pointer to pdev
+ *
+ * Return: Handle to target_if internal Spectral data on success, NULL on
+ * failure
+ */
+static inline
+struct target_if_spectral *get_target_if_spectral_handle_from_pdev(
+	struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral *spectral = NULL;
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	spectral = (struct target_if_spectral *)
+		psoc->soc_cb.rx_ops.sptrl_rx_ops.sptrlro_get_target_handle(
+		pdev);
+	return spectral;
+}
+
+/**
+ * target_if_spectral_set_rxchainmask() - Set Spectral Rx chainmask
+ * @pdev: Pointer to pdev
+ * @spectral_rx_chainmask: Spectral Rx chainmask
+ *
+ * Return: None
+ */
+static inline
+void target_if_spectral_set_rxchainmask(struct wlan_objmgr_pdev *pdev,
+					u_int8_t spectral_rx_chainmask)
+{
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	spectral->params.ss_chn_mask = spectral_rx_chainmask;
+}
+
+/**
+ * target_if_spectral_process_phyerr() - Process Spectral PHY error
+ * @pdev: Pointer to pdev
+ * @data: PHY error data received from FW
+ * @datalen: Length of data
+ * @p_rfqual: Pointer to RF Quality information
+ * @p_chaninfo: Pointer to channel information
+ * @tsf: TSF time instance at which the Spectral sample was received
+ * @acs_stats: ACS stats
+ *
+ * Process Spectral PHY error by extracting necessary information from the data
+ * sent by FW, and send the extracted information to application layer.
+ *
+ * Return: None
+ */
+static inline
+void target_if_spectral_process_phyerr(
+	struct wlan_objmgr_pdev *pdev,
+	u_int8_t *data, u_int32_t datalen,
+	struct target_if_spectral_rfqual_info *p_rfqual,
+	struct target_if_spectral_chan_info *p_chaninfo,
+	u_int64_t tsf64,
+	struct target_if_spectral_acs_stats *acs_stats)
+{
+	struct target_if_spectral *spectral = NULL;
+	struct target_if_spectral_ops *p_sops = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+	p_sops->spectral_process_phyerr(spectral, data, datalen,
+					p_rfqual, p_chaninfo,
+					tsf64, acs_stats);
+}
+
+#ifdef WIN32
+#pragma pack(pop, target_if_spectral)
+#endif
+#ifdef __ATTRIB_PACK
+#undef __ATTRIB_PACK
+#endif
+
+#endif /* _TARGET_IF_SPECTRAL_H_ */
diff --git a/target_if/spectral/target_if_spectral_netlink.c b/target_if/spectral/target_if_spectral_netlink.c
new file mode 100644
index 0000000..458e2ce
--- /dev/null
+++ b/target_if/spectral/target_if_spectral_netlink.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <osdep.h>
+#include <wlan_tgt_def_config.h>
+#include <hif.h>
+#include <hif_hw_version.h>
+#include <wmi_unified_api.h>
+#include <target_if_spectral.h>
+#include <wlan_lmac_if_def.h>
+#include <wlan_osif_priv.h>
+
+#ifdef HOST_OFFLOAD
+extern void
+atd_spectral_msg_send(
+	struct net_device *dev,
+	 SPECTRAL_SAMP_MSG *msg,
+	 uint16_t msg_len);
+#endif
+
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+struct sock *target_if_spectral_nl_sock;
+static atomic_t spectral_nl_users = ATOMIC_INIT(0);
+
+#if (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
+void target_if_spectral_nl_data_ready(struct sock *sk, int len)
+{
+	qdf_print("%s %d\n", __func__, __LINE__);
+}
+
+#else
+void target_if_spectral_nl_data_ready(struct sk_buff *skb)
+{
+	qdf_print("%s %d\n", __func__, __LINE__);
+}
+
+#endif /* VERSION */
+
+int target_if_spectral_init_netlink(struct target_if_spectral *spectral)
+{
+#if KERNEL_VERSION(3, 6, 0) <= LINUX_VERSION_CODE
+
+	struct netlink_kernel_cfg cfg = {
+	.groups = 1,
+	.input  = target_if_spectral_nl_data_ready,
+	};
+#endif
+
+	if (!spectral) {
+	qdf_print("%s: sc_spectral is NULL\n", __func__);
+	return -EIO;
+	}
+
+	spectral->spectral_sent_msg = 0;
+
+	if (!target_if_spectral_nl_sock) {
+#if KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE
+	target_if_spectral_nl_sock = (struct sock *)netlink_kernel_create(
+					&init_net,
+					NETLINK_ATHEROS,
+					&cfg);
+#elif KERNEL_VERSION(3, 6, 0) <= LINUX_VERSION_CODE
+	target_if_spectral_nl_sock = (struct sock *)netlink_kernel_create(
+					&init_net,
+					NETLINK_ATHEROS,
+					THIS_MODULE,
+					&cfg);
+#elif (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
+	target_if_spectral_nl_sock = (
+		struct sock *)netlink_kernel_create(NETLINK_ATHEROS,
+		 1,
+		 &target_if_spectral_nl_data_ready,
+		 THIS_MODULE);
+#else
+#if (KERNEL_VERSION(3, 10, 0) <= LINUX_VERSION_CODE)
+	struct netlink_kernel_cfg cfg;
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.groups = 1;
+	cfg.input = &target_if_spectral_nl_data_ready;
+	target_if_spectral_nl_sock = (struct sock *)netlink_kernel_create(
+				&init_net, NETLINK_ATHEROS, &cfg);
+#else
+	target_if_spectral_nl_sock = (struct sock *)netlink_kernel_create(
+				&init_net,
+				NETLINK_ATHEROS,
+				1,
+				&target_if_spectral_nl_data_ready,
+				NULL,
+				THIS_MODULE);
+#endif
+#endif
+	if (!target_if_spectral_nl_sock) {
+		qdf_print("%s NETLINK_KERNEL_CREATE FAILED\n", __func__);
+		return -ENODEV;
+	}
+	}
+	atomic_inc(&spectral_nl_users);
+	spectral->spectral_sock = target_if_spectral_nl_sock;
+
+	if ((!spectral) || (!spectral->spectral_sock)) {
+		qdf_print("%s NULL pointers (spectral=%d) (sock=%d)\n",
+			  __func__, (!spectral), (!spectral->spectral_sock));
+		return -ENODEV;
+	}
+	if (!spectral->spectral_skb)
+		qdf_print(KERN_ERR "%s %d NULL SKB\n", __func__, __LINE__);
+
+	return 0;
+}
+
+int target_if_spectral_destroy_netlink(struct target_if_spectral *spectral)
+{
+	spectral->spectral_sock = NULL;
+	if (atomic_dec_and_test(&spectral_nl_users)) {
+	sock_release(target_if_spectral_nl_sock->sk_socket);
+	target_if_spectral_nl_sock = NULL;
+	}
+	return 0;
+}
+
+#endif /* SPECTRAL_USE_NETLINK_SOCKETS */
+
+static void spectral_process_noise_pwr_report(
+	struct target_if_spectral *spectral,
+	 const SPECTRAL_SAMP_MSG *spec_samp_msg)
+{
+	int i, done;
+
+/*
+ *	qdf_print(
+ *	"%s: #%d/%d datalen=%d tstamp=%x last_tstamp=%x "
+ *	"rssi=%d nb_lower=%d peak=%d\n",
+ *	__func__, spectral->noise_pwr_reports_recv,
+ *	spectral->noise_pwr_reports_reqd,
+ *	spec_samp_msg->samp_data.spectral_data_len,
+ *	spec_samp_msg->samp_data.spectral_tstamp,
+ *	spec_samp_msg->samp_data.spectral_last_tstamp,
+ *	spec_samp_msg->samp_data.spectral_lower_rssi,
+ *	spec_samp_msg->samp_data.spectral_nb_lower,
+ *	spec_samp_msg->samp_data.spectral_lower_max_index);
+ */
+
+	qdf_spin_lock(&spectral->noise_pwr_reports_lock);
+
+	if (!spectral->noise_pwr_reports_reqd) {
+		qdf_spin_unlock(&spectral->noise_pwr_reports_lock);
+		return;
+	}
+
+	if (spectral->noise_pwr_reports_recv <
+		spectral->noise_pwr_reports_reqd) {
+		spectral->noise_pwr_reports_recv++;
+
+/*
+ *	qdf_print(
+ *	"#%d/%d: rssi=%3d,%3d,%3d %3d,%3d,%3d\n",
+ *	spectral->noise_pwr_reports_recv,
+ *	spectral->noise_pwr_reports_reqd,
+ *	spec_samp_msg->samp_data.spectral_chain_ctl_rssi[0],
+ *	spec_samp_msg->samp_data.spectral_chain_ctl_rssi[1],
+ *	spec_samp_msg->samp_data.spectral_chain_ctl_rssi[2],
+ *	spec_samp_msg->samp_data.spectral_chain_ext_rssi[0],
+ *	spec_samp_msg->samp_data.spectral_chain_ext_rssi[1],
+ *	spec_samp_msg->samp_data.spectral_chain_ext_rssi[2]);
+ */
+
+	for (i = 0; i < ATH_HOST_MAX_ANTENNA; i++) {
+		uint32_t index;
+
+		if (spectral->noise_pwr_chain_ctl[i]) {
+			index = spectral->noise_pwr_chain_ctl[i]->rptcount++;
+			spectral->noise_pwr_chain_ctl[i]->pwr[index] =
+			spec_samp_msg->samp_data.spectral_chain_ctl_rssi[i];
+		}
+		if (spectral->noise_pwr_chain_ext[i]) {
+			index = spectral->noise_pwr_chain_ext[i]->rptcount++;
+			spectral->noise_pwr_chain_ext[i]->pwr[index] =
+			spec_samp_msg->samp_data.spectral_chain_ext_rssi[i];
+		}
+	}
+	}
+
+	done = (spectral->noise_pwr_reports_recv >=
+			spectral->noise_pwr_reports_reqd);
+
+	qdf_spin_unlock(&spectral->noise_pwr_reports_lock);
+
+	if (done) {
+		qdf_spin_lock(&spectral->ath_spectral_lock);
+		target_if_stop_spectral_scan(spectral->pdev_obj);
+		spectral->sc_spectral_scan = 0;
+		qdf_spin_unlock(&spectral->ath_spectral_lock);
+
+/*
+ *	qdf_print(
+ *	"%s: done: %d/%d recv - set sc_spectral_scan = 0\n",
+ *	__func__, spectral->noise_pwr_reports_recv,
+ *	spectral->noise_pwr_reports_reqd);
+ */
+	}
+}
+
+/*
+ * Function     : spectral_create_samp_msg
+ * Description  : create SAMP message and send it host
+ * Input        :
+ * Output       :
+ *
+ */
+
+void target_if_spectral_create_samp_msg(
+	struct target_if_spectral *spectral,
+	 struct target_if_samp_msg_params *params)
+{
+	/*
+	 * XXX : Non-Rentrant. Will be an issue with dual concurrent
+	 *       operation on multi-processor system
+	 */
+
+	int temp_samp_msg_len   = 0;
+
+	static SPECTRAL_SAMP_MSG spec_samp_msg;
+
+	SPECTRAL_SAMP_MSG   *msg        = NULL;
+	SPECTRAL_SAMP_DATA *data        = NULL;
+	u_int8_t *bin_pwr_data          = NULL;
+	SPECTRAL_CLASSIFIER_PARAMS *cp  = NULL;
+	SPECTRAL_CLASSIFIER_PARAMS *pcp = NULL;
+	struct target_if_spectral_ops *p_sops            = NULL;
+	struct target_if_spectral_skb_event *sp_skb_event = NULL;
+
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+	static int samp_msg_index;
+#endif
+
+	p_sops              = GET_TIF_SPECTRAL_OPS(spectral);
+
+	temp_samp_msg_len   = sizeof(SPECTRAL_SAMP_MSG) -
+			      (MAX_NUM_BINS * sizeof(u_int8_t));
+	temp_samp_msg_len  += (params->pwr_count * sizeof(u_int8_t));
+	if (spectral->ch_width == IEEE80211_CWM_WIDTH160)
+		temp_samp_msg_len  +=
+			(params->pwr_count_sec80 * sizeof(u_int8_t));
+	bin_pwr_data        = params->bin_pwr_data;
+
+	memset(&spec_samp_msg, 0, sizeof(SPECTRAL_SAMP_MSG));
+
+	data = &spec_samp_msg.samp_data;
+
+	spec_samp_msg.signature                     = SPECTRAL_SIGNATURE;
+	spec_samp_msg.freq                          = params->freq;
+	spec_samp_msg.freq_loading                  = params->freq_loading;
+	spec_samp_msg.samp_data.spectral_data_len   = params->datalen;
+	spec_samp_msg.samp_data.spectral_rssi       = params->rssi;
+	spec_samp_msg.samp_data.ch_width            = spectral->ch_width;
+
+	spec_samp_msg.samp_data.spectral_combined_rssi  =
+		(u_int8_t)params->rssi;
+	spec_samp_msg.samp_data.spectral_upper_rssi     = params->upper_rssi;
+	spec_samp_msg.samp_data.spectral_lower_rssi     = params->lower_rssi;
+
+	OS_MEMCPY(
+		spec_samp_msg.samp_data.spectral_chain_ctl_rssi,
+		 params->chain_ctl_rssi,
+		 sizeof(params->chain_ctl_rssi));
+	OS_MEMCPY(
+		spec_samp_msg.samp_data.spectral_chain_ext_rssi,
+		 params->chain_ext_rssi,
+		 sizeof(params->chain_ext_rssi));
+
+	spec_samp_msg.samp_data.spectral_bwinfo         = params->bwinfo;
+	spec_samp_msg.samp_data.spectral_tstamp         = params->tstamp;
+	spec_samp_msg.samp_data.spectral_max_index      = params->max_index;
+
+	/* Classifier in user space needs access to these */
+	spec_samp_msg.samp_data.spectral_lower_max_index    =
+		params->max_lower_index;
+	spec_samp_msg.samp_data.spectral_upper_max_index    =
+		params->max_upper_index;
+	spec_samp_msg.samp_data.spectral_nb_lower           =
+		params->nb_lower;
+	spec_samp_msg.samp_data.spectral_nb_upper           = params->nb_upper;
+	spec_samp_msg.samp_data.spectral_last_tstamp        =
+		params->last_tstamp;
+	spec_samp_msg.samp_data.spectral_max_mag            = params->max_mag;
+	spec_samp_msg.samp_data.bin_pwr_count               =
+		params->pwr_count;
+	spec_samp_msg.samp_data.lb_edge_extrabins           =
+		spectral->lb_edge_extrabins;
+	spec_samp_msg.samp_data.rb_edge_extrabins           =
+		spectral->rb_edge_extrabins;
+	spec_samp_msg.samp_data.spectral_combined_rssi      = params->rssi;
+	spec_samp_msg.samp_data.spectral_max_scale          = params->max_exp;
+
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+
+	/*
+	 * This is a dirty hack to get the Windows build pass.
+	 * Currently Windows and Linux builds source spectral_data.h
+	 * form two different place. The windows version do not
+	 * have noise_floor member in it.
+	 *
+	 * As a temp workaround this variable is set under the
+	 * SPECTRAL_USE_NETLINK_SOCKETS as this is called only
+	 * under the linux build and this saves the day
+	 *
+	 * The plan to sync of header files in under the way
+	 *
+	 */
+
+	spec_samp_msg.samp_data.noise_floor = params->noise_floor;
+#endif  /* SPECTRAL_USE_NETLINK_SOCKETS */
+
+	/* Classifier in user space needs access to these */
+	cp  = &spec_samp_msg.samp_data.classifier_params;
+	pcp = &params->classifier_params;
+
+	OS_MEMCPY(cp, pcp, sizeof(SPECTRAL_CLASSIFIER_PARAMS));
+
+	SPECTRAL_MSG_COPY_CHAR_ARRAY(
+		&data->bin_pwr[0],
+		 bin_pwr_data,
+		 params->pwr_count);
+
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+	spec_samp_msg.vhtop_ch_freq_seg1            =
+		params->vhtop_ch_freq_seg1;
+	spec_samp_msg.vhtop_ch_freq_seg2            =
+		params->vhtop_ch_freq_seg2;
+
+	if (spectral->ch_width == IEEE80211_CWM_WIDTH160) {
+	spec_samp_msg.samp_data.spectral_rssi_sec80 = params->rssi_sec80;
+	spec_samp_msg.samp_data.noise_floor_sec80 = params->noise_floor_sec80;
+
+	spec_samp_msg.samp_data.spectral_data_len_sec80  =
+		params->datalen_sec80;
+	spec_samp_msg.samp_data.spectral_max_index_sec80 =
+		params->max_index_sec80;
+	spec_samp_msg.samp_data.spectral_max_mag_sec80   =
+		params->max_mag_sec80;
+	spec_samp_msg.samp_data.bin_pwr_count_sec80      =
+		params->pwr_count_sec80;
+	SPECTRAL_MSG_COPY_CHAR_ARRAY(&data->bin_pwr_sec80[0],
+				     (params->bin_pwr_data_sec80),
+				     params->pwr_count_sec80);
+
+	/* Note: REVERSE_ORDER is not a known use case for secondary 80 data at
+	 * this point.
+	 */
+	}
+#endif  /* SPECTRAL_USE_NETLINK_SOCKETS */
+
+#ifdef SPECTRAL_CLASSIFIER_IN_KERNEL
+	if (params->interf_list.count)
+		OS_MEMCPY(
+			&data->interf_list,
+			 &params->interf_list,
+			 sizeof(struct INTERF_SRC_RSP));
+	else
+#endif
+	data->interf_list.count = 0;
+
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+	target_if_spectral_prep_skb(spectral);
+	if (spectral->spectral_skb) {
+	p_sops->get_mac_address(spectral, spec_samp_msg.macaddr);
+	spectral->spectral_nlh =
+		(struct nlmsghdr *)spectral->spectral_skb->data;
+	memcpy(NLMSG_DATA(spectral->spectral_nlh),
+	       &spec_samp_msg,
+	       sizeof(SPECTRAL_SAMP_MSG));
+	msg = (SPECTRAL_SAMP_MSG *)NLMSG_DATA(spectral->spectral_nlh);
+	/* Broadcast spectral data only if it is a edma supported device */
+	if (!spectral->sc_spectral_non_edma)
+		target_if_spectral_bcast_msg(spectral);
+	samp_msg_index++;
+	}
+
+	/* Check if the device is non-edma and follow the required broadcast
+	 * path if true
+	 */
+	if (spectral->sc_spectral_non_edma) {
+	/* Allocating memory for the queue entity to hold the spectral socket
+	 * buffer
+	 */
+	sp_skb_event = (struct target_if_spectral_skb_event
+	*)qdf_mem_malloc(sizeof(struct target_if_spectral_skb_event));
+
+	if (sp_skb_event) {
+		OS_MEMZERO(
+			sp_skb_event,
+			 sizeof(struct target_if_spectral_skb_event));
+		sp_skb_event->sp_skb = spectral->spectral_skb;
+		sp_skb_event->sp_nlh = spectral->spectral_nlh;
+		spectral->spectral_skb = NULL;
+		spectral->spectral_nlh = NULL;
+
+		/* Queue spectral socket buffers to be broadcasted outside irq
+		 * lock
+		 */
+		qdf_spin_lock(&spectral->spectral_skbqlock);
+		STAILQ_INSERT_TAIL(
+			&spectral->spectral_skbq,
+			 sp_skb_event,
+			 spectral_skb_list);
+		qdf_spin_unlock(&spectral->spectral_skbqlock);
+	}
+	}
+#else
+	/*
+	 * call the indicate function to pass the data to the net layer
+	 * Windows will pass to a spectral WIN32 service
+	 */
+	msg = (SPECTRAL_SAMP_MSG *)qdf_mem_malloc(sizeof(SPECTRAL_SAMP_MSG));
+	if (msg) {
+	OS_MEMCPY(msg, &spec_samp_msg, sizeof(SPECTRAL_SAMP_MSG));
+	ath_spectral_indicate(
+		params->sc,
+		 (void *)msg,
+		 sizeof(SPECTRAL_SAMP_MSG));
+	OS_FREE(msg);
+	msg = NULL;
+	} else {
+	qdf_print("No buffer\n");
+	}
+#endif  /* SPECTRAL_USE_NETLINK_SOCKETS */
+
+#ifdef HOST_OFFLOAD
+	atd_spectral_msg_send(spectral->ic->ic_osdev->netdev,
+			      &spec_samp_msg,
+		sizeof(SPECTRAL_SAMP_MSG));
+#endif
+
+	if (spectral->sc_spectral_noise_pwr_cal)
+	spectral_process_noise_pwr_report(spectral, &spec_samp_msg);
+}
+
+#ifdef SPECTRAL_USE_NETLINK_SOCKETS
+
+void target_if_spectral_prep_skb(struct target_if_spectral *spectral)
+{
+	spectral->spectral_skb = dev_alloc_skb(MAX_SPECTRAL_PAYLOAD);
+
+	if (spectral->spectral_skb) {
+	skb_put(spectral->spectral_skb, MAX_SPECTRAL_PAYLOAD);
+	spectral->spectral_nlh =
+		(struct nlmsghdr *)spectral->spectral_skb->data;
+
+	OS_MEMZERO(spectral->spectral_nlh, sizeof(*spectral->spectral_nlh));
+
+	/* Possible bug that size of  SPECTRAL_SAMP_MSG and SPECTRAL_MSG
+	 * differ by 3 bytes  so we miss 3 bytes
+	 */
+
+	spectral->spectral_nlh->nlmsg_len   =
+		NLMSG_SPACE(sizeof(SPECTRAL_SAMP_MSG));
+	spectral->spectral_nlh->nlmsg_pid   = 0;
+	spectral->spectral_nlh->nlmsg_flags = 0;
+	} else {
+	spectral->spectral_skb = NULL;
+	spectral->spectral_nlh = NULL;
+	}
+}
+
+void target_if_spectral_unicast_msg(struct target_if_spectral *spectral)
+{
+	if (!spectral) {
+	qdf_print("%s Spectral is NULL\n", __func__);
+	return;
+	}
+
+	if (!spectral->spectral_sock) {
+	qdf_print("%s Spectral Socket is invalid\n", __func__);
+	dev_kfree_skb(spectral->spectral_skb);
+	spectral->spectral_skb = NULL;
+	return;
+	}
+
+	if (spectral->spectral_skb) {
+#if (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
+	NETLINK_CB(spectral->spectral_skb).dst_pid = spectral->spectral_pid;
+#endif /* VERSION - field depracated by newer kernel */
+#if KERNEL_VERSION(3, 7, 0) > LINUX_VERSION_CODE
+	NETLINK_CB(spectral->spectral_skb).pid = 0;  /* from kernel */
+#else
+	NETLINK_CB(spectral->spectral_skb).portid = 0;  /* from kernel */
+#endif
+		/* to mcast group 1<<0 */
+	NETLINK_CB(spectral->spectral_skb).dst_group = 0;
+
+	netlink_unicast(
+		spectral->spectral_sock,
+		 spectral->spectral_skb,
+		 spectral->spectral_pid,
+		 MSG_DONTWAIT);
+	}
+}
+
+/*
+ * Function     : target_if_spectral_bcast_msg
+ * Description  : Passes the Spectral Message to Host
+ * Input        : Pointer to spectral
+ * Output       : Void
+ *
+ */
+void target_if_spectral_bcast_msg(struct target_if_spectral *spectral)
+{
+#if (KERNEL_VERSION(2, 6, 31) >= LINUX_VERSION_CODE)
+	fd_set write_set;
+#endif
+	SPECTRAL_SAMP_MSG *msg  = NULL;
+	struct nlmsghdr *nlh    = NULL;
+	int status;
+
+#if (KERNEL_VERSION(2, 6, 31) >= LINUX_VERSION_CODE)
+	FD_ZERO(&write_set);
+#endif
+
+	if (!spectral)
+	return;
+
+	if (!spectral->spectral_sock) {
+		dev_kfree_skb(spectral->spectral_skb);
+		spectral->spectral_skb = NULL;
+		return;
+	}
+
+	if (!spectral->spectral_skb)
+	return;
+
+	nlh = (struct nlmsghdr *)spectral->spectral_skb->data;
+	msg = (SPECTRAL_SAMP_MSG *)NLMSG_DATA(spectral->spectral_nlh);
+	/* print_samp_msg (msg, sc); */
+	status = target_if_send_phydata(
+		spectral->pdev_obj,
+		 spectral->spectral_sock,
+		 spectral->spectral_skb);
+	if (status == 0)
+		spectral->spectral_sent_msg++;
+
+	/* netlink will have freed the skb */
+	if (spectral->spectral_skb)
+		spectral->spectral_skb = NULL;
+}
+
+void target_if_spectral_skb_dequeue(unsigned long data)
+{
+	struct target_if_spectral *spectral =
+		(struct target_if_spectral *)data;
+	struct target_if_spectral_skb_event *sp_skb_event = NULL;
+
+	qdf_spin_lock(&spectral->spectral_skbqlock);
+	/* Deque all the spectral socket buffers queued */
+	while (!STAILQ_EMPTY(&spectral->spectral_skbq)) {
+	sp_skb_event = STAILQ_FIRST(&spectral->spectral_skbq);
+	if (sp_skb_event) {
+		spectral->spectral_skb = sp_skb_event->sp_skb;
+		spectral->spectral_nlh = sp_skb_event->sp_nlh;
+		STAILQ_REMOVE_HEAD(
+			&spectral->spectral_skbq,
+			spectral_skb_list);
+		qdf_spin_unlock(&spectral->spectral_skbqlock);
+		OS_FREE(sp_skb_event);
+		/* Broadcast spectral data after dequeing */
+		target_if_spectral_bcast_msg(spectral);
+		qdf_spin_lock(&spectral->spectral_skbqlock);
+	}
+	}
+	qdf_spin_unlock(&spectral->spectral_skbqlock);
+}
+
+#endif /* SPECTRAL_USE_NETLINK_SOCKETS */
+
diff --git a/target_if/spectral/target_if_spectral_phyerr.c b/target_if/spectral/target_if_spectral_phyerr.c
new file mode 100644
index 0000000..6f534b7
--- /dev/null
+++ b/target_if/spectral/target_if_spectral_phyerr.c
@@ -0,0 +1,1653 @@
+/*
+ * Copyright (c) 2011,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <osdep.h>
+#include <qdf_types.h>
+#include <wlan_tgt_def_config.h>
+#include <hif.h>
+#include <hif_hw_version.h>
+#include <wmi_unified_api.h>
+#include <target_if_spectral.h>
+#include <wlan_lmac_if_def.h>
+#include <wlan_osif_priv.h>
+#include <osif_rawmode_sim.h>
+/* START of spectral GEN II HW specific function declarations */
+static int dump_summary_report_gen2(
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv,
+	 int tlvlen,
+	 bool is_160_format);
+static int process_search_fft_report_gen2(
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv,
+	 int tlvlen,
+	 SPECTRAL_SEARCH_FFT_INFO_GEN2 *p_fft_info);
+static int dump_adc_report_gen2(SPECTRAL_PHYERR_TLV_GEN2 *ptlv, int tlvlen);
+static int dump_search_fft_report_gen2(
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv,
+	 int tlvlen,
+	 bool is_160_format);
+/* END of spectral GEN II HW specific function declarations */
+
+#if WLAN_SPECTRAL_ENABLE
+
+/*
+ * Function     : print_buf
+ * Description  : Prints given buffer for given length
+ * Input        : Pointer to buffer and length
+ * Output       : Void
+ *
+ */
+static void print_buf(u_int8_t *pbuf, int len)
+{
+	int i = 0;
+
+	for (i = 0; i < len; i++) {
+		qdf_print("%02X ", pbuf[i]);
+		if (i % 32 == 31)
+			qdf_print("\n");
+	}
+}
+
+/*
+ * Function     : target_if_spectral_dump_fft
+ * Description  : Dump Spectral FFT
+ * Input        : Pointer to Spectral Phyerr FFT
+ * Output       : Success/Failure
+ *
+ */
+int target_if_spectral_dump_fft(u_int8_t *pfft, int fftlen)
+{
+	int i = 0;
+
+	/* TODO : Do not delete the following print
+	 *        The scripts used to validate Spectral depend on this Print
+	 */
+	qdf_print("SPECTRAL : FFT Length is 0x%x (%d)\n", fftlen, fftlen);
+
+	qdf_print("fft_data # ");
+	for (i = 0; i < fftlen; i++) {
+		qdf_print("%d ", pfft[i]);
+		/* if (i % 32 == 31)
+		 * qdf_print("\n");
+		 */
+	}
+	qdf_print("\n");
+	return 0;
+}
+
+/*
+ * Function     : target_if_spectral_send_tlv_to_host
+ * Description  : Send the TLV information to Host
+ * Input        : Pointer to the TLV
+ * Output       : Success/Failure
+ *
+ */
+
+#ifdef HOST_OFFLOAD
+extern void
+atd_spectral_msg_send(
+	struct net_device *dev,
+	 SPECTRAL_SAMP_MSG *msg,
+	 uint16_t msg_len);
+#endif
+
+int target_if_spectral_send_tlv_to_host(
+	struct target_if_spectral *spectral,
+	 u_int8_t *data,
+	 u_int32_t datalen)
+{
+	int status = true;
+
+	target_if_spectral_prep_skb(spectral);
+	if (spectral->spectral_skb) {
+		spectral->spectral_nlh =
+			(struct nlmsghdr *)spectral->spectral_skb->data;
+		memcpy(NLMSG_DATA(spectral->spectral_nlh), data, datalen);
+		target_if_spectral_bcast_msg(spectral);
+	} else {
+		status = false;
+	}
+#ifdef HOST_OFFLOAD
+	atd_spectral_msg_send(spectral->ic->ic_osdev->netdev,
+			      data,
+		datalen);
+#endif
+	return status;
+}
+
+/*
+ * Function     : dbg_print_SAMP_param
+ * Description  : Print contents of SAMP struct
+ * Input        : Pointer to SAMP message
+ * Output       : Void
+ *
+ */
+void target_if_dbg_print_SAMP_param(struct target_if_samp_msg_params *p)
+{
+	qdf_print("\nSAMP Packet : -------------------- START --------------"
+		  "------\n");
+	qdf_print("Freq        = %d\n", p->freq);
+	qdf_print("RSSI        = %d\n", p->rssi);
+	qdf_print("Bin Count   = %d\n", p->pwr_count);
+	qdf_print("Timestamp   = %d\n", p->tstamp);
+	qdf_print("SAMP Packet : -------------------- END ------------------"
+		  "-----\n");
+}
+
+/*
+ * Function     : dbg_print_SAMP_msg
+ * Description  : Print contents of SAMP Message
+ * Input        : Pointer to SAMP message
+ * Output       : Void
+ *
+ */
+void target_if_dbg_print_SAMP_msg(SPECTRAL_SAMP_MSG *ss_msg)
+{
+	int i = 0;
+
+	SPECTRAL_SAMP_DATA *p = &ss_msg->samp_data;
+	SPECTRAL_CLASSIFIER_PARAMS *pc = &p->classifier_params;
+	struct INTERF_SRC_RSP *pi = &p->interf_list;
+
+	line();
+	qdf_print("Spectral Message\n");
+	line();
+	qdf_print("Signature   :   0x%x\n", ss_msg->signature);
+	qdf_print("Freq        :   %d\n", ss_msg->freq);
+	qdf_print("Freq load   :   %d\n", ss_msg->freq_loading);
+	qdf_print("Intfnc type :   %d\n", ss_msg->int_type);
+	line();
+	qdf_print("Spectral Data info\n");
+	line();
+	qdf_print("data length     :   %d\n", p->spectral_data_len);
+	qdf_print("rssi            :   %d\n", p->spectral_rssi);
+	qdf_print("combined rssi   :   %d\n", p->spectral_combined_rssi);
+	qdf_print("upper rssi      :   %d\n", p->spectral_upper_rssi);
+	qdf_print("lower rssi      :   %d\n", p->spectral_lower_rssi);
+	qdf_print("bw info         :   %d\n", p->spectral_bwinfo);
+	qdf_print("timestamp       :   %d\n", p->spectral_tstamp);
+	qdf_print("max index       :   %d\n", p->spectral_max_index);
+	qdf_print("max exp         :   %d\n", p->spectral_max_exp);
+	qdf_print("max mag         :   %d\n", p->spectral_max_mag);
+	qdf_print("last timstamp   :   %d\n", p->spectral_last_tstamp);
+	qdf_print("upper max idx   :   %d\n", p->spectral_upper_max_index);
+	qdf_print("lower max idx   :   %d\n", p->spectral_lower_max_index);
+	qdf_print("bin power count :   %d\n", p->bin_pwr_count);
+	line();
+	qdf_print("Classifier info\n");
+	line();
+	qdf_print("20/40 Mode      :   %d\n", pc->spectral_20_40_mode);
+	qdf_print("dc index        :   %d\n", pc->spectral_dc_index);
+	qdf_print("dc in MHz       :   %d\n", pc->spectral_dc_in_mhz);
+	qdf_print("upper channel   :   %d\n", pc->upper_chan_in_mhz);
+	qdf_print("lower channel   :   %d\n", pc->lower_chan_in_mhz);
+	line();
+	qdf_print("Interference info\n");
+	line();
+	qdf_print("inter count     :   %d\n", pi->count);
+
+	for (i = 0; i < pi->count; i++) {
+	qdf_print("inter type  :   %d\n", pi->interf[i].interf_type);
+	qdf_print("min freq    :   %d\n", pi->interf[i].interf_min_freq);
+	qdf_print("max freq    :   %d\n", pi->interf[i].interf_max_freq);
+	}
+}
+
+/*
+ * Function     : get_offset_swar_sec80
+ * Description  : Get offset for SWAR according to the channel width
+ * Input        : Channel width
+ * Output       : Offset for SWAR algorithm
+ */
+uint32_t target_if_get_offset_swar_sec80(uint32_t channel_width)
+{
+	uint32_t offset = 0;
+
+	switch (channel_width) {
+	case IEEE80211_CWM_WIDTH20:
+		offset = OFFSET_CH_WIDTH_20;
+		break;
+	case IEEE80211_CWM_WIDTH40:
+		offset = OFFSET_CH_WIDTH_40;
+		break;
+	case IEEE80211_CWM_WIDTH80:
+		offset = OFFSET_CH_WIDTH_80;
+		break;
+	case IEEE80211_CWM_WIDTH160:
+		offset = OFFSET_CH_WIDTH_160;
+		break;
+	default:
+		offset = OFFSET_CH_WIDTH_80;
+		break;
+	}
+	return offset;
+}
+
+/* START of spectral GEN II HW specific functions */
+
+/*
+ * Function     : dump_summary_report_gen2
+ * Description  : Dump Spectral Summary Report
+ * Input        : Pointer to Spectral Phyerr TLV and Length, flag indicating
+ *                whether information provided by HW is in altered format for
+ *                802.11ac 160/80+80 MHz support (QCA9984 onwards).
+ * Output       : Success/Failure
+ *
+ */
+int dump_summary_report_gen2(
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv,
+	 int tlvlen,
+	 bool is_160_format)
+{
+	/* For simplicity, everything is defined as uint32_t (except one).
+	 * Proper code will later use the right sizes.
+	 */
+
+	/* For easy comparision between MDK team and OS team, the MDK script
+	 * variable names have been used
+	 */
+
+	uint32_t agc_mb_gain;
+	uint32_t sscan_gidx;
+	uint32_t agc_total_gain;
+	uint32_t recent_rfsat;
+	uint32_t ob_flag;
+	uint32_t nb_mask;
+	uint32_t peak_mag;
+	int16_t peak_inx;
+
+	uint32_t ss_summary_A = 0;
+	uint32_t ss_summary_B = 0;
+	uint32_t ss_summary_C = 0;
+	uint32_t ss_summary_D = 0;
+	uint32_t ss_summary_E = 0;
+	SPECTRAL_PHYERR_HDR_GEN2 *phdr =
+		(SPECTRAL_PHYERR_HDR_GEN2 *)((u_int8_t *)ptlv +
+		sizeof(SPECTRAL_PHYERR_TLV_GEN2));
+
+	qdf_print("SPECTRAL : SPECTRAL SUMMARY REPORT\n");
+
+	if (is_160_format) {
+	if (tlvlen != 20) {
+		qdf_print("SPECTRAL : Unexpected TLV length %d for Spectral "
+			  "Summary Report! Hexdump follows\n", tlvlen);
+		print_buf((u_int8_t *)ptlv, tlvlen + 4);
+		return -EPERM;
+	}
+
+	/* Doing copy as the contents may not be aligned */
+	qdf_mem_copy(&ss_summary_A, (u_int8_t *)phdr, sizeof(int));
+	qdf_mem_copy(
+		&ss_summary_B,
+		 (u_int8_t *)((u_int8_t *)phdr + sizeof(int)),
+		 sizeof(int));
+	qdf_mem_copy(
+		&ss_summary_C,
+		 (u_int8_t *)((u_int8_t *)phdr + 2 * sizeof(int)),
+		 sizeof(int));
+	qdf_mem_copy(
+		&ss_summary_D,
+		 (u_int8_t *)((u_int8_t *)phdr + 3 * sizeof(int)),
+		 sizeof(int));
+	qdf_mem_copy(
+		&ss_summary_E,
+		 (u_int8_t *)((u_int8_t *)phdr + 4 * sizeof(int)),
+		 sizeof(int));
+
+	/*The following is adapted from MDK scripts for easier comparability */
+
+	recent_rfsat = ((ss_summary_A >> 8) & 0x1);
+	sscan_gidx = (ss_summary_A & 0xff);
+	printf("sscan_gidx=%d, is_recent_rfsat=%d\n",
+	       sscan_gidx, recent_rfsat);
+
+	/* First segment */
+	agc_mb_gain = ((ss_summary_B >> 10) & 0x7f);
+	agc_total_gain = (ss_summary_B & 0x3ff);
+	nb_mask = ((ss_summary_C >> 22) & 0xff);
+	ob_flag = ((ss_summary_B >> 17) & 0x1);
+	peak_inx = (ss_summary_C  & 0xfff);
+	if (peak_inx > 2047)
+		peak_inx = peak_inx - 4096;
+	peak_mag = ((ss_summary_C >> 12) & 0x3ff);
+
+	printf("agc_total_gain_segid0 = 0x%.2x, agc_mb_gain_segid0=%d\n",
+	       agc_total_gain, agc_mb_gain);
+	printf("nb_mask_segid0 = 0x%.2x, ob_flag_segid0=%d, "
+	       "peak_index_segid0=%d, peak_mag_segid0=%d\n",
+	       nb_mask, ob_flag, peak_inx, peak_mag);
+
+	/* Second segment */
+	agc_mb_gain = ((ss_summary_D >> 10) & 0x7f);
+	agc_total_gain = (ss_summary_D & 0x3ff);
+	nb_mask = ((ss_summary_E >> 22) & 0xff);
+	ob_flag = ((ss_summary_D >> 17) & 0x1);
+	peak_inx = (ss_summary_E  & 0xfff);
+	if (peak_inx > 2047)
+		peak_inx = peak_inx - 4096;
+	peak_mag = ((ss_summary_E >> 12) & 0x3ff);
+
+	printf("agc_total_gain_segid1 = 0x%.2x, agc_mb_gain_segid1=%d\n",
+	       agc_total_gain, agc_mb_gain);
+	printf("nb_mask_segid1 = 0x%.2x, ob_flag_segid1=%d, "
+	       "peak_index_segid1=%d, peak_mag_segid1=%d\n",
+	       nb_mask, ob_flag, peak_inx, peak_mag);
+	} else {
+	if (tlvlen != 8) {
+		qdf_print("SPECTRAL : Unexpected TLV length %d for Spectral "
+			  "Summary Report! Hexdump follows\n", tlvlen);
+		print_buf((u_int8_t *)ptlv, tlvlen + 4);
+		return -EPERM;
+	}
+
+	/* Doing copy as the contents may not be aligned */
+	qdf_mem_copy(&ss_summary_A, (u_int8_t *)phdr, sizeof(int));
+	qdf_mem_copy(
+		&ss_summary_B,
+		 (u_int8_t *)((u_int8_t *)phdr + sizeof(int)),
+		 sizeof(int));
+
+	nb_mask = ((ss_summary_B >> 22) & 0xff);
+	ob_flag = ((ss_summary_B >> 30) & 0x1);
+	peak_inx = (ss_summary_B  & 0xfff);
+
+	if (peak_inx > 2047)
+		peak_inx = peak_inx - 4096;
+
+	peak_mag = ((ss_summary_B >> 12) & 0x3ff);
+	agc_mb_gain = ((ss_summary_A >> 24) & 0x7f);
+	agc_total_gain = (ss_summary_A  & 0x3ff);
+	sscan_gidx = ((ss_summary_A >> 16) & 0xff);
+	recent_rfsat = ((ss_summary_B >> 31) & 0x1);
+
+	qdf_print("nb_mask = 0x%.2x, ob_flag=%d, peak_index=%d, peak_mag=%d, "
+		  "agc_mb_gain=%d, agc_total_gain=%d, sscan_gidx=%d, "
+		  "recent_rfsat=%d\n",
+		  nb_mask, ob_flag, peak_inx, peak_mag, agc_mb_gain,
+		  agc_total_gain, sscan_gidx, recent_rfsat);
+	}
+
+	return 0;
+}
+
+/*
+ * Function     : process_search_fft_report_gen2
+ * Description  : Process Search FFT Report
+ * Input        : Pointer to Spectral Phyerr TLV and Length and pointer to
+ *                search fft info
+ * Output       : Success/Failure
+ *
+ */
+int process_search_fft_report_gen2(
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv,
+	 int tlvlen,
+	 SPECTRAL_SEARCH_FFT_INFO_GEN2 *p_fft_info)
+{
+	/* For simplicity, everything is defined as uint32_t (except one).
+	 * Proper code will later use the right sizes.
+	 */
+	/* For easy comparision between MDK team and OS team, the MDK script
+	 * variable names have been used
+	 */
+	uint32_t relpwr_db;
+	uint32_t num_str_bins_ib;
+	uint32_t base_pwr;
+	uint32_t total_gain_info;
+
+	uint32_t fft_chn_idx;
+	int16_t peak_inx;
+	uint32_t avgpwr_db;
+	uint32_t peak_mag;
+
+	uint32_t fft_summary_A = 0;
+	uint32_t fft_summary_B = 0;
+	u_int8_t *tmp = (u_int8_t *)ptlv;
+	SPECTRAL_PHYERR_HDR_GEN2 *phdr =
+	  (SPECTRAL_PHYERR_HDR_GEN2 *)(tmp + sizeof(SPECTRAL_PHYERR_TLV_GEN2));
+
+	/* Relook this */
+	if (tlvlen < 8) {
+		qdf_print("SPECTRAL : Unexpected TLV length %d for Spectral "
+			  "Summary Report! Hexdump follows\n", tlvlen);
+		print_buf((u_int8_t *)ptlv, tlvlen + 4);
+		return -EPERM;
+	}
+
+	/* Doing copy as the contents may not be aligned */
+	qdf_mem_copy(&fft_summary_A, (u_int8_t *)phdr, sizeof(int));
+	qdf_mem_copy(
+		&fft_summary_B,
+		 (u_int8_t *)((u_int8_t *)phdr + sizeof(int)),
+		 sizeof(int));
+
+	relpwr_db       = ((fft_summary_B >> 26) & 0x3f);
+	num_str_bins_ib = fft_summary_B & 0xff;
+	base_pwr        = ((fft_summary_A >> 14) & 0x1ff);
+	total_gain_info = ((fft_summary_A >> 23) & 0x1ff);
+
+	fft_chn_idx     = ((fft_summary_A >> 12) & 0x3);
+	peak_inx        = fft_summary_A & 0xfff;
+
+	if (peak_inx > 2047)
+		peak_inx = peak_inx - 4096;
+
+	avgpwr_db = ((fft_summary_B >> 18) & 0xff);
+	peak_mag = ((fft_summary_B >> 8) & 0x3ff);
+
+	/* Populate the Search FFT Info */
+	if (p_fft_info) {
+	p_fft_info->relpwr_db       = relpwr_db;
+	p_fft_info->num_str_bins_ib = num_str_bins_ib;
+	p_fft_info->base_pwr        = base_pwr;
+	p_fft_info->total_gain_info = total_gain_info;
+	p_fft_info->fft_chn_idx     = fft_chn_idx;
+	p_fft_info->peak_inx        = peak_inx;
+	p_fft_info->avgpwr_db       = avgpwr_db;
+	p_fft_info->peak_mag        = peak_mag;
+	}
+
+	return 0;
+}
+
+/*
+ * Function     : dump_adc_report_gen2
+ * Description  : Dump ADC Reports
+ * Input        : Pointer to Spectral Phyerr TLV and Length
+ * Output       : Success/Failure
+ *
+ */
+int dump_adc_report_gen2(SPECTRAL_PHYERR_TLV_GEN2 *ptlv, int tlvlen)
+{
+	int i;
+	uint32_t *pdata;
+	uint32_t data;
+
+	/* For simplicity, everything is defined as uint32_t (except one).
+	 * Proper code will later use the right sizes.
+	 */
+	uint32_t samp_fmt;
+	uint32_t chn_idx;
+	uint32_t recent_rfsat;
+	uint32_t agc_mb_gain;
+	uint32_t agc_total_gain;
+
+	uint32_t adc_summary = 0;
+
+	u_int8_t *ptmp = (u_int8_t *)ptlv;
+
+	qdf_print("SPECTRAL : ADC REPORT\n");
+
+	/* Relook this */
+	if (tlvlen < 4) {
+		qdf_print("Unexpected TLV length %d for ADC Report! Hexdump"
+			  " follows\n", tlvlen);
+		print_buf((u_int8_t *)ptlv, tlvlen + 4);
+		return -EPERM;
+	}
+
+	qdf_mem_copy(&adc_summary, (u_int8_t *)(ptlv + 4), sizeof(int));
+
+	samp_fmt = ((adc_summary >> 28) & 0x1);
+	chn_idx = ((adc_summary >> 24) & 0x3);
+	recent_rfsat = ((adc_summary >> 23) & 0x1);
+	agc_mb_gain = ((adc_summary >> 16) & 0x7f);
+	agc_total_gain = adc_summary & 0x3ff;
+
+	qdf_print("samp_fmt= %u, chn_idx= %u, recent_rfsat= %u, agc_mb_gain=%u"
+		  " agc_total_gain=%u\n", samp_fmt, chn_idx, recent_rfsat,
+		  agc_mb_gain, agc_total_gain);
+
+	for (i = 0; i < (tlvlen / 4); i++) {
+	pdata = (uint32_t *)(ptmp + 4 + i * 4);
+	data = *pdata;
+
+	/* Interpreting capture format 1 */
+	if (1) {
+		uint8_t i1;
+		uint8_t q1;
+		uint8_t i2;
+		uint8_t q2;
+		int8_t si1;
+		int8_t sq1;
+		int8_t si2;
+		int8_t sq2;
+
+		i1 = data & 0xff;
+		q1 = (data >> 8) & 0xff;
+		i2 = (data >> 16) & 0xff;
+		q2 = (data >> 24) & 0xff;
+
+		if (i1 > 127)
+			si1 = i1 - 256;
+		else
+			si1 = i1;
+
+		if (q1 > 127)
+			sq1 = q1 - 256;
+		else
+			sq1 = q1;
+
+		if (i2 > 127)
+			si2 = i2 - 256;
+		else
+			si2 = i2;
+
+		if (q2 > 127)
+			sq2 = q2 - 256;
+		else
+			sq2 = q2;
+
+		qdf_print("SPECTRAL ADC : Interpreting capture format 1\n");
+		qdf_print("adc_data_format_1 # %d %d %d\n", 2 * i, si1, sq1);
+		qdf_print("adc_data_format_1 # %d %d %d\n",
+			  2 * i + 1, si2, sq2);
+	}
+
+	/* Interpreting capture format 0 */
+	if (1) {
+		uint16_t i1;
+		uint16_t q1;
+		int16_t si1;
+		int16_t sq1;
+
+		i1 = data & 0xffff;
+		q1 = (data >> 16) & 0xffff;
+		if (i1 > 32767)
+			si1 = i1 - 65536;
+		else
+			si1 = i1;
+
+		if (q1 > 32767)
+			sq1 = q1 - 65536;
+		else
+			sq1 = q1;
+		qdf_print("SPECTRAL ADC : Interpreting capture format 0\n");
+		qdf_print("adc_data_format_2 # %d %d %d\n", i, si1, sq1);
+	}
+	}
+
+	qdf_print("\n");
+
+	return 0;
+}
+
+/*
+ * Function     : dump_search_fft_report_gen2
+ * Description  : Process Search FFT Report
+ * Input        : Pointer to Spectral Phyerr TLV and Length, flag indicating
+ *                whether information provided by HW is in altered format for
+ *                802.11ac 160/80+80 MHz support (QCA9984 onwards).
+ * Output       : Success/Failure
+ *
+ */
+int dump_search_fft_report_gen2(
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv,
+	 int tlvlen,
+	 bool is_160_format)
+{
+	int i;
+	uint32_t fft_mag;
+
+	/* For simplicity, everything is defined as uint32_t (except one).
+	 * Proper code will later use the right sizes.
+	 */
+	/* For easy comparision between MDK team and OS team, the MDK script
+	 * variable names have been used
+	 */
+	uint32_t relpwr_db;
+	uint32_t num_str_bins_ib;
+	uint32_t base_pwr;
+	uint32_t total_gain_info;
+
+	uint32_t fft_chn_idx;
+	int16_t peak_inx;
+	uint32_t avgpwr_db;
+	uint32_t peak_mag;
+	u_int8_t segid;
+
+	uint32_t fft_summary_A = 0;
+	uint32_t fft_summary_B = 0;
+	uint32_t fft_summary_C = 0;
+	u_int8_t *tmp = (u_int8_t *)ptlv;
+	SPECTRAL_PHYERR_HDR_GEN2 *phdr =
+	  (SPECTRAL_PHYERR_HDR_GEN2 *)(tmp + sizeof(SPECTRAL_PHYERR_TLV_GEN2));
+	u_int32_t segid_skiplen = 0;
+
+	if (is_160_format)
+		segid_skiplen = sizeof(SPECTRAL_SEGID_INFO);
+
+	qdf_print("SPECTRAL : SEARCH FFT REPORT\n");
+
+	/* Relook this */
+	if (tlvlen < (8 + segid_skiplen)) {
+		qdf_print("SPECTRAL : Unexpected TLV length %d for Spectral "
+			  "Summary Report! Hexdump follows\n", tlvlen);
+		print_buf((u_int8_t *)ptlv, tlvlen + 4);
+		return -EPERM;
+	}
+
+	/* Doing copy as the contents may not be aligned */
+	qdf_mem_copy(&fft_summary_A, (u_int8_t *)phdr, sizeof(int));
+	qdf_mem_copy(
+		&fft_summary_B,
+		 (u_int8_t *)((u_int8_t *)phdr + sizeof(int)),
+		 sizeof(int));
+	if (is_160_format)
+		qdf_mem_copy(
+			&fft_summary_C,
+			 (u_int8_t *)((u_int8_t *)phdr + 2 * sizeof(int)),
+			 sizeof(int));
+
+	relpwr_db       = ((fft_summary_B >> 26) & 0x3f);
+	num_str_bins_ib = fft_summary_B & 0xff;
+	base_pwr        = ((fft_summary_A >> 14) & 0x1ff);
+	total_gain_info = ((fft_summary_A >> 23) & 0x1ff);
+
+	fft_chn_idx     = ((fft_summary_A >> 12) & 0x3);
+	peak_inx        = fft_summary_A & 0xfff;
+
+	if (peak_inx > 2047)
+		peak_inx = peak_inx - 4096;
+
+	avgpwr_db = ((fft_summary_B >> 18) & 0xff);
+	peak_mag = ((fft_summary_B >> 8) & 0x3ff);
+
+	qdf_print("Header A = 0x%x Header B = 0x%x\n",
+		  phdr->hdr_a, phdr->hdr_b);
+	qdf_print("Base Power= 0x%x, Total Gain= %d, relpwr_db=%d, "
+		  "num_str_bins_ib=%d fft_chn_idx=%d peak_inx=%d avgpwr_db=%d "
+		  "peak_mag=%d\n", base_pwr, total_gain_info, relpwr_db,
+		  num_str_bins_ib, fft_chn_idx, peak_inx, avgpwr_db, peak_mag);
+	if (is_160_format) {
+		segid = fft_summary_C & 0x1;
+		qdf_print("Segment ID: %hhu\n", segid);
+	}
+
+	qdf_print("FFT bins:\n");
+	for (i = 0; i < (tlvlen - 8 - segid_skiplen); i++) {
+	fft_mag = ((u_int8_t *)ptlv)[12 + segid_skiplen + i];
+	qdf_print("%d %d, ", i, fft_mag);
+	}
+
+	qdf_print("\n");
+
+	return 0;
+}
+
+/*
+ * Function     : spectral_process_phyerr_gen2
+ * Description  : Process PHY Error
+ * Input        : Pointer to buffer
+ * Output       : Success/Failure
+ *
+ */
+int spectral_process_phyerr_gen2(
+	struct target_if_spectral *spectral,
+	u_int8_t *data,
+	u_int32_t datalen, struct target_if_spectral_rfqual_info *p_rfqual,
+	struct target_if_spectral_chan_info *p_chaninfo,
+	u_int64_t tsf64,
+	struct target_if_spectral_acs_stats *acs_stats)
+{
+	/*
+	 * XXX : The classifier do not use all the members of the SAMP
+	 *       message data format.
+	 *       The classifier only depends upon the following parameters
+	 *
+	 *          1. Frequency (freq, msg->freq)
+	 *          2. Spectral RSSI (spectral_rssi,
+	 *          msg->samp_data.spectral_rssi)
+	 *          3. Bin Power Count (bin_pwr_count,
+	 *          msg->samp_data.bin_pwr_count)
+	 *          4. Bin Power values (bin_pwr, msg->samp_data.bin_pwr[0]
+	 *          5. Spectral Timestamp (spectral_tstamp,
+	 *          msg->samp_data.spectral_tstamp)
+	 *          6. MAC Address (macaddr, msg->macaddr)
+	 *
+	 *       This function prepares the params structure and populates it
+	 *       with
+	 *       relevant values, this is in turn passed to
+	 *       spectral_create_samp_msg()
+	 *       to prepare fully formatted Spectral SAMP message
+	 *
+	 *       XXX : Need to verify
+	 *          1. Order of FFT bin values
+	 *
+	 */
+
+	struct target_if_samp_msg_params params;
+	SPECTRAL_SEARCH_FFT_INFO_GEN2 search_fft_info;
+	SPECTRAL_SEARCH_FFT_INFO_GEN2 *p_sfft = &search_fft_info;
+	SPECTRAL_SEARCH_FFT_INFO_GEN2 search_fft_info_sec80;
+	SPECTRAL_SEARCH_FFT_INFO_GEN2 *p_sfft_sec80 = &search_fft_info_sec80;
+	u_int32_t segid_skiplen = 0;
+
+	int8_t rssi_up  = 0;
+	int8_t rssi_low = 0;
+
+	int8_t chn_idx_highest_enabled = 0;
+	int8_t chn_idx_lowest_enabled  = 0;
+
+	u_int8_t control_rssi   = 0;
+	u_int8_t extension_rssi = 0;
+	u_int8_t combined_rssi  = 0;
+
+	u_int32_t tstamp    = 0;
+
+	struct target_if_spectral_ops *p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv = (SPECTRAL_PHYERR_TLV_GEN2 *)data;
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv_sec80 = NULL;
+	SPECTRAL_PHYERR_FFT_GEN2 *pfft = NULL;
+	SPECTRAL_PHYERR_FFT_GEN2 *pfft_sec80 = NULL;
+
+	u_int8_t segid = 0;
+	u_int8_t segid_sec80 = 0;
+
+	if (spectral->is_160_format)
+	segid_skiplen = sizeof(SPECTRAL_SEGID_INFO);
+
+	pfft = (SPECTRAL_PHYERR_FFT_GEN2 *)(data +
+	  sizeof(SPECTRAL_PHYERR_TLV_GEN2) +
+	  sizeof(SPECTRAL_PHYERR_HDR_GEN2) + segid_skiplen);
+
+	/* XXX Extend SPECTRAL_DPRINTK() to use spectral_debug_level,
+	 * and use this facility inside spectral_dump_phyerr_data()
+	 * and supporting functions.
+	 */
+	if (spectral_debug_level & ATH_DEBUG_SPECTRAL2)
+	spectral_dump_phyerr_data_gen2(data, datalen, spectral->is_160_format);
+
+	if (spectral_debug_level & ATH_DEBUG_SPECTRAL4) {
+	spectral_dump_phyerr_data_gen2(data, datalen, spectral->is_160_format);
+	spectral_debug_level = ATH_DEBUG_SPECTRAL;
+	}
+
+	if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) {
+	/* EV# 118023: We tentatively disable the below print
+	 * and provide stats instead.
+	 */
+	/* qdf_print("SPECTRAL : Mismatch\n"); */
+	spectral->diag_stats.spectral_mismatch++;
+	return -EPERM;
+	}
+
+	OS_MEMZERO(&params, sizeof(params));
+
+	if (ptlv->tag == TLV_TAG_SEARCH_FFT_REPORT_GEN2) {
+	if (spectral->is_160_format) {
+		segid = *((SPECTRAL_SEGID_INFO *)(
+				(u_int8_t *)ptlv +
+				sizeof(SPECTRAL_PHYERR_TLV_GEN2) +
+				sizeof(SPECTRAL_PHYERR_HDR_GEN2)));
+
+		if (segid != 0) {
+		spectral->diag_stats.spectral_vhtseg1id_mismatch++;
+		return -EPERM;
+		}
+	}
+
+	process_search_fft_report_gen2(ptlv, ptlv->length, &search_fft_info);
+
+	tstamp = p_sops->get_tsf64(spectral) & SPECTRAL_TSMASK;
+
+	combined_rssi   = p_rfqual->rssi_comb;
+
+	if (spectral->upper_is_control)
+		rssi_up = control_rssi;
+	else
+		rssi_up = extension_rssi;
+
+	if (spectral->lower_is_control)
+		rssi_low = control_rssi;
+	else
+		rssi_low = extension_rssi;
+
+	params.rssi         = p_rfqual->rssi_comb;
+	params.lower_rssi   = rssi_low;
+	params.upper_rssi   = rssi_up;
+
+	if (spectral->sc_spectral_noise_pwr_cal) {
+		params.chain_ctl_rssi[0] =
+			p_rfqual->pc_rssi_info[0].rssi_pri20;
+		params.chain_ctl_rssi[1] =
+			p_rfqual->pc_rssi_info[1].rssi_pri20;
+		params.chain_ctl_rssi[2] =
+			p_rfqual->pc_rssi_info[2].rssi_pri20;
+		params.chain_ext_rssi[0] =
+			p_rfqual->pc_rssi_info[0].rssi_sec20;
+		params.chain_ext_rssi[1] =
+			p_rfqual->pc_rssi_info[1].rssi_sec20;
+		params.chain_ext_rssi[2] =
+			p_rfqual->pc_rssi_info[2].rssi_sec20;
+	}
+
+	/*
+	 * XXX : This actually depends on the programmed chain mask
+	 *       There are three chains in Peregrine and 4 chains in Beeliner &
+	 *       Cascade
+	 *       This value decides the per-chain enable mask to select
+	 *       the input ADC for search FTT.
+	 *       For modes upto VHT80, if more than one chain is enabled, the
+	 *       max valid chain
+	 *       is used. LSB corresponds to chain zero.
+	 *       For VHT80_80 and VHT160, the lowest enabled chain is used for
+	 *       primary
+	 *       detection and highest enabled chain is used for secondary
+	 *       detection.
+	 *
+	 *  XXX: The current algorithm do not use these control and extension
+	 *       channel
+	 *       Instead, it just relies on the combined RSSI values only.
+	 *       For fool-proof detection algorithm, we should take these RSSI
+	 *       values
+	 *       in to account. This is marked for future enhancements.
+	 */
+	chn_idx_highest_enabled = ((spectral->params.ss_chn_mask & 0x8) ? 3 :
+			(spectral->params.ss_chn_mask & 0x4) ? 2 :
+			(spectral->params.ss_chn_mask & 0x2) ? 1 : 0);
+	chn_idx_lowest_enabled  = ((spectral->params.ss_chn_mask & 0x1) ? 0 :
+			(spectral->params.ss_chn_mask & 0x2) ? 1 :
+			(spectral->params.ss_chn_mask & 0x4) ? 2 : 3);
+	control_rssi    = (u_int8_t)
+		p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_pri20;
+	extension_rssi  = (u_int8_t)
+		p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_sec20;
+
+	params.bwinfo   = 0;
+	params.tstamp   = 0;
+	params.max_mag  = p_sfft->peak_mag;
+
+	params.max_index    = p_sfft->peak_inx;
+	params.max_exp      = 0;
+	params.peak         = 0;
+	params.bin_pwr_data = (u_int8_t *)pfft;
+	params.freq         = p_sops->get_current_channel(spectral);
+	params.freq_loading = 0;
+
+	params.interf_list.count = 0;
+	params.max_lower_index   = 0;
+	params.max_upper_index   = 0;
+	params.nb_lower          = 0;
+	params.nb_upper          = 0;
+	/*
+	 * For modes upto VHT80, the noise floor is populated with the one
+	 * corresponding
+	 * to the highest enabled antenna chain
+	 */
+	params.noise_floor       =
+		p_rfqual->noise_floor[chn_idx_highest_enabled];
+	params.datalen           = ptlv->length;
+	params.pwr_count         = ptlv->length -
+		sizeof(SPECTRAL_PHYERR_HDR_GEN2) - segid_skiplen;
+	params.tstamp            = (tsf64 & SPECTRAL_TSMASK);
+
+	acs_stats->ctrl_nf             = params.noise_floor;
+	acs_stats->ext_nf              = params.noise_floor;
+	acs_stats->nfc_ctl_rssi        = control_rssi;
+	acs_stats->nfc_ext_rssi        = extension_rssi;
+
+	if (spectral->is_160_format &&
+	    spectral->ch_width == IEEE80211_CWM_WIDTH160) {
+		/* We expect to see one more Search FFT report, and it should
+		 * be equal in size to the current one.
+		 */
+		if (datalen < (2 * (sizeof(SPECTRAL_PHYERR_TLV_GEN2) +
+			ptlv->length))) {
+			spectral->diag_stats.spectral_sec80_sfft_insufflen++;
+			return -EPERM;
+		}
+
+		ptlv_sec80 = (SPECTRAL_PHYERR_TLV_GEN2 *)(
+					data +
+					sizeof(SPECTRAL_PHYERR_TLV_GEN2) +
+					ptlv->length);
+
+		if (ptlv_sec80->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) {
+			spectral->diag_stats.spectral_mismatch++;
+			return -EPERM;
+		}
+
+		if (ptlv_sec80->tag != TLV_TAG_SEARCH_FFT_REPORT_GEN2) {
+			spectral->diag_stats.spectral_no_sec80_sfft++;
+			return -EPERM;
+		}
+
+		segid_sec80 = *((SPECTRAL_SEGID_INFO *)(
+					(u_int8_t *)ptlv_sec80 +
+					sizeof(SPECTRAL_PHYERR_TLV_GEN2) +
+					sizeof(SPECTRAL_PHYERR_HDR_GEN2)));
+
+		if (segid_sec80 != 1) {
+		spectral->diag_stats.spectral_vhtseg2id_mismatch++;
+		return -EPERM;
+		}
+
+		params.vhtop_ch_freq_seg1  = p_chaninfo->center_freq1;
+		params.vhtop_ch_freq_seg2  = p_chaninfo->center_freq2;
+
+		process_search_fft_report_gen2(
+			ptlv_sec80,
+			ptlv_sec80->length, &search_fft_info_sec80);
+
+		pfft_sec80 = (SPECTRAL_PHYERR_FFT_GEN2 *)(
+				((u_int8_t *)ptlv_sec80) +
+				sizeof(SPECTRAL_PHYERR_TLV_GEN2) +
+				sizeof(SPECTRAL_PHYERR_HDR_GEN2) +
+				segid_skiplen);
+
+		/* XXX: Confirm. TBD at SoD. */
+		params.rssi_sec80           = p_rfqual->rssi_comb;
+		if (spectral->is_sec80_rssi_war_required)
+			params.rssi_sec80 =
+				get_combined_rssi_sec80_segment_gen2(
+					spectral,
+					&search_fft_info_sec80);
+		/* XXX: Determine dynamically. TBD at SoD. */
+		/*
+		 * For VHT80_80/VHT160, the noise floor for primary 80MHz
+		 * segment is populated with the
+		 * lowest enabled antenna chain and the noise floor for
+		 * secondary 80MHz segment is populated
+		 * with the highest enabled antenna chain
+		 */
+		params.noise_floor_sec80    =
+			p_rfqual->noise_floor[chn_idx_highest_enabled];
+		params.noise_floor          =
+			p_rfqual->noise_floor[chn_idx_lowest_enabled];
+
+		params.max_mag_sec80        = p_sfft_sec80->peak_mag;
+		params.max_index_sec80      = p_sfft_sec80->peak_inx;
+		/* XXX Does this definition of datalen *still hold? */
+		params.datalen_sec80        = ptlv_sec80->length;
+		params.pwr_count_sec80      =
+			ptlv_sec80->length -
+			sizeof(SPECTRAL_PHYERR_HDR_GEN2) -
+			segid_skiplen;
+		params.bin_pwr_data_sec80   = (u_int8_t *)pfft_sec80;
+	}
+	qdf_mem_copy(
+		&params.classifier_params,
+		 &spectral->classifier_params,
+		 sizeof(struct spectral_classifier_params));
+
+#ifdef SPECTRAL_DEBUG_SAMP_MSG
+	target_if_dbg_print_SAMP_param(&params);
+#endif
+	target_if_spectral_create_samp_msg(spectral, &params);
+	}
+
+	return 0;
+}
+
+/*
+ * Function     : spectral_dump_header_gen2
+ * Description  : Dump Spectral header
+ * Input        : Pointer to Spectral Phyerr Header
+ * Output       : Success/Failure
+ *
+ */
+int spectral_dump_header_gen2(SPECTRAL_PHYERR_HDR_GEN2 *phdr)
+{
+	u_int32_t a = 0;
+	u_int32_t b = 0;
+
+	qdf_mem_copy(&a, (u_int8_t *)phdr, sizeof(int));
+	qdf_mem_copy(
+		&b,
+		(u_int8_t *)((u_int8_t *)phdr + sizeof(int)), sizeof(int));
+
+	qdf_print("SPECTRAL : HEADER A 0x%x (%d)\n", a, a);
+	qdf_print("SPECTRAL : HEADER B 0x%x (%d)\n", b, b);
+	return 0;
+}
+
+/*
+ * Function     : get_combined_rssi_sec80_segment_gen2
+ * Description  : Get approximate combined RSSI for Secondary 80 segment
+ * Input        : Pointer to spectral and  pointer to search fft info
+ *                of secondary 80 segment
+ * Output       : Combined RSSI for secondary 80Mhz segment
+ *
+ */
+int8_t get_combined_rssi_sec80_segment_gen2(
+	struct target_if_spectral *spectral,
+	 SPECTRAL_SEARCH_FFT_INFO_GEN2 *p_sfft_sec80)
+{
+	uint32_t avgpwr_db = 0;
+	uint32_t total_gain_db = 0;
+	uint32_t offset = 0;
+	int8_t comb_rssi = 0;
+
+	/* Obtain required parameters for algorithm from search FFT report */
+	avgpwr_db = p_sfft_sec80->avgpwr_db;
+	total_gain_db = p_sfft_sec80->total_gain_info;
+
+	/* Calculate offset */
+	offset = target_if_get_offset_swar_sec80(spectral->ch_width);
+
+	/* Calculate RSSI */
+	comb_rssi = ((avgpwr_db - total_gain_db) + offset);
+
+	return comb_rssi;
+}
+
+/*
+ * Function     : spectral_dump_tlv_gen2
+ * Description  : Dump Spectral TLV
+ * Input        : Pointer to Spectral Phyerr TLV, flag indicating whether
+ *                information provided by HW is in altered format for 802.11ac
+ *                160/80+80 MHz support (QCA9984 onwards).
+ * Output       : Success/Failure
+ *
+ */
+int spectral_dump_tlv_gen2(SPECTRAL_PHYERR_TLV_GEN2 *ptlv, bool is_160_format)
+{
+	int ret = 0;
+
+	/* TODO : Do not delete the following print
+	 *        The scripts used to validate Spectral depend on this Print
+	 */
+	qdf_print("SPECTRAL : TLV Length is 0x%x (%d)\n",
+		  ptlv->length, ptlv->length);
+
+	switch (ptlv->tag) {
+	case TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2:
+		ret = dump_summary_report_gen2(
+			ptlv, ptlv->length, is_160_format);
+		break;
+
+	case TLV_TAG_SEARCH_FFT_REPORT_GEN2:
+		ret = dump_search_fft_report_gen2(
+			ptlv, ptlv->length, is_160_format);
+		break;
+
+	case TLV_TAG_ADC_REPORT_GEN2:
+		ret = dump_adc_report_gen2(
+			ptlv, ptlv->length);
+		break;
+
+	default:
+		qdf_print("SPECTRAL : INVALID TLV\n");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Function     : spectral_dump_phyerr_data_gen2
+ * Description  : Dump Spectral related PHY Error TLVs
+ * Input        : Pointer to buffer, flag indicating whether information
+ *                provided by HW is in altered format for 802.11ac 160/80+80 MHz
+ *                support (QCA9984 onwards).
+ * Output       : Success/Failure
+ *
+ */
+int spectral_dump_phyerr_data_gen2(u_int8_t *data, u_int32_t datalen,
+				   bool is_160_format)
+{
+	SPECTRAL_PHYERR_TLV_GEN2 *ptlv = NULL;
+	u_int32_t bytes_processed = 0;
+	u_int32_t bytes_remaining = datalen;
+	u_int32_t curr_tlv_complete_size = 0;
+
+	if (datalen < sizeof(SPECTRAL_PHYERR_TLV_GEN2)) {
+	qdf_print("DRIVER: Total PHY error data length %u too short to contain"
+		  " any TLVs\n", datalen);
+	return -EPERM;
+	}
+
+	while (bytes_processed < datalen) {
+	if (bytes_remaining < sizeof(SPECTRAL_PHYERR_TLV_GEN2)) {
+		qdf_print("DRIVER: Remaining PHY error data length %u too "
+			  "short to contain a TLV\n", bytes_remaining);
+		return -EPERM;
+	}
+
+	ptlv = (SPECTRAL_PHYERR_TLV_GEN2 *)(data + bytes_processed);
+
+	if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) {
+		qdf_print("DRIVER : Invalid signature 0x%x!\n",
+			  ptlv->signature);
+		return -EPERM;
+	}
+
+	curr_tlv_complete_size = sizeof(SPECTRAL_PHYERR_TLV_GEN2) +
+		ptlv->length;
+
+	if (curr_tlv_complete_size > bytes_remaining) {
+		qdf_print("DRIVER : Current indicated complete TLV size %u "
+			  "greater than number of bytes remaining to be "
+			  "processed %u",
+			  curr_tlv_complete_size,
+			  bytes_remaining);
+		return -EPERM;
+	}
+
+	if (spectral_dump_tlv_gen2(ptlv, is_160_format) == -1)
+		return -EPERM;
+
+	bytes_processed += curr_tlv_complete_size;
+	bytes_remaining = datalen - bytes_processed;
+	}
+
+	return 0;
+}
+
+/* END of spectral GEN II HW specific functions */
+
+/* START of spectral GEN III HW specific functions */
+
+/*
+ * Function     : process_search_fft_report_gen3
+ * Description  : Process Search FFT Report
+ * Input        : Pointer to Spectral fft report and pointer to search fft info
+ * Output       : Success/Failure
+ *
+ */
+int process_search_fft_report_gen3(
+	struct spectral_phyerr_fft_report_gen3 *p_fft_report,
+	 struct spectral_search_fft_info_gen3 *p_sfft)
+{
+	/* For simplicity, everything is defined as uint32_t (except one).
+	 * Proper code will later use the right sizes.
+	 */
+	/* For easy comparision between MDK team and OS team, the MDK script
+	 * variable names have been used
+	 */
+	int32_t peak_sidx;
+	int32_t peak_mag;
+
+	/* Populate the Search FFT Info */
+	if (p_sfft) {
+		p_sfft->timestamp       = p_fft_report->fft_timestamp;
+
+		p_sfft->fft_detector_id = get_bitfield(
+			p_fft_report->hdr_a,
+			 2,
+			 0);
+		p_sfft->fft_num         = get_bitfield(
+			p_fft_report->hdr_a,
+			 3,
+			 2);
+		p_sfft->fft_radar_check = get_bitfield(
+			p_fft_report->hdr_a,
+			 12,
+			 5);
+
+		peak_sidx              = get_bitfield(
+			p_fft_report->hdr_a,
+			 11,
+			 17);
+		p_sfft->fft_peak_sidx  = unsigned_to_signed(peak_sidx, 11);
+		p_sfft->fft_chn_idx    = get_bitfield(
+			p_fft_report->hdr_a,
+			 3,
+			 28);
+
+		p_sfft->fft_base_pwr_db   = get_bitfield(
+			p_fft_report->hdr_b,
+			 9,
+			 0);
+		p_sfft->fft_total_gain_db = get_bitfield(
+			p_fft_report->hdr_b,
+			 8,
+			 9);
+
+		p_sfft->fft_num_str_bins_ib = get_bitfield(
+			p_fft_report->hdr_c,
+			 8,
+			 0);
+		peak_mag                    = get_bitfield(
+			p_fft_report->hdr_c,
+			 10,
+			 8);
+		p_sfft->fft_peak_mag        = unsigned_to_signed(peak_mag, 10);
+		p_sfft->fft_avgpwr_db       = get_bitfield(
+			p_fft_report->hdr_c,
+			 7,
+			 18);
+		p_sfft->fft_relpwr_db       = get_bitfield(
+			p_fft_report->hdr_c,
+			 7,
+			 25);
+	}
+
+	return 0;
+}
+
+/*
+ * Function     : spectral_dump_fft_report_gen3
+ * Description  : Process Search FFT Report
+ * Input        : Pointer to Spectral fft report and pointer to search fft info
+ * Output       : Success/Failure
+ *
+ */
+int spectral_dump_fft_report_gen3(
+	struct spectral_phyerr_fft_report_gen3 *p_fft_report,
+				  struct spectral_search_fft_info_gen3 *p_sfft)
+{
+	int i = 0;
+	int fft_mag = 0;
+	int fft_hdr_length = (p_fft_report->fft_hdr_length * 4);
+	int report_len     = (fft_hdr_length + 8);
+	int fft_bin_len    = (fft_hdr_length - 16);
+
+	qdf_print("##############################################"
+		  "###############\n");
+	qdf_print("Spectral search fft_report\n");
+	qdf_print("fft_timestamp  = 0x%x\n"
+			"fft_hdr_length = %d(32 bit words)\n"
+			"fft_hdr_tag    = 0x%x\n"
+			"fft_hdr_sig    = 0x%x\n",
+			p_fft_report->fft_timestamp,
+			p_fft_report->fft_hdr_length,
+			p_fft_report->fft_hdr_tag,
+			p_fft_report->fft_hdr_sig);
+
+	qdf_print("Length field in search fft report is %d(0x%x) bytes\n",
+		  fft_hdr_length, fft_hdr_length);
+	qdf_print("Total length of search fft report is %d(0x%x) bytes\n",
+		  report_len, report_len);
+	qdf_print("Number of fftbins in report is %d(0x%x)\n", fft_bin_len,
+		  fft_bin_len);
+
+	qdf_print("fft_detector_id     = %u\n"
+			"fft_num             = %u\n"
+			"fft_radar_check     = %u\n"
+			"fft_peak_sidx       = %d\n"
+			"fft_chn_idx         = %u\n"
+			"fft_base_pwr_db     = %u\n"
+			"fft_total_gain_db   = %u\n"
+			"fft_num_str_bins_ib = %u\n"
+			"fft_peak_mag        = %d\n"
+			"fft_avgpwr_db       = %u\n"
+			"fft_relpwr_db       = %u\n",
+			p_sfft->fft_detector_id,
+			p_sfft->fft_num,
+			p_sfft->fft_radar_check,
+			p_sfft->fft_peak_sidx,
+			p_sfft->fft_chn_idx,
+			p_sfft->fft_base_pwr_db,
+			p_sfft->fft_total_gain_db,
+			p_sfft->fft_num_str_bins_ib,
+			p_sfft->fft_peak_mag,
+			p_sfft->fft_avgpwr_db,
+			p_sfft->fft_relpwr_db);
+
+	qdf_print("FFT bins:\n");
+	for (i = 0; i < (fft_hdr_length - 16); i++) {
+	fft_mag = ((u_int8_t *)p_fft_report)[SPECTRAL_FFT_BINS_POS + i];
+	qdf_print("%d: %d, ", i, fft_mag);
+	if (i % 16 == 0)
+		qdf_print("\n");
+	}
+	qdf_print("\n");
+	qdf_print("###########################################################"
+		  "##\n");
+
+	return 0;
+}
+
+int consume_searchfft_report_gen3(
+	struct target_if_spectral *spectral,
+	 struct phyerr_info *pinfo)
+{
+	/*
+	 * XXX : The classifier do not use all the members of the SAMP
+	 *       message data format.
+	 *       The classifier only depends upon the following parameters
+	 *
+	 *          1. Frequency (freq, msg->freq)
+	 *          2. Spectral RSSI (spectral_rssi,
+	 *          msg->samp_data.spectral_rssi)
+	 *          3. Bin Power Count (bin_pwr_count,
+	 *          msg->samp_data.bin_pwr_count)
+	 *          4. Bin Power values (bin_pwr, msg->samp_data.bin_pwr[0]
+	 *          5. Spectral Timestamp (spectral_tstamp,
+	 *          msg->samp_data.spectral_tstamp)
+	 *          6. MAC Address (macaddr, msg->macaddr)
+	 *
+	 *       This function prepares the params structure and populates it
+	 *       with
+	 *       relevant values, this is in turn passed to
+	 *       spectral_create_samp_msg()
+	 *       to prepare fully formatted Spectral SAMP message
+	 *
+	 *       XXX : Need to verify
+	 *          1. Order of FFT bin values
+	 *
+	 */
+
+	/* Unpack the arguments */
+	u_int32_t datalen = pinfo->datalen;
+	struct target_if_spectral_rfqual_info *p_rfqual = pinfo->p_rfqual;
+	struct target_if_spectral_chan_info *p_chaninfo = pinfo->p_chaninfo;
+	u_int64_t tsf64 = pinfo->tsf64;
+	struct target_if_spectral_acs_stats *acs_stats = pinfo->acs_stats;
+
+	struct target_if_samp_msg_params params;
+	struct spectral_search_fft_info_gen3 search_fft_info;
+	struct spectral_search_fft_info_gen3 *p_sfft = &search_fft_info;
+	int8_t rssi_up = 0;
+	int8_t rssi_low = 0;
+	int8_t chn_idx_highest_enabled = 0;
+	int8_t chn_idx_lowest_enabled  = 0;
+	u_int8_t control_rssi   = 0;
+	u_int8_t extension_rssi = 0;
+	u_int32_t tstamp    = 0;
+	int fft_hdr_length = 0;
+	int report_len  = 0;
+	int fft_bin_len = 0;
+	struct target_if_spectral_ops *p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+	struct spectral_phyerr_fft_report_gen3 *p_fft_report =
+		(struct spectral_phyerr_fft_report_gen3 *)(pinfo->data);
+
+	OS_MEMZERO(&params, sizeof(params));
+
+	fft_hdr_length = p_fft_report->fft_hdr_length * 4;
+	if (fft_hdr_length < 16) {
+	qdf_print("SPECTRAL : Unexpected TLV length %u for FFT Report! Hexdump"
+		  " follows\n", fft_hdr_length);
+	goto fail;
+	}
+
+	report_len     = (fft_hdr_length + 8);
+	fft_bin_len    = (fft_hdr_length - 16);
+	if (datalen < report_len) {
+		qdf_print("DRIVER: Total PHY error data length %u too short to"
+			  " contain the search fft report of length %u\n",
+			  datalen, report_len);
+		goto fail;
+	}
+
+	process_search_fft_report_gen3(p_fft_report, p_sfft);
+
+	if (p_sfft->fft_detector_id != 0) {
+		qdf_print("Expected segid is 0 but we got %d\n",
+			  p_sfft->fft_detector_id);
+		spectral->diag_stats.spectral_vhtseg1id_mismatch++;
+		goto fail;
+	}
+
+	if (spectral_debug_level & (ATH_DEBUG_SPECTRAL2 | ATH_DEBUG_SPECTRAL4))
+		spectral_dump_fft_report_gen3(p_fft_report, p_sfft);
+
+	tstamp = p_sops->get_tsf64(spectral) & SPECTRAL_TSMASK;
+
+	if (spectral->upper_is_control)
+		rssi_up = control_rssi;
+	else
+		rssi_up = extension_rssi;
+
+	if (spectral->lower_is_control)
+		rssi_low = control_rssi;
+	else
+		rssi_low = extension_rssi;
+
+	params.rssi         = p_rfqual->rssi_comb;
+	params.lower_rssi   = rssi_low;
+	params.upper_rssi   = rssi_up;
+
+	if (spectral->sc_spectral_noise_pwr_cal) {
+	/* qdf_print("SPECTRAL : Needs to verified with FW\n"); */
+	params.chain_ctl_rssi[0] = p_rfqual->pc_rssi_info[0].rssi_pri20;
+	params.chain_ctl_rssi[1] = p_rfqual->pc_rssi_info[1].rssi_pri20;
+	params.chain_ctl_rssi[2] = p_rfqual->pc_rssi_info[2].rssi_pri20;
+	params.chain_ext_rssi[0] = p_rfqual->pc_rssi_info[0].rssi_sec20;
+	params.chain_ext_rssi[1] = p_rfqual->pc_rssi_info[1].rssi_sec20;
+	params.chain_ext_rssi[2] = p_rfqual->pc_rssi_info[2].rssi_sec20;
+	}
+
+	/*
+	 * XXX : This actually depends on the programmed chain mask
+	 *       There are three chains in Peregrine and 4 chains in Beeliner &
+	 *       Cascade
+	 *       This value decides the per-chain enable mask to select
+	 *       the input ADC for search FTT.
+	 *       For modes upto VHT80, if more than one chain is enabled, the
+	 *       max valid chain
+	 *       is used. LSB corresponds to chain zero.
+	 *       For VHT80_80 and VHT160, the lowest enabled chain is used for
+	 *       primary
+	 *       detection and highest enabled chain is used for secondary
+	 *       detection.
+	 *
+	 *  XXX: The current algorithm do not use these control and extension
+	 *       channel
+	 *       Instead, it just relies on the combined RSSI values only.
+	 *       For fool-proof detection algorithm, we should take these RSSI
+	 *       values
+	 *       in to account. This is marked for future enhancements.
+	 */
+	/* qdf_print("SPECTRAL : TBD (Chainmask changes for 8x8)\n"); */
+	chn_idx_highest_enabled = ((spectral->params.ss_chn_mask & 0x8) ? 3 :
+		(spectral->params.ss_chn_mask & 0x4) ? 2 :
+		(spectral->params.ss_chn_mask & 0x2) ? 1 : 0);
+	chn_idx_lowest_enabled  = ((spectral->params.ss_chn_mask & 0x1) ? 0 :
+		(spectral->params.ss_chn_mask & 0x2) ? 1 :
+		(spectral->params.ss_chn_mask & 0x4) ? 2 : 3);
+	control_rssi    = (u_int8_t)
+		p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_pri20;
+	extension_rssi  = (u_int8_t)
+		p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_sec20;
+
+	params.bwinfo   = 0;
+	params.tstamp   = 0;
+	params.max_mag  = p_sfft->fft_peak_mag;
+
+	/* params.max_index    = p_sfft->peak_inx; */
+	params.max_exp      = 0;
+	params.peak         = 0;
+	params.bin_pwr_data = (u_int8_t *)((uint8_t *)p_fft_report +
+		SPECTRAL_FFT_BINS_POS);
+	params.freq         = p_sops->get_current_channel(spectral);
+	params.freq_loading = 0;
+
+	params.interf_list.count = 0;
+	params.max_lower_index   = 0;
+	params.max_upper_index   = 0;
+	params.nb_lower          = 0;
+	params.nb_upper          = 0;
+	/*
+	 * For modes upto VHT80, the noise floor is populated with the one
+	 * corresponding
+	 * to the highest enabled antenna chain
+	 */
+	params.noise_floor       =
+		p_rfqual->noise_floor[chn_idx_highest_enabled];
+	params.datalen           = (fft_hdr_length * 4);
+	params.pwr_count         = fft_bin_len;
+	params.tstamp            = (tsf64 & SPECTRAL_TSMASK);
+
+	acs_stats->ctrl_nf             = params.noise_floor;
+	acs_stats->ext_nf              = params.noise_floor;
+	acs_stats->nfc_ctl_rssi        = control_rssi;
+	acs_stats->nfc_ext_rssi        = extension_rssi;
+
+	if (spectral->ch_width == IEEE80211_CWM_WIDTH160) {
+	/* We expect to see one more Search FFT report, and it should be
+	 * equal in size to the current one.
+	 */
+	if (datalen != (2 * report_len)) {
+		spectral->diag_stats.spectral_sec80_sfft_insufflen++;
+		goto fail;
+	}
+
+	p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)(
+			(uint8_t *)p_fft_report + report_len);
+
+	if (p_fft_report->fft_hdr_sig != SPECTRAL_PHYERR_SIGNATURE_GEN3) {
+		spectral->diag_stats.spectral_mismatch++;
+		goto fail;
+	}
+
+	if (p_fft_report->fft_hdr_tag != TLV_TAG_SEARCH_FFT_REPORT_GEN3) {
+		spectral->diag_stats.spectral_no_sec80_sfft++;
+		goto fail;
+	}
+
+	fft_hdr_length = p_fft_report->fft_hdr_length * 4;
+	report_len     = (fft_hdr_length + 8);
+	fft_bin_len    = (fft_hdr_length - 16);
+
+	process_search_fft_report_gen3(p_fft_report,  p_sfft);
+
+	if (p_sfft->fft_detector_id != 1) {
+		qdf_print("Expected segid is 1 but we got %d\n",
+			  p_sfft->fft_detector_id);
+		spectral->diag_stats.spectral_vhtseg2id_mismatch++;
+		goto fail;
+	}
+
+	if (spectral_debug_level & (ATH_DEBUG_SPECTRAL2 | ATH_DEBUG_SPECTRAL4))
+		spectral_dump_fft_report_gen3(p_fft_report, p_sfft);
+
+	params.vhtop_ch_freq_seg1  = p_chaninfo->center_freq1;
+	params.vhtop_ch_freq_seg2  = p_chaninfo->center_freq2;
+
+	/* XXX: Confirm. TBD at SoD. */
+	params.rssi_sec80           = p_rfqual->rssi_comb;
+
+	/* if (spectral->is_sec80_rssi_war_required) { */
+	/* params.rssi_sec80 = get_combined_rssi_sec80_segment_gen3(spectral,
+	 * &search_fft_info_sec80);
+	 */
+	/* } */
+	/* XXX: Determine dynamically. TBD at SoD. */
+
+	/*
+	 * For VHT80_80/VHT160, the noise floor for primary 80MHz segment is
+	 * populated with the
+	 * lowest enabled antenna chain and the noise floor for secondary 80MHz
+	 * segment is populated
+	 * with the highest enabled antenna chain
+	 */
+	params.noise_floor_sec80    =
+		p_rfqual->noise_floor[chn_idx_highest_enabled];
+	params.noise_floor          =
+		p_rfqual->noise_floor[chn_idx_lowest_enabled];
+
+	params.max_mag_sec80        = p_sfft->fft_peak_mag;
+	/* params.max_index_sec80      = p_sfft->peak_inx; */
+	/* XXX Does this definition of datalen *still hold? */
+	params.datalen_sec80        = fft_hdr_length;
+	params.pwr_count_sec80      = fft_bin_len;
+	params.bin_pwr_data_sec80   = (u_int8_t *)(
+		(uint8_t *)p_fft_report + SPECTRAL_FFT_BINS_POS);
+	}
+
+	qdf_mem_copy(
+		&params.classifier_params,
+		 &spectral->classifier_params,
+		 sizeof(struct spectral_classifier_params));
+#ifdef SPECTRAL_DEBUG_SAMP_MSG
+	target_if_dbg_print_SAMP_param(&params);
+#endif
+	target_if_spectral_create_samp_msg(spectral, &params);
+
+	return 0;
+
+fail:
+	qdf_print("Error in function %s while processing search fft report\n",
+		  __func__);
+	print_buf((uint8_t *)p_fft_report, fft_hdr_length + 8);
+	return -EPERM;
+}
+
+/*
+ * Function     : spectral_process_phyerr_gen3
+ * Descrip_tion  : Process PHY Error
+ * Input        : Pointer to buffer
+ * Output       : Success/Failure
+ *
+ */
+int spectral_process_phyerr_gen3(
+	struct target_if_spectral *spectral,
+	u_int8_t *data,
+	u_int32_t datalen, struct target_if_spectral_rfqual_info *p_rfqual,
+	struct target_if_spectral_chan_info *p_chaninfo,
+	u_int64_t tsf64,
+	struct target_if_spectral_acs_stats *acs_stats)
+{
+	uint8_t tag = 0;
+	uint8_t signature = 0;
+	struct phyerr_info pinfo;
+	int ret = 0;
+
+	/* pack arguments in a structure as there are
+	 * more than 3 arguments
+	 */
+	pinfo.data = data;
+	pinfo.datalen = datalen;
+	pinfo.p_rfqual = p_rfqual;
+	pinfo.p_chaninfo = p_chaninfo;
+	pinfo.tsf64 = tsf64;
+	pinfo.acs_stats = acs_stats;
+
+	if (spectral_debug_level &
+	    (ATH_DEBUG_SPECTRAL2 | ATH_DEBUG_SPECTRAL4)) {
+		qdf_print("Printing the spectral phyerr buffer for debug "
+			  "purpose\n");
+		qdf_print("Dalalength of buffer = 0x%x(%d)\n",
+			  datalen, datalen);
+		RAWSIM_PKT_HEXDUMP(data, datalen);
+	}
+
+	/* Peek into the data to figure out whether
+	 *      1) Signature matches the expected value
+	 *      2) What is inside the package (TAG ID is used for finding this)
+	 */
+	tag = *(data + PHYERR_HDR_TAG_POS);
+	signature = *(data + PHYERR_HDR_SIG_POS);
+
+	if (signature != SPECTRAL_PHYERR_SIGNATURE_GEN3) {
+		qdf_print("Unexpected signature %x in spectral phyerror "
+			  "event\n", signature);
+		spectral->diag_stats.spectral_mismatch++;
+		ret = -1;
+		goto end;
+	}
+
+	switch (tag) {
+	case TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3:
+		/* Place holder
+		 * We don't use spectral scan report as of now
+		 */
+		break;
+
+	case TLV_TAG_SEARCH_FFT_REPORT_GEN3:
+		ret = consume_searchfft_report_gen3(spectral, &pinfo);
+		break;
+
+	default:
+		qdf_print("Unknown tag %x in spectral phyerror event\n", tag);
+		break;
+	}
+
+end:
+	if (spectral_debug_level & ATH_DEBUG_SPECTRAL4)
+		spectral_debug_level = ATH_DEBUG_SPECTRAL;
+	return ret;
+}
+
+/* END of spectral GEN III HW specific functions */
+
+#endif  /* WLAN_SPECTRAL_ENABLE */
diff --git a/target_if/spectral/target_if_spectral_sim.c b/target_if/spectral/target_if_spectral_sim.c
new file mode 100644
index 0000000..e71e3b1
--- /dev/null
+++ b/target_if/spectral/target_if_spectral_sim.c
@@ -0,0 +1,958 @@
+/*
+ * Copyright (c) 2015,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if QCA_SUPPORT_SPECTRAL_SIMULATION
+#include "target_if_spectral.h"
+#include "target_if_spectral_sim.h"
+#include "target_if_spectral_sim_int.h"
+#include "_ieee80211.h"
+#include "ieee80211_api.h"
+#include "ieee80211_defines.h"
+#include "qdf_types.h"
+#include "ieee80211_var.h"
+#include <wlan_mlme_dispatcher.h>
+
+/* Helper functions */
+
+int tif_populate_reportset_fromfile(ath_spectralsim_reportset * reportset,
+				    enum phy_ch_width width,
+				bool is_80_80);
+static int populate_report_static_gen2(ath_spectralsim_report *report,
+				       enum phy_ch_width width,
+					bool is_80_80);
+static int populate_report_static_gen3(ath_spectralsim_report *report,
+				       enum phy_ch_width width,
+					bool is_80_80);
+static void depopulate_report(ath_spectralsim_report *report);
+
+static int populate_reportset_static(ath_spectralsim_context *simctx,
+				     ath_spectralsim_reportset *reportset,
+						enum phy_ch_width width,
+						bool is_80_80);
+static void depopulate_reportset(ath_spectralsim_reportset *reportset);
+
+static int populate_simdata(ath_spectralsim_context *simctx);
+static void depopulate_simdata(ath_spectralsim_context *simctx);
+static OS_TIMER_FUNC(spectral_sim_phyerrdelivery_handler);
+
+/* Static configuration.
+ * For now, we will be having a single configuration per BW, and a single
+ * report per configuration (since we need the data only for ensuring correct
+ * format handling).
+ *
+ * Extend this for more functionality if required in the future.
+ */
+
+/* Statically populate simulation data for one report. */
+static int populate_report_static_gen2(ath_spectralsim_report *report,
+				       enum phy_ch_width width,
+					bool is_80_80)
+{
+	qdf_assert_always(report);
+
+	switch (width) {
+	case CH_WIDTH_20MHZ:
+		report->data = NULL;
+		report->data = (u_int8_t *)
+		qdf_mem_malloc(sizeof(reportdata_20_gen2));
+
+		if (!report->data) {
+		qdf_print("Spectral simulation: Could not allocate memory for "
+				"report data\n");
+		goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_20_gen2);
+		qdf_mem_copy(report->data,
+			     reportdata_20_gen2, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_20, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_20, sizeof(report->chan_info));
+
+		break;
+	case CH_WIDTH_40MHZ:
+		report->data = NULL;
+		report->data = (u_int8_t *)
+		qdf_mem_malloc(sizeof(reportdata_40_gen2));
+
+		if (!report->data) {
+		qdf_print("Spectral simulation: Could not allocate memory for "
+				"report data\n");
+		goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_40_gen2);
+		qdf_mem_copy(report->data,
+			     reportdata_40_gen2, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_40, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_40, sizeof(report->chan_info));
+
+		break;
+	case CH_WIDTH_80MHZ:
+		report->data = NULL;
+		report->data = (u_int8_t *)
+		qdf_mem_malloc(sizeof(reportdata_80_gen2));
+
+		if (!report->data) {
+		qdf_print("Spectral simulation: Could not allocate memory for "
+				"report data\n");
+		goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_80_gen2);
+		qdf_mem_copy(report->data,
+			     reportdata_80_gen2, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_80, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_80, sizeof(report->chan_info));
+
+		break;
+	case CH_WIDTH_160MHZ:
+		if (is_80_80) {
+		report->data = NULL;
+		report->data = (u_int8_t *)
+			qdf_mem_malloc(sizeof(reportdata_80_80_gen2));
+
+		if (!report->data) {
+			qdf_print("Spectral simulation: Could not allocate "
+				  "memory for report data\n");
+			goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_80_80_gen2);
+		qdf_mem_copy(report->data,
+			     reportdata_80_80_gen2, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_80_80, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_80_80, sizeof(report->chan_info));
+
+		} else {
+		report->data = NULL;
+		report->data = (u_int8_t *)
+			qdf_mem_malloc(sizeof(reportdata_160_gen2));
+
+		if (!report->data) {
+			qdf_print("Spectral simulation: Could not allocate "
+				  "memory for report data\n");
+			goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_160_gen2);
+		qdf_mem_copy(report->data,
+			     reportdata_160_gen2, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_160, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_160, sizeof(report->chan_info));
+		}
+		break;
+	default:
+		qdf_print("Unhandled width. Please correct. Asserting\n");
+		qdf_assert_always(0);
+	}
+
+	return 0;
+
+bad:
+	return -EPERM;
+}
+
+/* Statically populate simulation data for one report. */
+static int populate_report_static_gen3(ath_spectralsim_report *report,
+				       enum phy_ch_width width,
+					bool is_80_80)
+{
+	qdf_assert_always(report);
+
+	switch (width) {
+	case CH_WIDTH_20MHZ:
+		report->data = NULL;
+		report->data = (u_int8_t *)
+		qdf_mem_malloc(sizeof(reportdata_20_gen3));
+
+		if (!report->data) {
+			qdf_print("Spectral simulation: Could not allocate "
+				  "memory for report data\n");
+		goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_20_gen3);
+		qdf_mem_copy(report->data,
+			     reportdata_20_gen3, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_20, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_20, sizeof(report->chan_info));
+
+		break;
+	case CH_WIDTH_40MHZ:
+		report->data = NULL;
+		report->data = (u_int8_t *)
+		qdf_mem_malloc(sizeof(reportdata_40_gen3));
+
+		if (!report->data) {
+			qdf_print("Spectral simulation: Could not allocate "
+				  "memory for report data\n");
+		goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_40_gen3);
+		qdf_mem_copy(report->data,
+			     reportdata_40_gen3, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_40, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_40, sizeof(report->chan_info));
+
+		break;
+	case CH_WIDTH_80MHZ:
+		report->data = NULL;
+		report->data = (u_int8_t *)
+		qdf_mem_malloc(sizeof(reportdata_80_gen3));
+
+		if (!report->data) {
+		qdf_print("Spectral simulation: Could not allocate memory for "
+				"report data\n");
+		goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_80_gen3);
+		qdf_mem_copy(report->data,
+			     reportdata_80_gen3, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_80, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_80, sizeof(report->chan_info));
+
+		break;
+	case CH_WIDTH_160MHZ:
+		if (is_80_80) {
+		report->data = NULL;
+		report->data = (u_int8_t *)
+			qdf_mem_malloc(sizeof(reportdata_80_80_gen3));
+
+		if (!report->data) {
+			qdf_print("Spectral simulation: Could not allocate "
+				  "memory for report data\n");
+			goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_80_80_gen3);
+		qdf_mem_copy(report->data,
+			     reportdata_80_80_gen3, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_80_80, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_80_80, sizeof(report->chan_info));
+
+		} else {
+		report->data = NULL;
+		report->data = (u_int8_t *)
+			qdf_mem_malloc(sizeof(reportdata_160_gen3));
+
+		if (!report->data) {
+			qdf_print("Spectral simulation: Could not allocate "
+				  "memory for report data\n");
+			goto bad;
+		}
+
+		report->datasize = sizeof(reportdata_160_gen3);
+		qdf_mem_copy(report->data,
+			     reportdata_160_gen3, report->datasize);
+
+		qdf_mem_copy(&report->rfqual_info,
+			     &rfqual_info_160, sizeof(report->rfqual_info));
+
+		qdf_mem_copy(&report->chan_info,
+			     &chan_info_160, sizeof(report->chan_info));
+		}
+		break;
+	default:
+		qdf_print("Unhandled width. Please correct. Asserting\n");
+		qdf_assert_always(0);
+	}
+
+	return 0;
+
+bad:
+	return -EPERM;
+}
+
+static void depopulate_report(ath_spectralsim_report *report)
+{
+	if (!report)
+	return;
+
+	if (report->data) {
+	qdf_mem_free(report->data);
+	report->data = NULL;
+	report->datasize = 0;
+	}
+}
+
+/* Statically populate simulation data for a given configuration. */
+static int populate_reportset_static(ath_spectralsim_context *simctx,
+				     ath_spectralsim_reportset *reportset,
+						enum phy_ch_width width,
+						bool is_80_80)
+{
+	int ret = 0;
+	ath_spectralsim_report *report = NULL;
+
+	qdf_assert_always(reportset);
+
+	reportset->headreport = NULL;
+	reportset->curr_report = NULL;
+
+	/* For now, we populate only one report */
+	report = (ath_spectralsim_report *)
+	qdf_mem_malloc(sizeof(ath_spectralsim_report));
+
+	if (!report) {
+		qdf_print("Spectral simulation: Could not allocate memory "
+			  "for report.\n");
+		goto bad;
+	}
+
+	qdf_mem_zero(report, sizeof(*report));
+
+	switch (width) {
+	case CH_WIDTH_20MHZ:
+		qdf_mem_copy(&reportset->config,
+			     &config_20_1, sizeof(reportset->config));
+
+		ret = simctx->populate_report_static(report, CH_WIDTH_20MHZ, 0);
+		if (ret != 0)
+		goto bad;
+
+		report->next = NULL;
+		reportset->headreport = report;
+		break;
+	case CH_WIDTH_40MHZ:
+		qdf_mem_copy(&reportset->config,
+			     &config_40_1, sizeof(reportset->config));
+
+		ret = simctx->populate_report_static(report, CH_WIDTH_40MHZ, 0);
+		if (ret != 0)
+		goto bad;
+
+		report->next = NULL;
+		reportset->headreport = report;
+		break;
+	case CH_WIDTH_80MHZ:
+		qdf_mem_copy(&reportset->config,
+			     &config_80_1, sizeof(reportset->config));
+
+		ret = simctx->populate_report_static(report, CH_WIDTH_80MHZ, 0);
+		if (ret != 0)
+		goto bad;
+
+		report->next = NULL;
+		reportset->headreport = report;
+		break;
+	case CH_WIDTH_160MHZ:
+		if (is_80_80) {
+		qdf_mem_copy(&reportset->config,
+			     &config_80_80_1, sizeof(reportset->config));
+
+		ret = simctx->populate_report_static(
+			report,
+			 CH_WIDTH_160MHZ,
+			 1);
+		if (ret != 0)
+			goto bad;
+
+		report->next = NULL;
+		reportset->headreport = report;
+		} else {
+		qdf_mem_copy(&reportset->config,
+			     &config_160_1, sizeof(reportset->config));
+
+		ret = simctx->populate_report_static(
+			report,
+			 CH_WIDTH_160MHZ,
+			 0);
+		if (ret != 0)
+			goto bad;
+
+		report->next = NULL;
+		reportset->headreport = report;
+		}
+		break;
+	default:
+		qdf_print("Unhandled width. Please rectify.\n");
+		qdf_assert_always(0);
+	};
+
+	reportset->curr_report = reportset->headreport;
+
+	return 0;
+
+bad:
+	depopulate_reportset(reportset);
+	return -EPERM;
+}
+
+static void depopulate_reportset(ath_spectralsim_reportset *reportset)
+{
+	ath_spectralsim_report *curr_report = NULL;
+	ath_spectralsim_report *next_report = NULL;
+
+	if (!reportset)
+	return;
+
+	curr_report = reportset->headreport;
+
+	while (curr_report) {
+	next_report = curr_report->next;
+	depopulate_report(curr_report);
+	qdf_mem_free(curr_report);
+	curr_report = next_report;
+	}
+}
+
+/* Populate simulation data for a given bandwidth by loading from a file.
+ * This is a place-holder only. To be implemented in the future on a need
+ * basis.
+ *
+ * A different file per bandwidth is suggested for better segregation of data
+ * sets (since data is likely to be very different across BWs).
+ */
+int tif_populate_reportset_fromfile(ath_spectralsim_reportset *reportset,
+				    enum phy_ch_width width,
+					bool is_80_80)
+{
+	qdf_print("%s: To be implemented if required\n", __func__);
+
+	return 0;
+}
+
+/* Populate simulation data */
+static int populate_simdata(ath_spectralsim_context *simctx)
+{
+	/* For now, we use static population. Switch to loading from a file if
+	 * needed in the future.
+	 */
+
+	simctx->bw20_headreportset = NULL;
+	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
+						simctx->bw20_headreportset,
+		CH_WIDTH_20MHZ,
+		0);
+
+	simctx->bw40_headreportset = NULL;
+	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
+						simctx->bw40_headreportset,
+		CH_WIDTH_40MHZ,
+		0);
+
+	simctx->bw80_headreportset = NULL;
+	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
+						simctx->bw80_headreportset,
+		CH_WIDTH_80MHZ,
+		0);
+
+	simctx->bw160_headreportset = NULL;
+	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
+						simctx->bw160_headreportset,
+		CH_WIDTH_160MHZ,
+		0);
+
+	simctx->bw80_80_headreportset = NULL;
+	SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
+						simctx->bw80_80_headreportset,
+		CH_WIDTH_160MHZ,
+		1);
+
+	simctx->curr_reportset = NULL;
+
+	simctx->is_enabled = false;
+	simctx->is_active = false;
+
+	simctx->ssim_starting_tsf64 = 0;
+	simctx->ssim_count = 0;
+	simctx->ssim_period_ms = 0;
+
+	return 0;
+}
+
+static void depopulate_simdata(ath_spectralsim_context *simctx)
+{
+	if (!simctx)
+		return;
+
+	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw20_headreportset);
+	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw40_headreportset);
+	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_headreportset);
+	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw160_headreportset);
+	SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_80_headreportset);
+}
+
+static
+OS_TIMER_FUNC(spectral_sim_phyerrdelivery_handler)
+{
+	struct target_if_spectral *spectral = NULL;
+	ath_spectralsim_context *simctx = NULL;
+	ath_spectralsim_reportset *curr_reportset = NULL;
+	ath_spectralsim_report *curr_report = NULL;
+	struct target_if_spectral_acs_stats acs_stats;
+	u_int64_t curr_tsf64 = 0;
+	struct target_if_spectral_ops *p_sops;
+
+	OS_GET_TIMER_ARG(spectral, struct target_if_spectral *);
+	qdf_assert_always(spectral);
+
+	p_sops = GET_TIF_SPECTRAL_OPS(spectral);
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)spectral->simctx;
+	qdf_assert_always(simctx);
+
+	if (!simctx->is_active)
+		return;
+
+	curr_reportset = simctx->curr_reportset;
+	qdf_assert_always(curr_reportset);
+
+	curr_report = curr_reportset->curr_report;
+	qdf_assert_always(curr_report);
+
+	qdf_assert_always(curr_reportset->headreport);
+
+	/* We use a simulation TSF since in offload architectures we can't
+	 * expect to
+	 * get an accurate current TSF from HW.
+	 * In case of TSF wrap over, we'll use it as-is for now since the
+	 * simulation
+	 * is intended only for format verification.
+	 */
+	curr_tsf64 = simctx->ssim_starting_tsf64 +
+	((simctx->ssim_period_ms * simctx->ssim_count) * 1000);
+
+	p_sops->spectral_process_phyerr(spectral,
+		curr_report->data,
+		curr_report->datasize,
+		&curr_report->rfqual_info,
+		&curr_report->chan_info,
+		curr_tsf64,
+		&acs_stats);
+
+	simctx->ssim_count++;
+
+	if (curr_report->next)
+		curr_reportset->curr_report = curr_report->next;
+	else
+		curr_reportset->curr_report = curr_reportset->headreport;
+
+	if (curr_reportset->config.ss_count != 0 &&
+	    simctx->ssim_count == curr_reportset->config.ss_count) {
+	tif_spectral_sim_stop_spectral_scan(spectral);
+	} else {
+	qdf_timer_start(&simctx->ssim_pherrdelivery_timer,
+			simctx->ssim_period_ms);
+	}
+}
+
+/* Module services */
+
+int target_if_spectral_sim_attach(struct target_if_spectral *spectral)
+{
+	ath_spectralsim_context *simctx = NULL;
+
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)
+		qdf_mem_malloc(sizeof(ath_spectralsim_context));
+
+	if (!simctx) {
+		qdf_print("Spectral simulation: Could not allocate memory for "
+			  "context\n");
+		return -EPERM;
+	}
+
+	qdf_mem_zero(simctx, sizeof(*simctx));
+
+	spectral->simctx = simctx;
+
+	if (spectral->spectral_gen == SPECTRAL_GEN2)
+		simctx->populate_report_static = populate_report_static_gen2;
+	else if (spectral->spectral_gen == SPECTRAL_GEN3)
+		simctx->populate_report_static = populate_report_static_gen3;
+
+	if (populate_simdata(simctx) != 0) {
+	qdf_mem_free(simctx);
+	spectral->simctx = NULL;
+	qdf_print("Spectral simulation attach failed\n");
+	return -EPERM;
+	}
+
+	qdf_timer_init(NULL,
+		       &simctx->ssim_pherrdelivery_timer,
+		spectral_sim_phyerrdelivery_handler,
+		(void *)(spectral),
+		QDF_TIMER_TYPE_WAKE_APPS);
+
+	qdf_print("Spectral simulation attached\n");
+
+	return 0;
+}
+
+void target_if_spectral_sim_detach(struct target_if_spectral *spectral)
+{
+	ath_spectralsim_context *simctx = NULL;
+
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)spectral->simctx;
+	qdf_assert_always(simctx);
+
+	qdf_timer_free(&simctx->ssim_pherrdelivery_timer);
+
+	depopulate_simdata(simctx);
+	qdf_mem_free(simctx);
+	spectral->simctx = NULL;
+
+	qdf_print("Spectral simulation detached\n");
+}
+
+u_int32_t tif_spectral_sim_is_spectral_active(void *arg)
+{
+	struct target_if_spectral *spectral = NULL;
+	ath_spectralsim_context *simctx = NULL;
+
+	spectral = (struct target_if_spectral *)arg;
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)spectral->simctx;
+	qdf_assert_always(simctx);
+
+	return simctx->is_active;
+}
+EXPORT_SYMBOL(tif_spectral_sim_is_spectral_active);
+
+u_int32_t tif_spectral_sim_is_spectral_enabled(void *arg)
+{
+	struct target_if_spectral *spectral = NULL;
+	ath_spectralsim_context *simctx = NULL;
+
+	spectral = (struct target_if_spectral *)arg;
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)spectral->simctx;
+	qdf_assert_always(simctx);
+
+	return simctx->is_enabled;
+}
+EXPORT_SYMBOL(tif_spectral_sim_is_spectral_enabled);
+
+u_int32_t tif_spectral_sim_start_spectral_scan(void *arg)
+{
+	struct target_if_spectral *spectral = NULL;
+	ath_spectralsim_context *simctx = NULL;
+
+	spectral = (struct target_if_spectral *)arg;
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)spectral->simctx;
+	qdf_assert_always(simctx);
+
+	if (!simctx->curr_reportset) {
+		qdf_print("Spectral simulation: No current report set "
+			  "configured  - unable to start simulated Spectral "
+			  "scan\n");
+		return 0;
+	}
+
+	if (!simctx->curr_reportset->curr_report) {
+		qdf_print("Spectral simulation: No report data instances "
+			  "populated - unable to start simulated Spectral "
+			  "scan\n");
+	return 0;
+	}
+
+	if (!simctx->is_enabled)
+		simctx->is_enabled = true;
+
+	simctx->is_active = true;
+
+	/* Hardcoding current time as zero since it is simulation */
+	simctx->ssim_starting_tsf64 = 0;
+	simctx->ssim_count = 0;
+
+	/* TODO: Support high resolution timer in microseconds if required, so
+	 * that
+	 * we can support default periods such as ~200 us.  For now, we use 1
+	 * millisecond since the current use case for the simulation is to
+	 * validate
+	 * formats rather than have a time dependent classification.
+	 */
+	simctx->ssim_period_ms = 1;
+
+	qdf_timer_start(&simctx->ssim_pherrdelivery_timer,
+			simctx->ssim_period_ms);
+
+	return 1;
+}
+EXPORT_SYMBOL(tif_spectral_sim_start_spectral_scan);
+
+u_int32_t tif_spectral_sim_stop_spectral_scan(void *arg)
+{
+	struct target_if_spectral *spectral = NULL;
+	ath_spectralsim_context *simctx = NULL;
+
+	spectral = (struct target_if_spectral *)arg;
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)spectral->simctx;
+	qdf_assert_always(simctx);
+
+	qdf_timer_stop(&simctx->ssim_pherrdelivery_timer);
+
+	simctx->is_active = false;
+	simctx->is_enabled = false;
+
+	simctx->ssim_starting_tsf64 = 0;
+	simctx->ssim_count = 0;
+	simctx->ssim_period_ms = 0;
+
+	return 1;
+}
+EXPORT_SYMBOL(tif_spectral_sim_stop_spectral_scan);
+
+u_int32_t tif_spectral_sim_configure_params(
+	void *arg,
+	 struct spectral_config *params)
+{
+	struct target_if_spectral *spectral = NULL;
+	ath_spectralsim_context *simctx = NULL;
+	enum wlan_phymode phymode;
+	u_int8_t bw;
+	ath_spectralsim_reportset *des_headreportset = NULL;
+	ath_spectralsim_reportset *temp_reportset = NULL;
+	bool is_invalid_width = false;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	qdf_assert_always(params);
+
+#ifdef SPECTRAL_SIM_DUMP_PARAM_DATA
+	{
+	int i = 0;
+
+	qdf_print("\n");
+
+	qdf_print("Spectral simulation: Param data dump:\n"
+			"ss_fft_period=%hu\n"
+			"ss_period=%hu\n"
+			"ss_count=%hu\n"
+			"ss_short_report=%hu\n"
+			"radar_bin_thresh_sel=%hhu\n"
+			"ss_spectral_pri=%hu\n"
+			"ss_fft_size=%hu\n"
+			"ss_gc_ena=%hu\n"
+			"ss_restart_ena=%hu\n"
+			"ss_noise_floor_ref=%hu\n"
+			"ss_init_delay=%hu\n"
+			"ss_nb_tone_thr=%hu\n"
+			"ss_str_bin_thr=%hu\n"
+			"ss_wb_rpt_mode=%hu\n"
+			"ss_rssi_rpt_mode=%hu\n"
+			"ss_rssi_thr=%hu\n"
+			"ss_pwr_format=%hu\n"
+			"ss_rpt_mode=%hu\n"
+			"ss_bin_scale=%hu\n"
+			"ss_dBm_adj=%hu\n"
+			"ss_chn_mask=%hu\n"
+			"ss_nf_temp_data=%d\n",
+			params->ss_fft_period,
+			params->ss_period,
+			params->ss_count,
+			params->ss_short_report,
+			params->radar_bin_thresh_sel,
+			params->ss_spectral_pri,
+			params->ss_fft_size,
+			params->ss_gc_ena,
+			params->ss_restart_ena,
+			params->ss_noise_floor_ref,
+			params->ss_init_delay,
+			params->ss_nb_tone_thr,
+			params->ss_str_bin_thr,
+			params->ss_wb_rpt_mode,
+			params->ss_rssi_rpt_mode,
+			params->ss_rssi_thr,
+			params->ss_pwr_format,
+			params->ss_rpt_mode,
+			params->ss_bin_scale,
+			params->ss_dBm_adj,
+			params->ss_chn_mask,
+			params->ss_nf_temp_data);
+
+	for (i = 0; i < AH_MAX_CHAINS * 2; i++)
+		qdf_print("ss_nf_cal[%d]=%hhd\n", i, params->ss_nf_cal[i]);
+
+	for (i = 0; i < AH_MAX_CHAINS * 2; i++)
+		qdf_print("ss_nf_pwr[%d]=%hhd\n", i, params->ss_nf_pwr[i]);
+
+	qdf_print("\n");
+	}
+#endif /* SPECTRAL_SIM_DUMP_PARAM_DATA */
+
+	spectral = (struct target_if_spectral *)arg;
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)spectral->simctx;
+	qdf_assert_always(simctx);
+
+	vdev = target_if_spectral_get_vdev(spectral);
+	if (!vdev) {
+		qdf_print("Spectral simulation: No VAPs found - not proceeding"
+			  " with param config.\n");
+		return 0;
+	}
+
+	bw = wlan_vdev_get_ch_width(vdev);
+
+	switch (bw) {
+	case CH_WIDTH_20MHZ:
+		des_headreportset = simctx->bw20_headreportset;
+		break;
+	case CH_WIDTH_40MHZ:
+		des_headreportset = simctx->bw40_headreportset;
+		break;
+	case CH_WIDTH_80MHZ:
+		des_headreportset = simctx->bw80_headreportset;
+		break;
+	case CH_WIDTH_160MHZ:
+		phymode = wlan_vdev_get_phymode(vdev);
+		if (phymode == WLAN_PHYMODE_11AC_VHT160) {
+			des_headreportset = simctx->bw160_headreportset;
+		} else if (phymode == WLAN_PHYMODE_11AC_VHT80_80) {
+			des_headreportset = simctx->bw80_80_headreportset;
+		} else {
+			qdf_print("Spectral simulation: Unexpected PHY mode %u"
+				  " found for width 160 MHz...asserting.\n",
+				  phymode);
+			qdf_assert_always(0);
+		}
+		break;
+
+	case IEEE80211_CWM_WIDTHINVALID:
+		qdf_print("Spectral simulation: Invalid width configured - not"
+			  " proceeding with param config.\n");
+		is_invalid_width = true;
+	default:
+		qdf_print("Spectral simulation: Unknown width %u...asserting\n"
+			  , bw);
+		qdf_assert_always(0);
+		break;
+	}
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
+
+	if (is_invalid_width)
+		return 0;
+
+	if (!des_headreportset) {
+		qdf_print("Spectral simulation: No simulation data present for"
+			  " configured bandwidth/PHY mode - unable to proceed "
+			  " with param config.\n");
+	return 0;
+	}
+
+	simctx->curr_reportset = NULL;
+	temp_reportset = des_headreportset;
+
+	while (temp_reportset) {
+	if (qdf_mem_cmp(&temp_reportset->config,
+			params, sizeof(struct spectral_config)) == 0) {
+		/* Found a matching config. We are done. */
+		simctx->curr_reportset = temp_reportset;
+		break;
+	}
+
+	temp_reportset = temp_reportset->next;
+	}
+
+	if (!simctx->curr_reportset) {
+		qdf_print("Spectral simulation: No simulation data present for"
+			  " desired Spectral configuration - unable to proceed"
+			  " with param config.\n");
+	return 0;
+	}
+
+	if (!simctx->curr_reportset->curr_report) {
+		qdf_print("Spectral simulation: No report data instances "
+			  "populated for desired Spectral configuration - "
+			  "unable to proceed with param config\n");
+		return 0;
+	}
+
+	return 1;
+}
+EXPORT_SYMBOL(tif_spectral_sim_configure_params);
+
+u_int32_t tif_spectral_sim_get_params(
+	void *arg,
+	struct spectral_config *params)
+{
+	struct target_if_spectral *spectral = NULL;
+	ath_spectralsim_context *simctx = NULL;
+
+	qdf_assert_always(params);
+
+	spectral = (struct target_if_spectral *)arg;
+	qdf_assert_always(spectral);
+
+	simctx = (ath_spectralsim_context *)spectral->simctx;
+	qdf_assert_always(simctx);
+
+	if (!simctx->curr_reportset) {
+	qdf_print("Spectral simulation: No configured reportset found.\n");
+	return 0;
+	}
+
+	qdf_mem_copy(params, &simctx->curr_reportset->config, sizeof(*params));
+
+	return 1;
+}
+EXPORT_SYMBOL(tif_spectral_sim_get_params);
+
+#endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */
diff --git a/target_if/spectral/target_if_spectral_sim.h b/target_if/spectral/target_if_spectral_sim.h
new file mode 100644
index 0000000..d0e9411
--- /dev/null
+++ b/target_if/spectral/target_if_spectral_sim.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SPECTRAL_SIM_H_
+#define _SPECTRAL_SIM_H_
+
+#if QCA_SUPPORT_SPECTRAL_SIMULATION
+#include "target_if_spectral.h"
+
+/**
+ * @brief Initialize Spectral Simulation functionality
+ * @details
+ *  Setup data structures to be used for serving out data corresponding to
+ *  various bandwidths and configurations.
+ *
+ * @param spectral - ath_spectral structure
+ * @return Integer status value. 0:Success, -1:Failure
+ */
+int target_if_spectral_sim_attach(struct target_if_spectral *spectral);
+
+/**
+ * @brief De-initialize Spectral Simulation functionality
+ * @details
+ *  Free up data structures used for serving out data corresponding to various
+ *  bandwidths and configurations.
+ *
+ * @param spectral - ath_spectral structure
+ */
+void target_if_spectral_sim_detach(struct target_if_spectral *spectral);
+
+/**
+ * @brief Check if Spectral (simulated) is active
+ *
+ * @param arg - pointer to ath_spectral structure
+ * @return Integer status value. 0: Not active, 1: Active
+ */
+u_int32_t tif_spectral_sim_is_spectral_active(void *arg);
+
+/**
+ * @brief Check if Spectral (simulated) is enabled
+ *
+ * @param arg - pointer to ath_spectral structure
+ * @return Integer status value. 0: Not enabled, 1: Enabled
+ */
+u_int32_t tif_spectral_sim_is_spectral_enabled(void *arg);
+
+/**
+ * @brief Start Spectral simulation
+ *
+ * @param arg - pointer to ath_spectral structure
+ * @return Integer status value. 0: Failure, 1: Success
+ */
+u_int32_t tif_spectral_sim_start_spectral_scan(void *arg);
+
+/**
+ * @brief Stop Spectral simulation
+ *
+ * @param arg - pointer to ath_spectral structure
+ * @return Integer status value. 0: Failure, 1: Success
+ */
+u_int32_t tif_spectral_sim_stop_spectral_scan(void *arg);
+
+/**
+ * @brief Configure Spectral parameters into simulation
+ * @details
+ *  Internally, this function actually searches if a record set with the desired
+ *  configuration has been loaded. If so, it points to the record set for
+ *  later usage when the simulation is started. If not, it returns an error.
+ *
+ * @param arg - pointer to ath_spectral structure
+ * @param params - pointer to struct spectral_config structure bearing Spectral
+ *                 configuration
+ * @return Integer status value. 0: Failure, 1: Success
+ */
+u_int32_t tif_spectral_sim_configure_params(
+	void *arg,
+	 struct spectral_config *params);
+
+/**
+ * @brief Get Spectral parameters configured into simulation
+ *
+ * @param arg - pointer to ath_spectral structure
+ * @param params - pointer to struct spectral_config structure which should be
+ *                 populated with Spectral configuration
+ * @return Integer status value. 0: Failure, 1: Success
+ */
+u_int32_t tif_spectral_sim_get_params(
+	void *arg,
+	 struct spectral_config *params);
+
+#endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */
+#endif /* _SPECTRAL_SIM_H_ */
diff --git a/target_if/spectral/target_if_spectral_sim_int.h b/target_if/spectral/target_if_spectral_sim_int.h
new file mode 100644
index 0000000..c0b5332
--- /dev/null
+++ b/target_if/spectral/target_if_spectral_sim_int.h
@@ -0,0 +1,961 @@
+/*
+ * Copyright (c) 2015,2017 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SPECTRAL_SIM_INTERNAL_H_
+#define _SPECTRAL_SIM_INTERNAL_H_
+
+#if QCA_SUPPORT_SPECTRAL_SIMULATION
+#include "target_if_spectral.h"
+
+/* #define SPECTRAL_SIM_DUMP_PARAM_DATA 1 */
+/* Spectral report data instance. Usable in a linked list.
+ * - In the case of Direct Attach chipsets, one instance should correspond to
+ *   one PHY Data Error frame received from the HW.
+ *   XXX Direct Attach support to be implemented if needed. Any modifications
+ *   required here can be made at the time of implementation.
+ * - In the case of 802.11ac offload chipsets, one instance should correspond to
+ *   one report received from HW, inclusive of all TLVs.
+ */
+typedef struct _ath_spectralsim_report {
+	/* 11ac onwards only */
+	struct target_if_spectral_rfqual_info rfqual_info;
+	/* 11ac onwards only */
+	struct target_if_spectral_chan_info chan_info;
+	u_int32_t datasize;
+	u_int8_t *data;
+	struct _ath_spectralsim_report *next;
+} ath_spectralsim_report;
+
+/* Set of Spectral report data instances corresponding to one particular
+ * configuration. Usable in a linked list.
+ */
+typedef struct _ath_spectralsim_reportset {
+	struct spectral_config config;
+	ath_spectralsim_report *headreport;
+	ath_spectralsim_report *curr_report;
+	struct _ath_spectralsim_reportset *next;
+} ath_spectralsim_reportset;
+
+/* Main structure for Spectral simulation. All data and controls get linked
+ * here.
+ *
+ * For each width (20/40/80/160/80+80), we will have a linked list of
+ * ath_spectralsim_reportset nodes. Each ath_spectralsim_reportset will have a
+ * linked list of ath_spectralsim_report nodes. When the user requests for a
+ * given PHY mode and Spectral configuration, we find the appropriate
+ * ath_spectralsim_reportset, and then serve ath_spectralsim_report instances
+ * from the linked list. If required report count is higher than size of linked
+ * list (or infinite), we repeatedly cycle through the linked list.  There can
+ * be more elaborate data structures devised taking care of a large number of
+ * possibilities, but we stick to a simple scheme given limited simulation
+ * needs.
+ */
+typedef struct _ath_spectralsim_context {
+	ath_spectralsim_reportset *bw20_headreportset;
+	ath_spectralsim_reportset *bw40_headreportset;
+	ath_spectralsim_reportset *bw80_headreportset;
+	ath_spectralsim_reportset *bw160_headreportset;
+	ath_spectralsim_reportset *bw80_80_headreportset;
+
+	ath_spectralsim_reportset *curr_reportset;
+	bool    is_enabled;
+	bool    is_active;
+
+	qdf_timer_t ssim_pherrdelivery_timer;
+	u_int64_t ssim_starting_tsf64;
+	u_int32_t ssim_period_ms; /* TODO: Support in microseconds */
+	u_int32_t ssim_count;
+	int (*populate_report_static)(ath_spectralsim_report *report,
+				      enum phy_ch_width width,
+						bool is_80_80);
+} ath_spectralsim_context;
+
+/* Helper Macros */
+
+/* Allocate and populate reportset for a single configuration */
+#define SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx, reportset, width, \
+						is_80_80)                 \
+	{                                                                 \
+	(reportset) = (ath_spectralsim_reportset *)                       \
+		qdf_mem_malloc(sizeof(ath_spectralsim_reportset));        \
+									  \
+	if ((reportset) == NULL) {                                        \
+		qdf_print("Spectral simulation: Could not allocate memory " \
+			  "for report set\n"); \
+		depopulate_simdata((simctx));                             \
+		return -EPERM;                                                \
+	}                                                                 \
+									  \
+	qdf_mem_zero((reportset), sizeof(ath_spectralsim_reportset));     \
+									  \
+	if (populate_reportset_static( \
+		(simctx), (reportset), (width), (is_80_80)) != 0) { \
+		depopulate_simdata((simctx));                             \
+		return -EPERM;                                                \
+	}                                                                 \
+									  \
+	(reportset)->next = NULL;                                         \
+	}
+
+/* Depopulate and free list of report sets */
+#define SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(reportset)                 \
+	{                                                                 \
+	ath_spectralsim_reportset *curr_reportset = NULL;                 \
+	ath_spectralsim_reportset *next_reportset = NULL;                 \
+									\
+	curr_reportset = (reportset);                                   \
+									\
+	while (curr_reportset) {                                        \
+		next_reportset = curr_reportset->next;                  \
+		depopulate_reportset(curr_reportset);                   \
+		qdf_mem_free(curr_reportset);                           \
+		curr_reportset = next_reportset;                        \
+	}                                                               \
+									\
+	(reportset) = NULL;                                             \
+	}
+
+/* Values for static population */
+
+/* 20 MHz */
+
+static uint8_t reportdata_20_gen2[] = {
+#ifdef BIG_ENDIAN_HOST
+	0xbb,                           /* Signature */
+	0xfb,                           /* Tag */
+	0x00,                           /* Size */
+	0x54,
+	0x2e, 0x60, 0x0f, 0xe8,         /* FFT Summary A */
+	0x00, 0x00, 0x04, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#else
+	0x54,                           /* Length */
+	0x00,
+	0xfb,                           /* Tag */
+	0xbb,                           /* Signature */
+	0xe8, 0x0f, 0x60, 0x2e,         /* FFT Summary A */
+	0x00, 0x04, 0x00, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 2, 0, 1, 1, 1, 0,
+	0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1,
+	1, 1, 0, 2, 1, 2, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0,
+};
+
+static uint8_t reportdata_20_gen3[] = {
+#ifdef BIG_ENDIAN_HOST
+	0x12, 0x34, 0x56, 0x78,         /* fft_timestamp */
+	0xfa,                           /* fft_hdr_sig */
+	0x03,                           /* fft_hdr_tag */
+	0x00,                           /* fft_hdr_length */
+	0x14,
+	0x0f, 0xf6, 0x00, 0xe0,
+	0x00, 0x00, 0x2f, 0xba,
+	0x20, 0xb4, 0x2c, 0x01,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#else
+	0x78, 0x56, 0x34, 0x12,         /* fft_timestamp */
+	0x14,                           /* fft_hdr_length */
+	0x00,
+	0x03,                           /* fft_hdr_tag */
+	0xfa,                           /* fft_hdr_sig */
+	0xe0, 0x00, 0xf6, 0x0f,
+	0xba, 0x2f, 0x00, 0x00,
+	0x01, 0x2c, 0xb4, 0x20,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 2, 0, 1, 1, 1, 0,
+	0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1,
+	1, 1, 0, 2, 1, 2, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0,
+};
+
+static struct target_if_spectral_rfqual_info rfqual_info_20 = {
+				.rssi_comb = 1,
+
+				.pc_rssi_info[0].rssi_pri20 = 1,
+				.pc_rssi_info[0].rssi_sec20 = 128,
+				.pc_rssi_info[0].rssi_sec40 = 128,
+				.pc_rssi_info[0].rssi_sec80 = 128,
+
+				.pc_rssi_info[1].rssi_pri20 = 128,
+				.pc_rssi_info[1].rssi_sec20 = 128,
+				.pc_rssi_info[1].rssi_sec40 = 128,
+				.pc_rssi_info[1].rssi_sec80 = 128,
+
+				.pc_rssi_info[2].rssi_pri20 = 128,
+				.pc_rssi_info[2].rssi_sec20 = 128,
+				.pc_rssi_info[2].rssi_sec40 = 128,
+				.pc_rssi_info[2].rssi_sec80 = 128,
+
+				.pc_rssi_info[3].rssi_pri20 = 128,
+				.pc_rssi_info[3].rssi_sec20 = 128,
+				.pc_rssi_info[3].rssi_sec40 = 128,
+				.pc_rssi_info[3].rssi_sec80 = 128,
+
+				.noise_floor[0] = -90,
+				.noise_floor[1] = -90,
+				.noise_floor[2] = -90,
+				.noise_floor[3] = -90,
+				};
+
+static struct target_if_spectral_chan_info chan_info_20 = {
+				.center_freq1 = 5180,
+				.center_freq2 = 0,
+				.chan_width = 20,
+				};
+
+static struct spectral_config config_20_1 =  {
+				.ss_fft_period = 1,
+				.ss_period = 35,
+				.ss_count = 0,
+				.ss_short_report = 1,
+				.radar_bin_thresh_sel = 0,
+				.ss_spectral_pri = 1,
+				.ss_fft_size = 7,
+				.ss_gc_ena = 1,
+				.ss_restart_ena = 0,
+				.ss_noise_floor_ref = 65440,
+				.ss_init_delay = 80,
+				.ss_nb_tone_thr = 12,
+				.ss_str_bin_thr = 8,
+				.ss_wb_rpt_mode = 0,
+				.ss_rssi_rpt_mode = 0,
+				.ss_rssi_thr = 240,
+				.ss_pwr_format = 0,
+				.ss_rpt_mode = 2,
+				.ss_bin_scale = 1,
+				.ss_dBm_adj = 1,
+				.ss_chn_mask = 1,
+				.ss_nf_cal[0] = 0,
+				.ss_nf_cal[1] = 0,
+				.ss_nf_cal[2] = 0,
+				.ss_nf_cal[3] = 0,
+				.ss_nf_cal[4] = 0,
+				.ss_nf_cal[5] = 0,
+				.ss_nf_pwr[0] = 0,
+				.ss_nf_pwr[1] = 0,
+				.ss_nf_pwr[2] = 0,
+				.ss_nf_pwr[3] = 0,
+				.ss_nf_pwr[4] = 0,
+				.ss_nf_pwr[5] = 0,
+				.ss_nf_temp_data = 0,
+				};
+
+/* 40 MHz */
+
+static uint8_t reportdata_40_gen2[] = {
+#ifdef BIG_ENDIAN_HOST
+	0xbb,                           /* Signature */
+	0xfb,                           /* Tag */
+	0x00,                           /* Size */
+	0x94,
+	0x2e, 0x61, 0x0f, 0x80,         /* FFT Summary A */
+	0x00, 0x00, 0x06, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#else
+	0x94,                           /* Length */
+	0x00,
+	0xfb,                           /* Tag */
+	0xbb,                           /* Signature */
+	0x80, 0x0f, 0x61, 0x2e,         /* FFT Summary A */
+	0x00, 0x06, 0x00, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1,
+	0, 0, 0, 1, 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0,
+	1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+	0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
+};
+
+static uint8_t reportdata_40_gen3[] = {
+#ifdef BIG_ENDIAN_HOST
+	0x12, 0x34, 0x56, 0x78,         /* fft_timestamp */
+	0xfa,                           /* fft_hdr_sig */
+	0x03,                           /* fft_hdr_tag */
+	0x00,                           /* fft_hdr_length */
+	0x24,
+	0x0f, 0xf6, 0x00, 0xe0,
+	0x00, 0x00, 0x2f, 0xba,
+	0x20, 0xb4, 0x2c, 0x01,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#else
+	0x78, 0x56, 0x34, 0x12,         /* fft_timestamp */
+	0x24,                           /* fft_hdr_length */
+	0x00,
+	0x03,                           /* fft_hdr_tag */
+	0xfa,                           /* fft_hdr_sig */
+	0xe0, 0x00, 0xf6, 0x0f,
+	0xba, 0x2f, 0x00, 0x00,
+	0x01, 0x2c, 0xb4, 0x20,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1,
+	0, 0, 0, 1, 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0,
+	1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+	0, 0, 0, 1, 0, 0, 0, 0,
+};
+
+static struct target_if_spectral_rfqual_info rfqual_info_40 = {
+				.rssi_comb = 1,
+
+				.pc_rssi_info[0].rssi_pri20 = 1,
+				.pc_rssi_info[0].rssi_sec20 = 2,
+				.pc_rssi_info[0].rssi_sec40 = 128,
+				.pc_rssi_info[0].rssi_sec80 = 128,
+
+				.pc_rssi_info[1].rssi_pri20 = 128,
+				.pc_rssi_info[1].rssi_sec20 = 128,
+				.pc_rssi_info[1].rssi_sec40 = 128,
+				.pc_rssi_info[1].rssi_sec80 = 128,
+
+				.pc_rssi_info[2].rssi_pri20 = 128,
+				.pc_rssi_info[2].rssi_sec20 = 128,
+				.pc_rssi_info[2].rssi_sec40 = 128,
+				.pc_rssi_info[2].rssi_sec80 = 128,
+
+				.pc_rssi_info[3].rssi_pri20 = 128,
+				.pc_rssi_info[3].rssi_sec20 = 128,
+				.pc_rssi_info[3].rssi_sec40 = 128,
+				.pc_rssi_info[3].rssi_sec80 = 128,
+
+				.noise_floor[0] = -90,
+				.noise_floor[1] = -90,
+				.noise_floor[2] = -90,
+				.noise_floor[3] = -90,
+				};
+
+static struct target_if_spectral_chan_info chan_info_40 = {
+				.center_freq1 = 5180,
+				.center_freq2 = 0,
+				.chan_width = 40,
+				};
+
+static struct spectral_config config_40_1 =  {
+				.ss_fft_period = 1,
+				.ss_period = 35,
+				.ss_count = 0,
+				.ss_short_report = 1,
+				.radar_bin_thresh_sel = 0,
+				.ss_spectral_pri = 1,
+				.ss_fft_size = 8,
+				.ss_gc_ena = 1,
+				.ss_restart_ena = 0,
+				.ss_noise_floor_ref = 65440,
+				.ss_init_delay = 80,
+				.ss_nb_tone_thr = 12,
+				.ss_str_bin_thr = 8,
+				.ss_wb_rpt_mode = 0,
+				.ss_rssi_rpt_mode = 0,
+				.ss_rssi_thr = 240,
+				.ss_pwr_format = 0,
+				.ss_rpt_mode = 2,
+				.ss_bin_scale = 1,
+				.ss_dBm_adj = 1,
+				.ss_chn_mask = 1,
+				.ss_nf_cal[0] = 0,
+				.ss_nf_cal[1] = 0,
+				.ss_nf_cal[2] = 0,
+				.ss_nf_cal[3] = 0,
+				.ss_nf_cal[4] = 0,
+				.ss_nf_cal[5] = 0,
+				.ss_nf_pwr[0] = 0,
+				.ss_nf_pwr[1] = 0,
+				.ss_nf_pwr[2] = 0,
+				.ss_nf_pwr[3] = 0,
+				.ss_nf_pwr[4] = 0,
+				.ss_nf_pwr[5] = 0,
+				.ss_nf_temp_data = 0,
+				};
+
+/* 80 MHz */
+
+static uint8_t reportdata_80_gen2[] = {
+#ifdef BIG_ENDIAN_HOST
+	0xbb,                           /* Signature */
+	0xfb,                           /* Tag */
+	0x01,                           /* Size */
+	0x14,
+	0x19, 0xeb, 0x80, 0x40,         /* FFT Summary A */
+	0x00, 0x00, 0x10, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#else
+	0x14,                           /* Length */
+	0x01,
+	0xfb,                           /* Tag */
+	0xbb,                           /* Signature */
+	0x40, 0x80, 0xeb, 0x19,         /* FFT Summary A */
+	0x00, 0x10, 0x00, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static uint8_t reportdata_80_gen3[] = {
+#ifdef BIG_ENDIAN_HOST
+	0x12, 0x34, 0x56, 0x78,         /* fft_timestamp */
+	0xfa,                           /* fft_hdr_sig */
+	0x03,                           /* fft_hdr_tag */
+	0x00,                           /* fft_hdr_length */
+	0x44,
+	0x0f, 0xf6, 0x00, 0xe0,
+	0x00, 0x00, 0x2f, 0xba,
+	0x20, 0xb4, 0x2c, 0x01,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#else
+	0x78, 0x56, 0x34, 0x12,         /* fft_timestamp */
+	0x44,                           /* fft_hdr_length */
+	0x00,
+	0x03,                           /* fft_hdr_tag */
+	0xfa,                           /* fft_hdr_sig */
+	0xe0, 0x00, 0xf6, 0x0f,
+	0xba, 0x2f, 0x00, 0x00,
+	0x01, 0x2c, 0xb4, 0x20,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static struct target_if_spectral_rfqual_info rfqual_info_80 = {
+				.rssi_comb = 16,
+
+				.pc_rssi_info[0].rssi_pri20 = 16,
+				.pc_rssi_info[0].rssi_sec20 = 17,
+				.pc_rssi_info[0].rssi_sec40 = 0,
+				.pc_rssi_info[0].rssi_sec80 = 128,
+
+				.pc_rssi_info[1].rssi_pri20 = 128,
+				.pc_rssi_info[1].rssi_sec20 = 128,
+				.pc_rssi_info[1].rssi_sec40 = 128,
+				.pc_rssi_info[1].rssi_sec80 = 128,
+
+				.pc_rssi_info[2].rssi_pri20 = 128,
+				.pc_rssi_info[2].rssi_sec20 = 128,
+				.pc_rssi_info[2].rssi_sec40 = 128,
+				.pc_rssi_info[2].rssi_sec80 = 128,
+
+				.pc_rssi_info[3].rssi_pri20 = 128,
+				.pc_rssi_info[3].rssi_sec20 = 128,
+				.pc_rssi_info[3].rssi_sec40 = 128,
+				.pc_rssi_info[3].rssi_sec80 = 128,
+
+				.noise_floor[0] = -90,
+				.noise_floor[1] = -90,
+				.noise_floor[2] = -90,
+				.noise_floor[3] = -90,
+				};
+
+static struct target_if_spectral_chan_info chan_info_80 = {
+				.center_freq1 = 5210,
+				.center_freq2 = 0,
+				.chan_width = 80,
+				};
+
+static struct spectral_config config_80_1 =  {
+				.ss_fft_period = 1,
+				.ss_period = 35,
+				.ss_count = 0,
+				.ss_short_report = 1,
+				.radar_bin_thresh_sel = 0,
+				.ss_spectral_pri = 1,
+				.ss_fft_size = 9,
+				.ss_gc_ena = 1,
+				.ss_restart_ena = 0,
+				.ss_noise_floor_ref = 65440,
+				.ss_init_delay = 80,
+				.ss_nb_tone_thr = 12,
+				.ss_str_bin_thr = 8,
+				.ss_wb_rpt_mode = 0,
+				.ss_rssi_rpt_mode = 0,
+				.ss_rssi_thr = 240,
+				.ss_pwr_format = 0,
+				.ss_rpt_mode = 2,
+				.ss_bin_scale = 1,
+				.ss_dBm_adj = 1,
+				.ss_chn_mask = 1,
+				.ss_nf_cal[0] = 0,
+				.ss_nf_cal[1] = 0,
+				.ss_nf_cal[2] = 0,
+				.ss_nf_cal[3] = 0,
+				.ss_nf_cal[4] = 0,
+				.ss_nf_cal[5] = 0,
+				.ss_nf_pwr[0] = 0,
+				.ss_nf_pwr[1] = 0,
+				.ss_nf_pwr[2] = 0,
+				.ss_nf_pwr[3] = 0,
+				.ss_nf_pwr[4] = 0,
+				.ss_nf_pwr[5] = 0,
+				.ss_nf_temp_data = 0,
+				};
+
+/* 160 MHz */
+
+static uint8_t reportdata_160_gen2[] = {
+	/* Segment 1 */
+#ifdef BIG_ENDIAN_HOST
+	0xbb,                           /* Signature */
+	0xfb,                           /* Tag */
+	0x01,                           /* Size */
+	0x14,
+	0x23, 0x66, 0x00, 0x40,         /* FFT Summary A */
+	0x5c, 0x5c, 0x78, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#else
+	0x14,                           /* Length */
+	0x01,
+	0xfb,                           /* Tag */
+	0xbb,                           /* Signature */
+	0x40, 0x00, 0x66, 0x23,         /* FFT Summary A */
+	0x00, 0x78, 0x5c, 0x5c,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 2, 4, 60, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0,
+
+	/* Segment 2 */
+#ifdef BIG_ENDIAN_HOST
+	0xbb,                           /* Signature */
+	0xfb,                           /* Tag */
+	0x01,                           /* Size */
+	0x14,
+	0x23, 0x66, 0x00, 0x40,         /* FFT Summary A */
+	0x5c, 0x5c, 0x78, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x01,         /* Segment ID */
+#else
+	0x14,                           /* Length */
+	0x01,
+	0xfb,                           /* Tag */
+	0xbb,                           /* Signature */
+	0x40, 0x00, 0x66, 0x23,         /* FFT Summary A */
+	0x00, 0x78, 0x5c, 0x5c,         /* FFT Summary B */
+	0x01, 0x00, 0x00, 0x00,         /* Segment ID */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 2, 4, 60, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0,
+};
+
+static uint8_t reportdata_160_gen3[] = {
+	/* Segment 1 */
+#ifdef BIG_ENDIAN_HOST
+	0x12, 0x34, 0x56, 0x78,         /* fft_timestamp */
+	0xfa,                           /* fft_hdr_sig */
+	0x03,                           /* fft_hdr_tag */
+	0x00,                           /* fft_hdr_length */
+	0x44,
+	0x0f, 0xf6, 0x00, 0xe0,
+	0x00, 0x00, 0x2f, 0xba,
+	0x20, 0xb4, 0x2c, 0x01,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#else
+	0x78, 0x56, 0x34, 0x12,         /* fft_timestamp */
+	0x44,                           /* fft_hdr_length */
+	0x00,
+	0x03,                           /* fft_hdr_tag */
+	0xfa,                           /* fft_hdr_sig */
+	0xe0, 0x00, 0xf6, 0x0f,
+	0xba, 0x2f, 0x00, 0x00,
+	0x01, 0x2c, 0xb4, 0x20,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 2, 4, 60, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+	/* Segment 2 */
+#ifdef BIG_ENDIAN_HOST
+	0x12, 0x34, 0x56, 0x78,         /* fft_timestamp */
+	0xfa,                           /* fft_hdr_sig */
+	0x03,                           /* fft_hdr_tag */
+	0x00,                           /* fft_hdr_length */
+	0x44,
+	0x0f, 0xf6, 0x00, 0xe1,
+	0x00, 0x00, 0x2f, 0xba,
+	0x20, 0xb4, 0x2c, 0x01,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#else
+	0x78, 0x56, 0x34, 0x12,         /* fft_timestamp */
+	0x44,                           /* fft_hdr_length */
+	0x00,
+	0x03,                           /* fft_hdr_tag */
+	0xfa,                           /* fft_hdr_sig */
+	0xe1, 0x00, 0xf6, 0x0f,
+	0xba, 0x2f, 0x00, 0x00,
+	0x01, 0x2c, 0xb4, 0x20,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 2, 4, 60, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static struct target_if_spectral_rfqual_info rfqual_info_160 = {
+				.rssi_comb = 3,
+
+				.pc_rssi_info[0].rssi_pri20 = 3,
+				.pc_rssi_info[0].rssi_sec20 = 12,
+				.pc_rssi_info[0].rssi_sec40 = 41,
+				.pc_rssi_info[0].rssi_sec80 = 128,
+
+				.pc_rssi_info[1].rssi_pri20 = 128,
+				.pc_rssi_info[1].rssi_sec20 = 128,
+				.pc_rssi_info[1].rssi_sec40 = 128,
+				.pc_rssi_info[1].rssi_sec80 = 128,
+
+				.pc_rssi_info[2].rssi_pri20 = 128,
+				.pc_rssi_info[2].rssi_sec20 = 128,
+				.pc_rssi_info[2].rssi_sec40 = 128,
+				.pc_rssi_info[2].rssi_sec80 = 128,
+
+				.pc_rssi_info[3].rssi_pri20 = 128,
+				.pc_rssi_info[3].rssi_sec20 = 128,
+				.pc_rssi_info[3].rssi_sec40 = 128,
+				.pc_rssi_info[3].rssi_sec80 = 128,
+
+				.noise_floor[0] = -90,
+				.noise_floor[1] = -90,
+				.noise_floor[2] = -90,
+				.noise_floor[3] = -90,
+				};
+
+static struct target_if_spectral_chan_info chan_info_160 = {
+				.center_freq1 = 5250,
+				.center_freq2 = 0,
+				.chan_width = 160,
+				};
+
+static struct spectral_config config_160_1 =  {
+				.ss_fft_period = 1,
+				.ss_period = 35,
+				.ss_count = 0,
+				.ss_short_report = 1,
+				.radar_bin_thresh_sel = 0,
+				.ss_spectral_pri = 1,
+				.ss_fft_size = 9,
+				.ss_gc_ena = 1,
+				.ss_restart_ena = 0,
+				.ss_noise_floor_ref = 65440,
+				.ss_init_delay = 80,
+				.ss_nb_tone_thr = 12,
+				.ss_str_bin_thr = 8,
+				.ss_wb_rpt_mode = 0,
+				.ss_rssi_rpt_mode = 0,
+				.ss_rssi_thr = 240,
+				.ss_pwr_format = 0,
+				.ss_rpt_mode = 2,
+				.ss_bin_scale = 1,
+				.ss_dBm_adj = 1,
+				.ss_chn_mask = 1,
+				.ss_nf_cal[0] = 0,
+				.ss_nf_cal[1] = 0,
+				.ss_nf_cal[2] = 0,
+				.ss_nf_cal[3] = 0,
+				.ss_nf_cal[4] = 0,
+				.ss_nf_cal[5] = 0,
+				.ss_nf_pwr[0] = 0,
+				.ss_nf_pwr[1] = 0,
+				.ss_nf_pwr[2] = 0,
+				.ss_nf_pwr[3] = 0,
+				.ss_nf_pwr[4] = 0,
+				.ss_nf_pwr[5] = 0,
+				.ss_nf_temp_data = 0,
+				};
+
+/* 80+80 MHz */
+
+static uint8_t reportdata_80_80_gen2[] = {
+	/* Segment 1 */
+#ifdef BIG_ENDIAN_HOST
+	0xbb,                           /* Signature */
+	0xfb,                           /* Tag */
+	0x01,                           /* Size */
+	0x14,
+	0x23, 0x66, 0x00, 0x40,         /* FFT Summary A */
+	0x64, 0x64, 0x89, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#else
+	0x14,                           /* Length */
+	0x01,
+	0xfb,                           /* Tag */
+	0xbb,                           /* Signature */
+	0x40, 0x00, 0x66, 0x23,         /* FFT Summary A */
+	0x00, 0x89, 0x64, 0x64,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x00,         /* Segment ID */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 2, 6, 68, 5, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0,
+
+	/* Segment 2 */
+#ifdef BIG_ENDIAN_HOST
+	0xbb,                           /* Signature */
+	0xfb,                           /* Tag */
+	0x01,                           /* Size */
+	0x14,
+	0x23, 0x66, 0x00, 0x40,         /* FFT Summary A */
+	0x64, 0x64, 0x89, 0x00,         /* FFT Summary B */
+	0x00, 0x00, 0x00, 0x01,         /* Segment ID */
+#else
+	0x14,                           /* Length */
+	0x01,
+	0xfb,                           /* Tag */
+	0xbb,                           /* Signature */
+	0x40, 0x00, 0x66, 0x23,         /* FFT Summary A */
+	0x00, 0x89, 0x64, 0x64,         /* FFT Summary B */
+	0x01, 0x00, 0x00, 0x00,         /* Segment ID */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 2, 6, 68, 5, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0,
+};
+
+static uint8_t reportdata_80_80_gen3[] = {
+	/* Segment 1 */
+#ifdef BIG_ENDIAN_HOST
+	0x12, 0x34, 0x56, 0x78,         /* fft_timestamp */
+	0xfa,                           /* fft_hdr_sig */
+	0x03,                           /* fft_hdr_tag */
+	0x00,                           /* fft_hdr_length */
+	0x44,
+	0x0f, 0xf6, 0x00, 0xe0,
+	0x00, 0x00, 0x2f, 0xba,
+	0x20, 0xb4, 0x2c, 0x01,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#else
+	0x78, 0x56, 0x34, 0x12,         /* fft_timestamp */
+	0x44,                           /* fft_hdr_length */
+	0x00,
+	0x03,                           /* fft_hdr_tag */
+	0xfa,                           /* fft_hdr_sig */
+	0xe0, 0x00, 0xf6, 0x0f,
+	0xba, 0x2f, 0x00, 0x00,
+	0x01, 0x2c, 0xb4, 0x20,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 2, 6, 68, 5, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+	/* Segment 2 */
+#ifdef BIG_ENDIAN_HOST
+	0x12, 0x34, 0x56, 0x78,         /* fft_timestamp */
+	0xfa,                           /* fft_hdr_sig */
+	0x03,                           /* fft_hdr_tag */
+	0x00,                           /* fft_hdr_length */
+	0x44,
+	0x0f, 0xf6, 0x00, 0xe1,
+	0x00, 0x00, 0x2f, 0xba,
+	0x20, 0xb4, 0x2c, 0x01,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#else
+	0x78, 0x56, 0x34, 0x12,         /* fft_timestamp */
+	0x44,                           /* fft_hdr_length */
+	0x00,
+	0x03,                           /* fft_hdr_tag */
+	0xfa,                           /* fft_hdr_sig */
+	0xe1, 0x00, 0xf6, 0x0f,
+	0xba, 0x2f, 0x00, 0x00,
+	0x01, 0x2c, 0xb4, 0x20,
+	0x00, 0x00, 0x00, 0x00,         /* reserved */
+#endif /* BIG_ENDIAN_HOST */
+	/* FFT Data */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 2, 6, 68, 5, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static struct target_if_spectral_rfqual_info rfqual_info_80_80 = {
+				.rssi_comb = 1,
+
+				.pc_rssi_info[0].rssi_pri20 = 1,
+				.pc_rssi_info[0].rssi_sec20 = 17,
+				.pc_rssi_info[0].rssi_sec40 = 40,
+				.pc_rssi_info[0].rssi_sec80 = 128,
+
+				.pc_rssi_info[1].rssi_pri20 = 128,
+				.pc_rssi_info[1].rssi_sec20 = 128,
+				.pc_rssi_info[1].rssi_sec40 = 128,
+				.pc_rssi_info[1].rssi_sec80 = 128,
+
+				.pc_rssi_info[2].rssi_pri20 = 128,
+				.pc_rssi_info[2].rssi_sec20 = 128,
+				.pc_rssi_info[2].rssi_sec40 = 128,
+				.pc_rssi_info[2].rssi_sec80 = 128,
+
+				.pc_rssi_info[3].rssi_pri20 = 128,
+				.pc_rssi_info[3].rssi_sec20 = 128,
+				.pc_rssi_info[3].rssi_sec40 = 128,
+				.pc_rssi_info[3].rssi_sec80 = 128,
+
+				.noise_floor[0] = -90,
+				.noise_floor[1] = -90,
+				.noise_floor[2] = -90,
+				.noise_floor[3] = -90,
+				};
+
+static struct target_if_spectral_chan_info chan_info_80_80 = {
+				.center_freq1 = 5210,
+				.center_freq2 = 5530,
+				.chan_width = 160,
+				};
+
+static struct spectral_config config_80_80_1 =  {
+				.ss_fft_period = 1,
+				.ss_period = 35,
+				.ss_count = 0,
+				.ss_short_report = 1,
+				.radar_bin_thresh_sel = 0,
+				.ss_spectral_pri = 1,
+				.ss_fft_size = 9,
+				.ss_gc_ena = 1,
+				.ss_restart_ena = 0,
+				.ss_noise_floor_ref = 65440,
+				.ss_init_delay = 80,
+				.ss_nb_tone_thr = 12,
+				.ss_str_bin_thr = 8,
+				.ss_wb_rpt_mode = 0,
+				.ss_rssi_rpt_mode = 0,
+				.ss_rssi_thr = 240,
+				.ss_pwr_format = 0,
+				.ss_rpt_mode = 2,
+				.ss_bin_scale = 1,
+				.ss_dBm_adj = 1,
+				.ss_chn_mask = 1,
+				.ss_nf_cal[0] = 0,
+				.ss_nf_cal[1] = 0,
+				.ss_nf_cal[2] = 0,
+				.ss_nf_cal[3] = 0,
+				.ss_nf_cal[4] = 0,
+				.ss_nf_cal[5] = 0,
+				.ss_nf_pwr[0] = 0,
+				.ss_nf_pwr[1] = 0,
+				.ss_nf_pwr[2] = 0,
+				.ss_nf_pwr[3] = 0,
+				.ss_nf_pwr[4] = 0,
+				.ss_nf_pwr[5] = 0,
+				.ss_nf_temp_data = 0,
+				};
+
+#endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */
+#endif /* _SPECTRAL_SIM_INTERNAL_H_ */