qcacmn: Add QCA vendor commands for spectral scan

Add following vendor commands and their handlers.

 1) QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START
        Set the spectral parameters and start scan.
 2) QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS
        Stop spectral scan.
 3) QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG
        Get current values of spectral parameters.
 4) QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS
        Get stats for spectral scan debug.
 5) QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO
        Get the spectral hardware capability.
 6) QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS
        Get the current status of spectral scan.

CRs-Fixed: 2146272
Change-Id: I8e048d6c21e9fb1ed286c19df0edcad46f6e6414
diff --git a/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h b/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h
new file mode 100644
index 0000000..39bae6f
--- /dev/null
+++ b/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+/**
+ * DOC: declares driver functions interfacing with linux kernel
+ */
+
+#ifndef _WLAN_CFG80211_SPECTRAL_H_
+#define _WLAN_CFG80211_SPECTRAL_H_
+
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <net/cfg80211.h>
+#include <qca_vendor.h>
+#include <qdf_list.h>
+#include <qdf_types.h>
+#include <spectral_ioctl.h>
+#include <wlan_spectral_public_structs.h>
+
+#define CONFIG_REQUESTED(type)    ((type == \
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG) || \
+	(type == QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG))
+
+#define SCAN_REQUESTED(type)    ((type == \
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG) || \
+	(type == QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN))
+
+/**
+ * wlan_cfg80211_register_spectral_cmd_handler() - Registration api for spectral
+ * @pdev:    Pointer to pdev
+ * @idx:     Index in function table
+ * @handler: Pointer to handler
+ *
+ * Return: 0 on success, negative value on failure
+ */
+void wlan_cfg80211_register_spectral_cmd_handler(struct wlan_objmgr_pdev *pdev,
+						 int idx,
+						 void *handler);
+
+/**
+ * wlan_cfg80211_spectral_scan_config_and_start() - Start spectral scan
+ * @wiphy:    Pointer to wiphy
+ * @pdev:     Pointer to pdev
+ * @data:     Reference to data
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success, negative value on failure
+ */
+int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy,
+						 struct wlan_objmgr_pdev *pdev,
+						 const void *data,
+						 int data_len);
+
+/**
+ * wlan_cfg80211_spectral_scan_stop() - Stop spectral scan
+ * @wiphy:    Pointer to wiphy
+ * @pdev:     Pointer to pdev
+ * @data:     Reference to data
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success, negative value on failure
+ */
+int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy,
+				     struct wlan_objmgr_pdev *pdev,
+				     const void *data,
+				     int data_len);
+
+/**
+ * wlan_cfg80211_spectral_scan_get_config() - Get spectral scan config
+ * @wiphy:    Pointer to wiphy
+ * @pdev:     Pointer to pdev
+ * @data:     Reference to data
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success, negative value on failure
+ */
+int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy,
+					   struct wlan_objmgr_pdev *pdev,
+					   const void *data,
+					   int data_len);
+
+/**
+ * wlan_cfg80211_spectral_scan_get_cap() - Get spectral system capabilities
+ * @wiphy:    Pointer to wiphy
+ * @pdev:     Pointer to pdev
+ * @data:     Reference to data
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success, negative value on failure
+ */
+int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy,
+					struct wlan_objmgr_pdev *pdev,
+					const void *data,
+					int data_len);
+
+/**
+ * wlan_cfg80211_spectral_scan_get_diag_stats() - Get spectral diag stats
+ * @wiphy:    Pointer to wiphy
+ * @pdev:     Pointer to pdev
+ * @data:     Reference to data
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success, negative value on failure
+ */
+int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy,
+					       struct wlan_objmgr_pdev *pdev,
+					       const void *data,
+					       int data_len);
+
+/**
+ * wlan_cfg80211_spectral_scan_get_status() - Get spectral scan status
+ * @wiphy:    Pointer to wiphy
+ * @pdev:     Pointer to pdev
+ * @data:     Reference to data
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success, negative value on failure
+ */
+int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy,
+					   struct wlan_objmgr_pdev *pdev,
+					   const void *data,
+					   int data_len);
+#endif
diff --git a/os_if/linux/spectral/src/wlan_cfg80211_spectral.c b/os_if/linux/spectral/src/wlan_cfg80211_spectral.c
new file mode 100644
index 0000000..fdb160a
--- /dev/null
+++ b/os_if/linux/spectral/src/wlan_cfg80211_spectral.c
@@ -0,0 +1,671 @@
+/*
+ * 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.
+ */
+
+/**
+ * DOC: defines driver functions interfacing with linux kernel
+ */
+
+#include <qdf_list.h>
+#include <qdf_status.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <net/cfg80211.h>
+#include <wlan_cfg80211.h>
+#include <wlan_osif_priv.h>
+#include <qdf_mem.h>
+#ifdef WLAN_POLICY_MGR_ENABLE
+#include <wlan_policy_mgr_api.h>
+#endif
+#include <wlan_spectral_ucfg_api.h>
+#include <wlan_cfg80211_spectral.h>
+#include <spectral_ioctl.h>
+
+static const struct nla_policy spectral_scan_policy[
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE] = {
+							.type = NLA_U64},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT] = {
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL] = {
+							.type = NLA_U32},
+};
+
+static void wlan_spectral_intit_config(struct spectral_config *config_req)
+{
+	config_req->ss_period =          SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_count =           SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_fft_period =      SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_short_report =    SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_spectral_pri =    SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_fft_size =        SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_gc_ena =          SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_restart_ena =     SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_noise_floor_ref = SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_init_delay =      SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_nb_tone_thr =     SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_str_bin_thr =     SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_wb_rpt_mode =     SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_rssi_rpt_mode =   SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_rssi_thr =        SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_pwr_format =      SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_rpt_mode =        SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_bin_scale =       SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_dBm_adj =         SPECTRAL_PHYERR_PARAM_NOVAL;
+	config_req->ss_chn_mask =        SPECTRAL_PHYERR_PARAM_NOVAL;
+}
+
+static int wlan_spectral_set_config(struct wlan_objmgr_pdev *pdev,
+				    struct spectral_config *config_req)
+{
+	int status;
+
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_SET_CONFIG,
+				       config_req,
+				       sizeof(struct spectral_config),
+				       NULL,
+				       NULL);
+	if (status < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int wlan_spectral_set_debug_level(struct wlan_objmgr_pdev *pdev,
+					 uint32_t spectral_dbg_level)
+{
+	int status;
+
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_SET_DEBUG_LEVEL,
+				       &spectral_dbg_level,
+				       sizeof(uint32_t),
+				       NULL,
+				       NULL);
+	if (status < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int wlan_spectral_get_debug_level(struct wlan_objmgr_pdev *pdev,
+					 uint32_t *spectral_dbg_level)
+{
+	int status;
+	uint32_t outsize;
+
+	outsize = sizeof(uint32_t);
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_GET_DEBUG_LEVEL,
+				       NULL,
+				       0,
+				       spectral_dbg_level,
+				       &outsize);
+	if (status < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int wlan_spectral_get_config(struct wlan_objmgr_pdev *pdev,
+				    struct spectral_config *config_req)
+{
+	int status;
+	uint32_t outsize;
+
+	outsize = sizeof(struct spectral_config);
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_GET_CONFIG,
+				       NULL,
+				       0,
+				       config_req,
+				       &outsize);
+	if (status < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int wlan_spectral_get_cap(struct wlan_objmgr_pdev *pdev,
+				 struct spectral_caps *spectral_cap)
+{
+	int status;
+	uint32_t outsize;
+
+	outsize = sizeof(struct spectral_caps);
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_GET_CAPABILITY_INFO,
+				       NULL,
+				       0,
+				       spectral_cap,
+				       &outsize);
+	if (status < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int wlan_spectral_get_diag_stats(
+		struct wlan_objmgr_pdev *pdev,
+		struct spectral_diag_stats *spectral_diag)
+{
+	int status;
+	uint32_t outsize;
+
+	outsize = sizeof(struct spectral_diag_stats);
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_GET_DIAG_STATS,
+				       NULL,
+				       0,
+				       spectral_diag,
+				       &outsize);
+	if (status < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int wlan_spectral_scan_get_status(
+		struct wlan_objmgr_pdev *pdev,
+		struct spectral_scan_state *sscan_state)
+{
+	uint32_t is_active;
+	uint32_t is_enabled;
+	int status;
+	uint32_t outsize;
+
+	outsize = sizeof(uint32_t);
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_IS_ACTIVE,
+				       NULL,
+				       0,
+				       &is_active,
+				       &outsize);
+	if (status < 0)
+		return -EINVAL;
+
+	sscan_state->is_active = is_active;
+
+	outsize = sizeof(uint32_t);
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_IS_ENABLED,
+				       NULL,
+				       0,
+				       &is_enabled,
+				       &outsize);
+	if (status < 0)
+		return -EINVAL;
+
+	sscan_state->is_enabled = is_enabled;
+
+	return 0;
+}
+
+static int wlan_start_spectral_scan(struct wlan_objmgr_pdev *pdev)
+{
+	int status;
+
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_ACTIVATE_SCAN,
+				       NULL,
+				       0,
+				       NULL,
+				       NULL);
+	if (status < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int wlan_stop_spectral_scan(struct wlan_objmgr_pdev *pdev)
+{
+	int status;
+
+	status = ucfg_spectral_control(pdev,
+				       SPECTRAL_STOP_SCAN,
+				       NULL,
+				       0,
+				       NULL,
+				       NULL);
+	if (status < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy,
+						 struct wlan_objmgr_pdev *pdev,
+						 const void *data,
+						 int data_len)
+{
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1];
+	struct spectral_config config_req;
+	QDF_STATUS status;
+	uint64_t cookie;
+	struct sk_buff *skb;
+	uint32_t spectral_dbg_level;
+	uint32_t scan_req_type;
+
+	if (wlan_cfg80211_nla_parse(
+			tb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX,
+			data,
+			data_len,
+			spectral_scan_policy)) {
+		qdf_print("Invalid Spectral Scan config ATTR");
+		return -EINVAL;
+	}
+
+	wlan_spectral_intit_config(&config_req);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT])
+		config_req.ss_count = nla_get_u32(tb
+			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD])
+		config_req.ss_period = nla_get_u32(tb
+		[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY])
+		config_req.ss_spectral_pri = nla_get_u32(tb
+			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE])
+		config_req.ss_fft_size = nla_get_u32(tb
+			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA])
+		config_req.ss_gc_ena = nla_get_u32(tb
+			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA])
+		config_req.ss_restart_ena = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF])
+		config_req.ss_noise_floor_ref = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY])
+		config_req.ss_init_delay = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR])
+		config_req.ss_nb_tone_thr = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR])
+		config_req.ss_str_bin_thr = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE])
+		config_req.ss_wb_rpt_mode = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE])
+		config_req.ss_rssi_rpt_mode = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR])
+		config_req.ss_rssi_thr = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT])
+		config_req.ss_pwr_format = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE])
+		config_req.ss_rpt_mode = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE])
+		config_req.ss_bin_scale = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ])
+		config_req.ss_dBm_adj = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK])
+		config_req.ss_chn_mask = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD])
+		config_req.ss_fft_period = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT])
+		config_req.ss_short_report = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]) {
+		spectral_dbg_level = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]);
+		status = wlan_spectral_set_debug_level(pdev,
+						       spectral_dbg_level);
+		if (QDF_STATUS_SUCCESS != status)
+			return -EINVAL;
+	}
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE])
+		scan_req_type = nla_get_u32(tb
+		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]);
+
+	if (CONFIG_REQUESTED(scan_req_type)) {
+		status = wlan_spectral_set_config(pdev, &config_req);
+		if (QDF_STATUS_SUCCESS != status)
+			return -EINVAL;
+	}
+
+	if (SCAN_REQUESTED(scan_req_type)) {
+		status = wlan_start_spectral_scan(pdev);
+		if (QDF_STATUS_SUCCESS != status)
+			return -EINVAL;
+	}
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u64) +
+		NLA_HDRLEN + NLMSG_HDRLEN);
+	if (!skb) {
+		qdf_print(" reply skb alloc failed");
+		return -ENOMEM;
+	}
+
+	cookie = 0;
+	if (wlan_cfg80211_nla_put_u64(skb,
+				      QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE,
+				      cookie)) {
+		kfree_skb(skb);
+		return -EINVAL;
+	}
+
+	cfg80211_vendor_cmd_reply(skb);
+
+	return 0;
+}
+
+int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy,
+				     struct wlan_objmgr_pdev *pdev,
+				     const void *data,
+				     int data_len)
+{
+	QDF_STATUS status;
+
+	status = wlan_stop_spectral_scan(pdev);
+	if (QDF_STATUS_SUCCESS != status)
+		return -EINVAL;
+	return 0;
+}
+
+int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy,
+					   struct wlan_objmgr_pdev *pdev,
+					   const void *data,
+					   int data_len)
+{
+	struct spectral_config config_buf;
+	uint32_t spectral_dbg_level;
+	struct sk_buff *skb;
+
+	wlan_spectral_get_config(pdev, &config_buf);
+	wlan_spectral_get_debug_level(pdev, &spectral_dbg_level);
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (21 * sizeof(u32)) +
+		NLA_HDRLEN + NLMSG_HDRLEN);
+	if (!skb) {
+		qdf_print(" reply skb alloc failed");
+		return -ENOMEM;
+	}
+
+	if (nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT,
+			config_buf.ss_count) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD,
+			config_buf.ss_period) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY,
+			config_buf.ss_spectral_pri) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE,
+			config_buf.ss_fft_size) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA,
+			config_buf.ss_gc_ena) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA,
+			config_buf.ss_restart_ena) ||
+	    nla_put_u32(
+		skb,
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF,
+		config_buf.ss_noise_floor_ref) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY,
+			config_buf.ss_init_delay) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR,
+			config_buf.ss_nb_tone_thr) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR,
+			config_buf.ss_str_bin_thr) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE,
+			config_buf.ss_wb_rpt_mode) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE,
+			config_buf.ss_rssi_rpt_mode) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR,
+			config_buf.ss_rssi_thr) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT,
+			config_buf.ss_pwr_format) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE,
+			config_buf.ss_rpt_mode) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE,
+			config_buf.ss_bin_scale) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ,
+			config_buf.ss_dBm_adj) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK,
+			config_buf.ss_chn_mask) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD,
+			config_buf.ss_fft_period) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT,
+			config_buf.ss_short_report) ||
+	    nla_put_u32(skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL,
+			spectral_dbg_level)) {
+		kfree_skb(skb);
+		return -EINVAL;
+	}
+	cfg80211_vendor_cmd_reply(skb);
+
+	return 0;
+}
+
+int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy,
+					struct wlan_objmgr_pdev *pdev,
+					const void *data,
+					int data_len)
+{
+	struct spectral_caps spectral_cap;
+	struct sk_buff *skb;
+
+	wlan_spectral_get_cap(pdev, &spectral_cap);
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 4 * sizeof(u32) +
+		NLA_HDRLEN + NLMSG_HDRLEN);
+	if (!skb) {
+		qdf_print(" reply skb alloc failed");
+		return -ENOMEM;
+	}
+
+	if (spectral_cap.phydiag_cap)
+		if (nla_put_flag(
+			skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG))
+			goto fail;
+
+	if (spectral_cap.radar_cap)
+		if (nla_put_flag(skb,
+				 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR))
+			goto fail;
+
+	if (spectral_cap.spectral_cap)
+		if (nla_put_flag(
+			skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL))
+			goto fail;
+
+	if (spectral_cap.advncd_spectral_cap)
+		if (nla_put_flag(
+		skb,
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL))
+			goto fail;
+	cfg80211_vendor_cmd_reply(skb);
+	return 0;
+
+fail:
+	kfree_skb(skb);
+	return -EINVAL;
+}
+
+int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy,
+					       struct wlan_objmgr_pdev *pdev,
+					       const void *data,
+					       int data_len)
+{
+	struct spectral_diag_stats spetcral_diag;
+	struct sk_buff *skb;
+
+	wlan_spectral_get_diag_stats(pdev, &spetcral_diag);
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 5 * sizeof(u64) +
+		NLA_HDRLEN + NLMSG_HDRLEN);
+	if (!skb) {
+		qdf_print(" reply skb alloc failed");
+		return -ENOMEM;
+	}
+
+	if (wlan_cfg80211_nla_put_u64(
+		skb,
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH,
+		spetcral_diag.spectral_mismatch) ||
+	    wlan_cfg80211_nla_put_u64(
+		skb,
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN,
+		spetcral_diag.spectral_sec80_sfft_insufflen) ||
+	    wlan_cfg80211_nla_put_u64(
+		skb,
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT,
+		spetcral_diag.spectral_no_sec80_sfft) ||
+	    wlan_cfg80211_nla_put_u64(
+		skb,
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH,
+		spetcral_diag.spectral_vhtseg1id_mismatch) ||
+	    wlan_cfg80211_nla_put_u64(
+		skb,
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH,
+		spetcral_diag.spectral_vhtseg2id_mismatch)) {
+		kfree_skb(skb);
+		return -EINVAL;
+	}
+	cfg80211_vendor_cmd_reply(skb);
+
+	return 0;
+}
+
+int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy,
+					   struct wlan_objmgr_pdev *pdev,
+					   const void *data,
+					   int data_len)
+{
+	struct spectral_scan_state sscan_state;
+	struct sk_buff *skb;
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 2 * sizeof(u32) +
+		NLA_HDRLEN + NLMSG_HDRLEN);
+	if (!skb) {
+		qdf_print(" reply skb alloc failed");
+		return -ENOMEM;
+	}
+
+	wlan_spectral_scan_get_status(pdev, &sscan_state);
+
+	if (sscan_state.is_enabled)
+		if (nla_put_flag(
+			skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED))
+			goto fail;
+
+	if (sscan_state.is_active)
+		if (nla_put_flag(
+			skb,
+			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE))
+			goto fail;
+	cfg80211_vendor_cmd_reply(skb);
+	return 0;
+
+fail:
+	kfree_skb(skb);
+	return -EINVAL;
+}
diff --git a/spectral/Kbuild b/spectral/Kbuild
index eac23f4..6d7469e 100644
--- a/spectral/Kbuild
+++ b/spectral/Kbuild
@@ -23,6 +23,8 @@
 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
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/os_if/linux/spectral/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/os_if/linux/scan/inc
 
 ifeq ($(WLAN_CONV_CRYPTO_SUPPORTED), 1)
 INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/crypto/inc
@@ -181,7 +183,8 @@
                       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
+                      core/spectral_module.o \
+                      $(DEPTH)/cmn_dev/os_if/linux/spectral/src/wlan_cfg80211_spectral.o
 
 qca_spectral-objs +=  ${SPECTRAL_CMN_OBJS} \
                       ${SPECTRAL_TIF_OBJS} \
diff --git a/spectral/core/spectral_common.c b/spectral/core/spectral_common.c
index bb0eaf6..07d228f 100644
--- a/spectral/core/spectral_common.c
+++ b/spectral/core/spectral_common.c
@@ -25,6 +25,7 @@
 #include <osif_private.h>
 #include <wlan_spectral_public_structs.h>
 #include <wlan_mlme_dispatcher.h>
+#include <wlan_cfg80211_spectral.h>
 
 /**
  * spectral_get_vdev() - Get pointer to vdev to be used for Spectral
@@ -64,6 +65,34 @@
 	return vdev;
 }
 
+static void spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev *pdev)
+{
+	wlan_cfg80211_register_spectral_cmd_handler(
+			pdev,
+			SPECTRAL_SCAN_START_HANDLER_IDX,
+			wlan_cfg80211_spectral_scan_config_and_start);
+	wlan_cfg80211_register_spectral_cmd_handler(
+			pdev,
+			SPECTRAL_SCAN_STOP_HANDLER_IDX,
+			wlan_cfg80211_spectral_scan_stop);
+	wlan_cfg80211_register_spectral_cmd_handler(
+			pdev,
+			SPECTRAL_SCAN_GET_CONFIG_HANDLER_IDX,
+			wlan_cfg80211_spectral_scan_get_config);
+	wlan_cfg80211_register_spectral_cmd_handler(
+			pdev,
+			SPECTRAL_SCAN_GET_DIAG_STATS_HANDLER_IDX,
+			wlan_cfg80211_spectral_scan_get_diag_stats);
+	wlan_cfg80211_register_spectral_cmd_handler(
+			pdev,
+			SPECTRAL_SCAN_GET_CAP_HANDLER_IDX,
+			wlan_cfg80211_spectral_scan_get_cap);
+	wlan_cfg80211_register_spectral_cmd_handler(
+			pdev,
+			SPECTRAL_SCAN_GET_STATUS_HANDLER_IDX,
+			wlan_cfg80211_spectral_scan_get_status);
+}
+
 int spectral_control_cmn(
 	struct wlan_objmgr_pdev *pdev,
 	 u_int id,
@@ -348,6 +377,18 @@
 	}
 	break;
 
+case SPECTRAL_GET_DEBUG_LEVEL:
+	{
+		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_get_debug_level(pdev);
+	}
+	break;
+
 	case SPECTRAL_ACTIVATE_SCAN:
 	{
 		sc->sptrlc_start_spectral_scan(pdev);
@@ -511,6 +552,8 @@
 
 	qdf_mem_zero(ps, sizeof(struct pdev_spectral));
 	ps->psptrl_pdev = pdev;
+
+	spectral_register_cfg80211_handlers(pdev);
 	if (sc->sptrlc_pdev_spectral_init) {
 		target_handle = sc->sptrlc_pdev_spectral_init(pdev);
 		if (!target_handle) {
diff --git a/spectral/core/spectral_module.c b/spectral/core/spectral_module.c
index ce42e63..2283f05 100644
--- a/spectral/core/spectral_module.c
+++ b/spectral/core/spectral_module.c
@@ -22,6 +22,8 @@
 #include <qdf_types.h>
 #include<wlan_global_lmac_if_api.h>
 
+MODULE_LICENSE("Dual BSD/GPL");
+
 /**
  * spectral_init_module() - Initialize Spectral module
  *
diff --git a/spectral/dispatcher/inc/spectral_ioctl.h b/spectral/dispatcher/inc/spectral_ioctl.h
new file mode 100644
index 0000000..66988ad
--- /dev/null
+++ b/spectral/dispatcher/inc/spectral_ioctl.h
@@ -0,0 +1,97 @@
+/*
+ * 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 _SPECTRAL_IOCTL_H_
+#define _SPECTRAL_IOCTL_H_
+
+#include <wlan_dfs_ioctl.h>
+
+/*
+ * ioctl defines
+ */
+
+#define SPECTRAL_SET_CONFIG              (DFS_LAST_IOCTL + 1)
+#define SPECTRAL_GET_CONFIG              (DFS_LAST_IOCTL + 2)
+#define SPECTRAL_SHOW_INTERFERENCE       (DFS_LAST_IOCTL + 3)
+#define SPECTRAL_ENABLE_SCAN             (DFS_LAST_IOCTL + 4)
+#define SPECTRAL_DISABLE_SCAN            (DFS_LAST_IOCTL + 5)
+#define SPECTRAL_ACTIVATE_SCAN           (DFS_LAST_IOCTL + 6)
+#define SPECTRAL_STOP_SCAN               (DFS_LAST_IOCTL + 7)
+#define SPECTRAL_SET_DEBUG_LEVEL         (DFS_LAST_IOCTL + 8)
+#define SPECTRAL_IS_ACTIVE               (DFS_LAST_IOCTL + 9)
+#define SPECTRAL_IS_ENABLED              (DFS_LAST_IOCTL + 10)
+#define SPECTRAL_CLASSIFY_SCAN           (DFS_LAST_IOCTL + 11)
+#define SPECTRAL_GET_CLASSIFIER_CONFIG   (DFS_LAST_IOCTL + 12)
+#define SPECTRAL_EACS                    (DFS_LAST_IOCTL + 13)
+#define SPECTRAL_ACTIVATE_FULL_SCAN      (DFS_LAST_IOCTL + 14)
+#define SPECTRAL_STOP_FULL_SCAN          (DFS_LAST_IOCTL + 15)
+#define SPECTRAL_GET_CAPABILITY_INFO     (DFS_LAST_IOCTL + 16)
+#define SPECTRAL_GET_DIAG_STATS          (DFS_LAST_IOCTL + 17)
+#define SPECTRAL_GET_CHAN_WIDTH          (DFS_LAST_IOCTL + 18)
+#define SPECTRAL_GET_CHANINFO            (DFS_LAST_IOCTL + 19)
+#define SPECTRAL_CLEAR_CHANINFO          (DFS_LAST_IOCTL + 20)
+#define SPECTRAL_SET_ICM_ACTIVE          (DFS_LAST_IOCTL + 21)
+#define SPECTRAL_GET_NOMINAL_NOISEFLOOR  (DFS_LAST_IOCTL + 22)
+#define SPECTRAL_GET_DEBUG_LEVEL         (DFS_LAST_IOCTL + 23)
+
+/*
+ * 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)
+
+struct spectral_ioctl_params {
+	int16_t   spectral_fft_period;
+	int16_t   pectral_period;
+	int16_t   spectral_count;
+	u_int16_t spectral_short_report;
+	u_int16_t spectral_pri;
+};
+
+struct ath_spectral_caps {
+	u_int8_t phydiag_cap;
+	u_int8_t radar_cap;
+	u_int8_t spectral_cap;
+	u_int8_t advncd_spectral_cap;
+};
+
+#define SPECTRAL_IOCTL_PARAM_NOVAL (65535)
+
+#endif
diff --git a/spectral/dispatcher/inc/wlan_spectral_public_structs.h b/spectral/dispatcher/inc/wlan_spectral_public_structs.h
index 9ba5b60..15963d7 100644
--- a/spectral/dispatcher/inc/wlan_spectral_public_structs.h
+++ b/spectral/dispatcher/inc/wlan_spectral_public_structs.h
@@ -124,6 +124,16 @@
 #define SPECTRAL_SCAN_SHORT_REPORT_DEFAULT     (1)
 #define SPECTRAL_SCAN_FFT_PERIOD_DEFAULT       (1)
 
+enum wlan_cfg80211_spectral_vendorcmd_handler_idx {
+	SPECTRAL_SCAN_START_HANDLER_IDX,
+	SPECTRAL_SCAN_STOP_HANDLER_IDX,
+	SPECTRAL_SCAN_GET_CONFIG_HANDLER_IDX,
+	SPECTRAL_SCAN_GET_DIAG_STATS_HANDLER_IDX,
+	SPECTRAL_SCAN_GET_CAP_HANDLER_IDX,
+	SPECTRAL_SCAN_GET_STATUS_HANDLER_IDX,
+	SPECTRAL_SCAN_VENDOR_CMD_HANDLER_MAX,
+};
+
 /**
  * enum spectral_debug - Spectral debug level
  * @ATH_DEBUG_SPECTRAL:  Minimal SPECTRAL debug
@@ -296,12 +306,15 @@
 };
 
 /**
- * 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_scan_state - State of spectral scan
+ * @is_active:  Is spectral scan active
+ * @is_enabled: Is spectral scan enabled
  */
+struct spectral_scan_state {
+	uint8_t is_active;
+	uint8_t is_enabled;
+};
+
 typedef enum _dcs_int_type {
 	SPECTRAL_DCS_INT_NONE,
 	SPECTRAL_DCS_INT_CW,
diff --git a/target_if/spectral/target_if_spectral.c b/target_if/spectral/target_if_spectral.c
index 416a918..089451a 100644
--- a/target_if/spectral/target_if_spectral.c
+++ b/target_if/spectral/target_if_spectral.c
@@ -2363,8 +2363,7 @@
  */
 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;
+	return spectral_debug_level;
 }
 
 /**