qcacld-3.0: Featurize some vendor commands

Featurize some vendor commands to compile out when not needed.

Change-Id: I6757b5764930efbd9cd1c7ab74e5990e96267421
CRs-Fixed: 2270461
diff --git a/Kbuild b/Kbuild
index ce0e1d0..1f803ef 100644
--- a/Kbuild
+++ b/Kbuild
@@ -166,6 +166,46 @@
 HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_packet_filter.o
 endif
 
+ifeq ($(CONFIG_FEATURE_RSSI_MONITOR), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_rssi_monitor.o
+endif
+
+ifeq ($(CONFIG_FEATURE_BSS_TRANSITION), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_bss_transition.o
+endif
+
+ifeq ($(CONFIG_FEATURE_STATION_INFO), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_station_info.o
+endif
+
+ifeq ($(CONFIG_FEATURE_TX_POWER), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tx_power.o
+endif
+
+ifeq ($(CONFIG_FEATURE_OTA_TEST), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_ota_test.o
+endif
+
+ifeq ($(CONFIG_FEATURE_ACTIVE_TOS), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_active_tos.o
+endif
+
+ifeq ($(CONFIG_FEATURE_SAR_LIMITS), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sar_limits.o
+endif
+
+ifeq ($(CONFIG_FEATURE_CONCURRENCY_MATRIX), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_concurrency_matrix.o
+endif
+
+ifeq ($(CONFIG_FEATURE_SAP_COND_CHAN_SWITCH), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sap_cond_chan_switch.o
+endif
+
+ifeq ($(CONFIG_FEATURE_P2P_LISTEN_OFFLOAD), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_p2p_listen_offload.o
+endif
+
 ########### Driver Synchronization Core (DSC) ###########
 DSC_DIR := components/dsc
 DSC_INC_DIR := $(DSC_DIR)/inc
@@ -2093,12 +2133,23 @@
 cppflags-y += -DQCA_WIFI_QCA6290_11AX
 endif
 
-
 cppflags-$(CONFIG_WLAN_FEATURE_11AX) += -DWLAN_FEATURE_11AX
 cppflags-$(CONFIG_WLAN_FEATURE_11AX) += -DWLAN_FEATURE_11AX_BSS_COLOR
 
 cppflags-$(CONFIG_LITHIUM) += -DFEATURE_AST
 
+# Vendor Commands
+cppflags-$(CONFIG_FEATURE_RSSI_MONITOR) += -DFEATURE_RSSI_MONITOR
+cppflags-$(CONFIG_FEATURE_BSS_TRANSITION) += -DFEATURE_BSS_TRANSITION
+cppflags-$(CONFIG_FEATURE_STATION_INFO) += -DFEATURE_STATION_INFO
+cppflags-$(CONFIG_FEATURE_TX_POWER) += -DFEATURE_TX_POWER
+cppflags-$(CONFIG_FEATURE_OTA_TEST) += -DFEATURE_OTA_TEST
+cppflags-$(CONFIG_FEATURE_ACTIVE_TOS) += -DFEATURE_ACTIVE_TOS
+cppflags-$(CONFIG_FEATURE_SAR_LIMITS) += -DFEATURE_SAR_LIMITS
+cppflags-$(CONFIG_FEATURE_CONCURRENCY_MATRIX) += -DFEATURE_CONCURRENCY_MATRIX
+cppflags-$(CONFIG_FEATURE_SAP_COND_CHAN_SWITCH) += -DFEATURE_SAP_COND_CHAN_SWITCH
+cppflags-$(CONFIG_FEATURE_P2P_LISTEN_OFFLOAD) += -DFEATURE_P2P_LISTEN_OFFLOAD
+
 # Dummy flag for WIN/MCL converged data path compilation
 cppflags-y += -DDP_PRINT_ENABLE=0
 cppflags-y += -DATH_SUPPORT_WRAP=0
diff --git a/configs/default_defconfig b/configs/default_defconfig
index fa1166d..35368f9 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -573,6 +573,18 @@
 CONFIG_WLAN_FEATURE_TWT := y
 CONFIG_WLAN_FEATURE_BMI := y
 
+#Flags to enable/disable vendor commands
+CONFIG_FEATURE_RSSI_MONITOR := y
+CONFIG_FEATURE_BSS_TRANSITION := y
+CONFIG_FEATURE_STATION_INFO := y
+CONFIG_FEATURE_TX_POWER := y
+CONFIG_FEATURE_OTA_TEST := y
+CONFIG_FEATURE_ACTIVE_TOS := y
+CONFIG_FEATURE_SAR_LIMITS := y
+CONFIG_FEATURE_CONCURRENCY_MATRIX := y
+CONFIG_FEATURE_SAP_COND_CHAN_SWITCH := y
+CONFIG_FEATURE_P2P_LISTEN_OFFLOAD := y
+
 ifeq ($(CONFIG_HELIUMPLUS), y)
 ifneq ($(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE), y)
 CONFIG_ENABLE_DEBUG_ADDRESS_MARKING := y
diff --git a/configs/genoa.common b/configs/genoa.common
index 7868788..6eed4ba 100644
--- a/configs/genoa.common
+++ b/configs/genoa.common
@@ -3,7 +3,7 @@
 #features not required for GENOA IOT, compilation errors are there.
 CONFIG_SUPPORT_11AX := y
 CONFIG_160MHZ_SUPPORT := y
-CONFIG_FEATURE_STATS_EXT := y
+CONFIG_FEATURE_STATS_EXT := n
 CONFIG_QCA_IBSS_SUPPORT := y
 
 #required features
@@ -114,6 +114,18 @@
 CONFIG_CHNL_MATRIX_RESTRICTION := n
 CONFIG_WLAN_FEATURE_BMI := n
 
+#Flags to enable/disable vendor commands
+CONFIG_FEATURE_RSSI_MONITOR := n
+CONFIG_FEATURE_BSS_TRANSITION := n
+CONFIG_FEATURE_STATION_INFO := n
+CONFIG_FEATURE_TX_POWER := n
+CONFIG_FEATURE_OTA_TEST := n
+CONFIG_FEATURE_ACTIVE_TOS := n
+CONFIG_FEATURE_SAR_LIMITS := y
+CONFIG_FEATURE_CONCURRENCY_MATRIX := n
+CONFIG_FEATURE_SAP_COND_CHAN_SWITCH := n
+CONFIG_FEATURE_P2P_LISTEN_OFFLOAD := n
+
 ifeq ($(CONFIG_ARCH_SDM845), y)
 ifeq ($(CONFIG_IPA_OFFLOAD), y)
 CONFIG_ENABLE_SMMU_S1_TRANSLATION := y
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 946cd13..8be54ed 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1632,36 +1632,6 @@
 };
 
 /**
- * tos - Type of service requested by the application
- * TOS_BK: Back ground traffic
- * TOS_BE: Best effort traffic
- * TOS_VI: Video traffic
- * TOS_VO: Voice traffic
- */
-enum tos {
-	TOS_BK = 0,
-	TOS_BE = 1,
-	TOS_VI = 2,
-	TOS_VO = 3,
-};
-
-#define HDD_AC_BK_BIT                   1
-#define HDD_AC_BE_BIT                   2
-#define HDD_AC_VI_BIT                   4
-#define HDD_AC_VO_BIT                   8
-
-#define HDD_MAX_OFF_CHAN_TIME_FOR_VO    20
-#define HDD_MAX_OFF_CHAN_TIME_FOR_VI    20
-#define HDD_MAX_OFF_CHAN_TIME_FOR_BE    40
-#define HDD_MAX_OFF_CHAN_TIME_FOR_BK    40
-
-#define HDD_MAX_AC                      4
-#define HDD_MAX_OFF_CHAN_ENTRIES        2
-
-#define HDD_AC_BIT_INDX                 0
-#define HDD_DWELL_TIME_INDX             1
-
-/**
  * enum RX_OFFLOAD - Receive offload modes
  * @CFG_LRO_ENABLED: Large Rx offload
  * @CFG_GRO_ENABLED: Generic Rx Offload
@@ -2932,22 +2902,6 @@
 bool hdd_set_connection_in_progress(bool value);
 
 /**
- * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
- * @ap_adapter: adapter
- * @channel_count: valid channel count
- * @channel_list: valid channel list
- * @band: frequency band
- *
- * This API returns valid channel list for SAP after removing nol and
- * channel which lies outside of configuration.
- *
- * Return: Zero on success, non-zero on failure
- */
-int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
-				       uint32_t *channel_count,
-				       uint8_t *channel_list,
-				       enum band_info band);
-/**
  * wlan_hdd_init_chan_info() - initialize channel info variables
  * @hdd_ctx: hdd ctx
  *
@@ -3212,19 +3166,6 @@
 void hdd_set_rx_mode_rps(bool enable);
 
 /**
- * hdd_set_limit_off_chan_for_tos() - set limit off-chan command parameters
- * @adapter: pointer adapter context
- * @tos: type of service
- * @status: status of the traffic (active/inactive)
- *
- * This function updates the limit off-channel command parameters to WMA
- *
- * Return: 0 on success or non zero value on failure
- */
-int hdd_set_limit_off_chan_for_tos(struct hdd_adapter *adapter, enum tos tos,
-		bool is_tos_active);
-
-/**
  * hdd_drv_ops_inactivity_handler() - Timeout handler for driver ops
  * inactivity timer
  *
diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h
index 876ff19..9796b28 100644
--- a/core/hdd/inc/wlan_hdd_p2p.h
+++ b/core/hdd/inc/wlan_hdd_p2p.h
@@ -124,30 +124,6 @@
 	struct p2p_ps_config *ps_config);
 
 /**
- * wlan_hdd_listen_offload_start() - hdd set listen offload start
- * @adapter:  adapter context
- * @params:   listen offload parameters
- *
- * This function sets listen offload start parameters.
- *
- * Return: 0 - success
- *    others - failure
- */
-int wlan_hdd_listen_offload_start(struct hdd_adapter *adapter,
-	struct sir_p2p_lo_start *params);
-
-/**
- * wlan_hdd_listen_offload_stop() - hdd set listen offload stop
- * @adapter:  adapter context
- *
- * This function sets listen offload stop parameters.
- *
- * Return: 0 - success
- *    others - failure
- */
-int wlan_hdd_listen_offload_stop(struct hdd_adapter *adapter);
-
-/**
  * wlan_hdd_set_mas() - Function to set MAS value to FW
  * @adapter:            Pointer to HDD adapter
  * @mas_value:          0-Disable, 1-Enable MAS
diff --git a/core/hdd/src/wlan_hdd_active_tos.c b/core/hdd/src/wlan_hdd_active_tos.c
new file mode 100644
index 0000000..7884835
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_active_tos.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_active_tos.c
+ *
+ * WLAN active tos functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <wlan_hdd_active_tos.h>
+
+/**
+ * tos - Type of service requested by the application
+ * TOS_BK: Back ground traffic
+ * TOS_BE: Best effort traffic
+ * TOS_VI: Video traffic
+ * TOS_VO: Voice traffic
+ */
+enum tos {
+	TOS_BK = 0,
+	TOS_BE = 1,
+	TOS_VI = 2,
+	TOS_VO = 3,
+};
+
+#define HDD_AC_BK_BIT                   1
+#define HDD_AC_BE_BIT                   2
+#define HDD_AC_VI_BIT                   4
+#define HDD_AC_VO_BIT                   8
+
+#define HDD_MAX_OFF_CHAN_TIME_FOR_VO    20
+#define HDD_MAX_OFF_CHAN_TIME_FOR_VI    20
+#define HDD_MAX_OFF_CHAN_TIME_FOR_BE    40
+#define HDD_MAX_OFF_CHAN_TIME_FOR_BK    40
+
+#define HDD_MAX_AC                      4
+#define HDD_MAX_OFF_CHAN_ENTRIES        2
+
+#define HDD_AC_BIT_INDX                 0
+#define HDD_DWELL_TIME_INDX             1
+
+static int limit_off_chan_tbl[HDD_MAX_AC][HDD_MAX_OFF_CHAN_ENTRIES] = {
+		{ HDD_AC_BK_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_BK },
+		{ HDD_AC_BE_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_BE },
+		{ HDD_AC_VI_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_VI },
+		{ HDD_AC_VO_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_VO },
+};
+
+static const struct nla_policy
+wlan_hdd_set_limit_off_channel_param_policy
+[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS] = {.type = NLA_U8 },
+	[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START] = {.type = NLA_U8 },
+};
+
+/**
+ * hdd_set_limit_off_chan_for_tos() - set limit off-channel command parameters
+ * @adapter: HDD adapter
+ * @tos: type of service
+ * @is_tos_active: status of the traffic
+ *
+ * Return: 0 on success and non zero value on failure
+ */
+
+static int
+hdd_set_limit_off_chan_for_tos(struct hdd_adapter *adapter,
+			       enum tos tos,
+			       bool is_tos_active)
+{
+	int ac_bit;
+	struct hdd_context *hdd_ctx;
+	uint32_t max_off_chan_time = 0;
+	QDF_STATUS status;
+	int ret;
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	ret = wlan_hdd_validate_context(hdd_ctx);
+
+	if (ret < 0)
+		return ret;
+
+	ac_bit = limit_off_chan_tbl[tos][HDD_AC_BIT_INDX];
+
+	if (is_tos_active)
+		adapter->active_ac |= ac_bit;
+	else
+		adapter->active_ac &= ~ac_bit;
+
+	if (adapter->active_ac) {
+		if (adapter->active_ac & HDD_AC_VO_BIT) {
+			max_off_chan_time =
+				limit_off_chan_tbl[TOS_VO][HDD_DWELL_TIME_INDX];
+			policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
+							    PM_LATENCY);
+		} else if (adapter->active_ac & HDD_AC_VI_BIT) {
+			max_off_chan_time =
+				limit_off_chan_tbl[TOS_VI][HDD_DWELL_TIME_INDX];
+			policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
+							    PM_LATENCY);
+		} else {
+			/*ignore this command if only BE/BK is active */
+			is_tos_active = false;
+			policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
+					hdd_ctx->config->conc_system_pref);
+		}
+	} else {
+		/* No active tos */
+		policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
+				hdd_ctx->config->conc_system_pref);
+	}
+
+	status = sme_send_limit_off_channel_params(hdd_ctx->mac_handle,
+					adapter->session_id,
+					is_tos_active,
+					max_off_chan_time,
+					hdd_ctx->config->nRestTimeConc,
+					true);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		hdd_err("failed to set limit off chan params");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * __wlan_hdd_cfg80211_set_limit_offchan_param() - set limit off-channel cmd
+ * parameters
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to limit off-channel command parameters.
+ * @data_len: the length in byte of  limit off-channel command parameters.
+ *
+ * This is called when application wants to limit the off channel time due to
+ * active voip traffic.
+ *
+ * Return: An error code or 0 on success.
+ */
+static int
+__wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data,
+					    int data_len)
+{
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX + 1];
+	struct net_device   *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	int ret = 0;
+	uint8_t tos;
+	uint8_t tos_status;
+
+	hdd_enter();
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret < 0)
+		return ret;
+
+	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX,
+				 data, data_len,
+				 wlan_hdd_set_limit_off_channel_param_policy)) {
+		hdd_err("Invalid ATTR");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS]) {
+		hdd_err("attr tos failed");
+		goto fail;
+	}
+
+	tos = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS]);
+	if (tos >= HDD_MAX_AC) {
+		hdd_err("tos value %d exceeded Max value %d",
+			tos, HDD_MAX_AC);
+		goto fail;
+	}
+	hdd_debug("tos %d", tos);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START]) {
+		hdd_err("attr tos active failed");
+		goto fail;
+	}
+	tos_status = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START]);
+
+	hdd_debug("tos status %d", tos_status);
+	ret = hdd_set_limit_off_chan_for_tos(adapter, tos, tos_status);
+
+fail:
+	return ret;
+}
+
+int wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
+					      struct wireless_dev *wdev,
+					      const void *data, int data_len)
+
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_set_limit_offchan_param(wiphy, wdev, data,
+							  data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_active_tos.h b/core/hdd/src/wlan_hdd_active_tos.h
new file mode 100644
index 0000000..80f39c4
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_active_tos.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_ACTIVE_TOS_H
+#define __WLAN_HDD_ACTIVE_TOS_H
+
+/**
+ * DOC: wlan_hdd_active_tos_h
+ *
+ * WLAN Host Device Driver ACTIVE TOS API specification
+ */
+
+#ifdef FEATURE_ACTIVE_TOS
+/**
+ * wlan_hdd_cfg80211_set_limit_offchan_param() - set limit off-channel cmd
+ * parameters
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to limit off-channel command parameters.
+ * @data_len: the length in byte of  limit off-channel command parameters.
+ *
+ * This is called when application wants to limit the off channel time due to
+ * active voip traffic.
+ *
+ * Return: An error code or 0 on success.
+ */
+int wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
+					      struct wireless_dev *wdev,
+					      const void *data, int data_len);
+
+#define FEATURE_ACTIVE_TOS_VENDOR_COMMANDS			\
+{								\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,		\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |			\
+		WIPHY_VENDOR_CMD_NEED_NETDEV |			\
+		WIPHY_VENDOR_CMD_NEED_RUNNING,			\
+	.doit = wlan_hdd_cfg80211_set_limit_offchan_param	\
+},
+#else /* FEATURE_ACTIVE_TOS */
+#define FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
+#endif /* FEATURE_ACTIVE_TOS */
+
+#endif /* __WLAN_HDD_ACTIVE_TOS_H */
+
diff --git a/core/hdd/src/wlan_hdd_bss_transition.c b/core/hdd/src/wlan_hdd_bss_transition.c
new file mode 100644
index 0000000..fd4b012
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_bss_transition.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_bss_transition.c
+ *
+ * WLAN bss transition functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <wlan_hdd_bss_transition.h>
+
+/**
+ * wlan_hdd_is_bt_in_progress() - check if bt activity is in progress
+ * @hdd_ctx : HDD context
+ *
+ * Return: true if BT activity is in progress else false
+ */
+static bool wlan_hdd_is_bt_in_progress(struct hdd_context *hdd_ctx)
+{
+	if (hdd_ctx->bt_a2dp_active || hdd_ctx->bt_vo_active)
+		return true;
+
+	return false;
+}
+
+/**
+ * wlan_hdd_fill_btm_resp() - Fill bss candidate response buffer
+ * @reply_skb : pointer to reply_skb
+ * @info : bss candidate information
+ * @index : attribute type index for nla_next_start()
+ *
+ * Return : 0 on success and errno on failure
+ */
+static int wlan_hdd_fill_btm_resp(struct sk_buff *reply_skb,
+				  struct bss_candidate_info *info,
+				  int index)
+{
+	struct nlattr *attr;
+
+	attr = nla_nest_start(reply_skb, index);
+	if (!attr) {
+		hdd_err("nla_nest_start failed");
+		kfree_skb(reply_skb);
+		return -EINVAL;
+	}
+
+	if (nla_put(reply_skb,
+		  QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID,
+		  ETH_ALEN, info->bssid.bytes) ||
+	    nla_put_u32(reply_skb,
+		 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS,
+		 info->status)) {
+		hdd_err("nla_put failed");
+		kfree_skb(reply_skb);
+		return -EINVAL;
+	}
+
+	nla_nest_end(reply_skb, attr);
+
+	return 0;
+}
+
+/**
+ * __wlan_hdd_cfg80211_fetch_bss_transition_status() - fetch bss transition
+ * status
+ * @wiphy : WIPHY structure pointer
+ * @wdev : Wireless device structure pointer
+ * @data : Pointer to the data received
+ * @data_len : Length of the data received
+ *
+ * This function is used to fetch transition status for candidate bss. The
+ * transition status is either accept or reason for reject.
+ *
+ * Return : 0 on success and errno on failure
+ */
+static int
+__wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
+						struct wireless_dev *wdev,
+						const void *data, int data_len)
+{
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+	struct nlattr *tb_msg[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1];
+	uint8_t transition_reason;
+	struct nlattr *attr;
+	struct sk_buff *reply_skb;
+	int rem, j;
+	int ret;
+	bool is_bt_in_progress;
+	struct bss_candidate_info candidate_info[MAX_CANDIDATE_INFO];
+	uint16_t nof_candidates, i = 0;
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct hdd_station_ctx *hdd_sta_ctx =
+					WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+	mac_handle_t mac_handle;
+
+	const struct nla_policy
+	btm_params_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
+		[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON] = {
+							.type = NLA_U8},
+		[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO] = {
+							.type = NLA_NESTED},
+	};
+	const struct nla_policy
+	btm_cand_list_policy[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1]
+		= {[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID] = {
+						.len = QDF_MAC_ADDR_SIZE},
+		   [QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS] = {
+							.type = NLA_U32},
+		};
+
+	hdd_enter();
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EINVAL;
+	}
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (adapter->device_mode != QDF_STA_MODE ||
+	    hdd_sta_ctx->conn_info.connState != eConnectionState_Associated) {
+		hdd_err("Command is either not invoked for STA mode (device mode: %d) or STA is not associated (Connection state: %d)",
+			adapter->device_mode, hdd_sta_ctx->conn_info.connState);
+		return -EINVAL;
+	}
+
+	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
+				      data_len, btm_params_policy);
+	if (ret) {
+		hdd_err("Attribute parse failed");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON] ||
+	    !tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO]) {
+		hdd_err("Missing attributes");
+		return -EINVAL;
+	}
+
+	transition_reason = nla_get_u8(
+			    tb[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON]);
+
+	nla_for_each_nested(attr,
+			    tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO],
+			    rem) {
+		ret = wlan_cfg80211_nla_parse_nested(tb_msg,
+				    QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX,
+				    attr, btm_cand_list_policy);
+		if (ret) {
+			hdd_err("Attribute parse failed");
+			return -EINVAL;
+		}
+
+		if (!tb_msg[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]) {
+			hdd_err("Missing BSSID attribute");
+			return -EINVAL;
+		}
+
+		qdf_mem_copy((void *)candidate_info[i].bssid.bytes,
+			     nla_data(tb_msg[
+			     QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]),
+			     QDF_MAC_ADDR_SIZE);
+		i++;
+		if (i == MAX_CANDIDATE_INFO)
+			break;
+	}
+
+	/*
+	 * Determine status for each candidate and fill in the status field.
+	 * Also arrange the candidates in the order of preference.
+	 */
+	nof_candidates = i;
+
+	is_bt_in_progress = wlan_hdd_is_bt_in_progress(hdd_ctx);
+
+	mac_handle = hdd_ctx->mac_handle;
+	ret = sme_get_bss_transition_status(mac_handle, transition_reason,
+					    &hdd_sta_ctx->conn_info.bssId,
+					    candidate_info,
+					    nof_candidates,
+					    is_bt_in_progress);
+	if (ret)
+		return -EINVAL;
+
+	/* Prepare the reply and send it to userspace */
+	reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+			((QDF_MAC_ADDR_SIZE + sizeof(uint32_t)) *
+			 nof_candidates) + NLMSG_HDRLEN);
+	if (!reply_skb) {
+		hdd_err("reply buffer alloc failed");
+		return -ENOMEM;
+	}
+
+	attr = nla_nest_start(reply_skb,
+			      QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO);
+	if (!attr) {
+		hdd_err("nla_nest_start failed");
+		kfree_skb(reply_skb);
+		return -EINVAL;
+	}
+
+	/*
+	 * Order candidates as - accepted candidate list followed by rejected
+	 * candidate list
+	 */
+	for (i = 0, j = 0; i < nof_candidates; i++) {
+		/* copy accepted candidate list */
+		if (candidate_info[i].status == QCA_STATUS_ACCEPT) {
+			if (wlan_hdd_fill_btm_resp(reply_skb,
+						   &candidate_info[i], j))
+				return -EINVAL;
+			j++;
+		}
+	}
+	for (i = 0; i < nof_candidates; i++) {
+		/* copy rejected candidate list */
+		if (candidate_info[i].status != QCA_STATUS_ACCEPT) {
+			if (wlan_hdd_fill_btm_resp(reply_skb,
+						   &candidate_info[i], j))
+				return -EINVAL;
+			j++;
+		}
+	}
+	nla_nest_end(reply_skb, attr);
+
+	hdd_exit();
+
+	return cfg80211_vendor_cmd_reply(reply_skb);
+}
+
+int wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
+						  struct wireless_dev *wdev,
+						  const void *data,
+						  int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_fetch_bss_transition_status(wiphy, wdev,
+							      data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_bss_transition.h b/core/hdd/src/wlan_hdd_bss_transition.h
new file mode 100644
index 0000000..86ba247
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_bss_transition.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_BSS_TRANSITION_H
+#define __WLAN_HDD_BSS_TRANSITION_H
+
+/**
+ * DOC: wlan_hdd_bss_transition_h
+ *
+ * WLAN Host Device Driver BSS transition API specification
+ */
+
+#ifdef FEATURE_BSS_TRANSITION
+/**
+ * wlan_hdd_cfg80211_fetch_bss_transition_status() - fetch bss transition status
+ * @wiphy: WIPHY structure pointer
+ * @wdev: Wireless device structure pointer
+ * @data: Pointer to the data received
+ * @data_len: Length of the data received
+ *
+ * This function is used to fetch transition status for candidate bss. The
+ * transition status is either accept or reason for reject.
+ *
+ * Return: 0 on success and errno on failure
+ */
+int
+wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
+					      struct wireless_dev *wdev,
+					      const void *data, int data_len);
+
+#define FEATURE_BSS_TRANSITION_VENDOR_COMMANDS				\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd =							\
+		QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+		 WIPHY_VENDOR_CMD_NEED_NETDEV |				\
+		 WIPHY_VENDOR_CMD_NEED_RUNNING,				\
+	.doit = wlan_hdd_cfg80211_fetch_bss_transition_status		\
+},
+#else /* FEATURE_BSS_TRANSITION */
+#define FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
+#endif /* FEATURE_BSS_TRANSITION */
+
+#endif /* __WLAN_HDD_BSS_TRANSITION_H */
+
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 82e7538..e3d7bd2 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -107,6 +107,16 @@
 #include <wlan_cfg80211_mc_cp_stats.h>
 #include <wlan_cp_stats_mc_ucfg_api.h>
 #include "wlan_tdls_cfg_api.h"
+#include <wlan_hdd_bss_transition.h>
+#include <wlan_hdd_concurrency_matrix.h>
+#include <wlan_hdd_p2p_listen_offload.h>
+#include <wlan_hdd_rssi_monitor.h>
+#include <wlan_hdd_sap_cond_chan_switch.h>
+#include <wlan_hdd_station_info.h>
+#include <wlan_hdd_tx_power.h>
+#include <wlan_hdd_active_tos.h>
+#include <wlan_hdd_sar_limits.h>
+#include <wlan_hdd_ota_test.h>
 
 #define g_mode_rates_size (12)
 #define a_mode_rates_size (8)
@@ -160,10 +170,6 @@
 
 #define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
 			mode <= DFS_MODE_DEPRIORITIZE))
-
-#define MAX_TXPOWER_SCALE 4
-#define CDS_MAX_FEATURE_SET   8
-
 /*
  * Number of DPTRACE records to dump when a cfg80211 disconnect with reason
  * WLAN_REASON_DEAUTH_LEAVING DEAUTH is received from user-space.
@@ -1376,10 +1382,9 @@
 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
 	},
 #endif /* FEATURE_WLAN_EXTSCAN */
-	[QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
-		.vendor_id = QCA_NL80211_VENDOR_ID,
-		.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
-	},
+
+	FEATURE_RSSI_MONITOR_VENDOR_EVENTS
+
 #ifdef WLAN_FEATURE_TSF
 	[QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
 		.vendor_id = QCA_NL80211_VENDOR_ID,
@@ -2098,6 +2103,70 @@
 		freq_list[count] = cds_chan_to_freq(channel_list[count]);
 }
 
+/**
+ * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
+ * @ap_adapter: adapter
+ * @channel_count: valid channel count
+ * @channel_list: valid channel list
+ * @band: frequency band
+ *
+ * This API returns valid channel list for SAP after removing nol and
+ * channel which lies outside of configuration.
+ *
+ * Return: Zero on success, non-zero on failure
+ */
+static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
+					      uint32_t *channel_count,
+					      uint8_t *channel_list,
+					      enum band_info band)
+{
+	tsap_config_t *sap_config;
+	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
+	uint32_t chan_count;
+	uint8_t i;
+	QDF_STATUS status;
+	struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
+	uint8_t tmp_chan;
+
+	sap_config = &adapter->session.ap.sap_config;
+
+	status =
+		policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
+					   tmp_chan_list,
+					   &chan_count);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to get channel list");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < chan_count; i++) {
+		tmp_chan = tmp_chan_list[i];
+		if (*channel_count < QDF_MAX_NUM_CHAN) {
+			if ((band == BAND_2G) &&
+			    (WLAN_REG_IS_24GHZ_CH(tmp_chan)) &&
+			    (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
+				channel_list[*channel_count] = tmp_chan;
+				*channel_count += 1;
+			} else if ((band == BAND_5G) &&
+				(WLAN_REG_IS_5GHZ_CH(tmp_chan)) &&
+				(!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
+				channel_list[*channel_count] = tmp_chan;
+				*channel_count += 1;
+			}
+		} else {
+			break;
+		}
+	}
+
+	if (*channel_count == 0) {
+		hdd_err("no valid channel found");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
 				   uint8_t reason)
 {
@@ -3186,128 +3255,6 @@
 	return ret;
 }
 
-#define MAX_CONCURRENT_MATRIX \
-	QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX
-#define MATRIX_CONFIG_PARAM_SET_SIZE_MAX \
-	QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX
-static const struct nla_policy
-wlan_hdd_get_concurrency_matrix_policy[MAX_CONCURRENT_MATRIX + 1] = {
-	[MATRIX_CONFIG_PARAM_SET_SIZE_MAX] = {.type = NLA_U32},
-};
-
-/**
- * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
- * @wiphy: pointer phy adapter
- * @wdev: pointer to wireless device structure
- * @data: pointer to data buffer
- * @data_len: length of data
- *
- * This routine will give concurrency matrix
- *
- * Return: int status code
- */
-static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
-					 struct wireless_dev *wdev,
-					 const void *data,
-					 int data_len)
-{
-	uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
-	uint8_t i, feature_sets, max_feature_sets;
-	struct nlattr *tb[MAX_CONCURRENT_MATRIX + 1];
-	struct sk_buff *reply_skb;
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	int ret;
-
-	hdd_enter_dev(wdev->netdev);
-
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EPERM;
-	}
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	if (wlan_cfg80211_nla_parse(tb, MAX_CONCURRENT_MATRIX, data, data_len,
-				    wlan_hdd_get_concurrency_matrix_policy)) {
-		hdd_err("Invalid ATTR");
-		return -EINVAL;
-	}
-
-	/* Parse and fetch max feature set */
-	if (!tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
-		hdd_err("Attr max feature set size failed");
-		return -EINVAL;
-	}
-	max_feature_sets = nla_get_u32(tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
-	hdd_debug("Max feature set size: %d", max_feature_sets);
-
-	/* Fill feature combination matrix */
-	feature_sets = 0;
-	feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
-						WIFI_FEATURE_P2P;
-	feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
-						WIFI_FEATURE_NAN;
-	/* Add more feature combinations here */
-
-	feature_sets = QDF_MIN(feature_sets, max_feature_sets);
-	hdd_debug("Number of feature sets: %d", feature_sets);
-	hdd_debug("Feature set matrix");
-	for (i = 0; i < feature_sets; i++)
-		hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
-
-	reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
-			sizeof(u32) * feature_sets + NLMSG_HDRLEN);
-	if (!reply_skb) {
-		hdd_err("Feature set matrix: buffer alloc fail");
-		return -ENOMEM;
-	}
-
-	if (nla_put_u32(reply_skb,
-			QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
-			feature_sets) ||
-	    nla_put(reply_skb,
-		    QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
-		    sizeof(u32) * feature_sets,
-		    feature_set_matrix)) {
-		hdd_err("nla put fail");
-		kfree_skb(reply_skb);
-		return -EINVAL;
-	}
-	return cfg80211_vendor_cmd_reply(reply_skb);
-}
-
-#undef MAX_CONCURRENT_MATRIX
-#undef MATRIX_CONFIG_PARAM_SET_SIZE_MAX
-
-/**
- * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
- * @wiphy:   pointer to wireless wiphy structure.
- * @wdev:    pointer to wireless_dev structure.
- * @data:    Pointer to the data to be passed via vendor interface
- * @data_len:Length of the data to be passed
- *
- * Retrieves the concurrency feature set matrix
- *
- * Return: 0 on success, negative errno on failure
- */
-static int
-wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
-				       struct wireless_dev *wdev,
-				       const void *data,
-				       int data_len)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
-							data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
 /**
  * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
  * @feature_flags: pointer to the byte array of features.
@@ -4393,575 +4340,6 @@
 	return ret;
 }
 
-/*
- * define short names for the global vendor params
- * used by __wlan_hdd_cfg80211_get_station_cmd()
- */
-#define STATION_INVALID \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
-#define STATION_INFO \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
-#define STATION_ASSOC_FAIL_REASON \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
-#define STATION_REMOTE \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE
-#define STATION_MAX \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
-
-/* define short names for get station info attributes */
-#define LINK_INFO_STANDARD_NL80211_ATTR \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
-#define AP_INFO_STANDARD_NL80211_ATTR \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR
-#define INFO_ROAM_COUNT \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT
-#define INFO_AKM \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
-#define WLAN802_11_MODE \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE
-#define AP_INFO_HS20_INDICATION \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION
-#define HT_OPERATION \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
-#define VHT_OPERATION \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
-#define INFO_ASSOC_FAIL_REASON \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON
-#define REMOTE_MAX_PHY_RATE \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE
-#define REMOTE_TX_PACKETS \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS
-#define REMOTE_TX_BYTES \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES
-#define REMOTE_RX_PACKETS \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS
-#define REMOTE_RX_BYTES \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BYTES
-#define REMOTE_LAST_TX_RATE \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_TX_RATE
-#define REMOTE_LAST_RX_RATE \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE
-#define REMOTE_WMM \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_WMM
-#define REMOTE_SUPPORTED_MODE \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE
-#define REMOTE_AMPDU \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AMPDU
-#define REMOTE_TX_STBC \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_STBC
-#define REMOTE_RX_STBC \
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC
-#define REMOTE_CH_WIDTH\
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH
-#define REMOTE_SGI_ENABLE\
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
-	#define REMOTE_PAD\
-	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD
-#endif
-
-static const struct nla_policy
-hdd_get_station_policy[STATION_MAX + 1] = {
-	[STATION_INFO] = {.type = NLA_FLAG},
-	[STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
-	[STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
-};
-
-#ifdef QCA_SUPPORT_CP_STATS
-static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
-				  uint32_t *congestion)
-{
-	QDF_STATUS status;
-	struct cca_stats cca_stats;
-
-	status = ucfg_mc_cp_stats_cca_stats_get(adapter->hdd_vdev, &cca_stats);
-	if (QDF_IS_STATUS_ERROR(status))
-		return -EINVAL;
-
-	*congestion = cca_stats.congestion;
-	return 0;
-}
-#else
-static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
-				  uint32_t *congestion)
-{
-	struct hdd_station_ctx *hdd_sta_ctx;
-
-	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
-	*congestion = hdd_sta_ctx->conn_info.cca;
-	return 0;
-}
-#endif
-
-/**
- * hdd_get_station_assoc_fail() - Handle get station assoc fail
- * @hdd_ctx: HDD context within host driver
- * @wdev: wireless device
- *
- * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
- * Validate cmd attributes and send the station info to upper layers.
- *
- * Return: Success(0) or reason code for failure
- */
-static int hdd_get_station_assoc_fail(struct hdd_context *hdd_ctx,
-						 struct hdd_adapter *adapter)
-{
-	struct sk_buff *skb = NULL;
-	uint32_t nl_buf_len;
-	struct hdd_station_ctx *hdd_sta_ctx;
-	uint32_t congestion;
-
-	nl_buf_len = NLMSG_HDRLEN;
-	nl_buf_len += sizeof(uint32_t);
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
-
-	if (!skb) {
-		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
-		return -ENOMEM;
-	}
-
-	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
-
-	if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
-			hdd_sta_ctx->conn_info.assoc_status_code)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-
-	if (hdd_get_sta_congestion(adapter, &congestion))
-		congestion = 0;
-
-	hdd_info("congestion:%d", congestion);
-	if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
-			congestion)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-
-	return cfg80211_vendor_cmd_reply(skb);
-fail:
-	if (skb)
-		kfree_skb(skb);
-	return -EINVAL;
-}
-
-/**
- * hdd_map_auth_type() - transform auth type specific to
- * vendor command
- * @auth_type: csr auth type
- *
- * Return: Success(0) or reason code for failure
- */
-static int hdd_convert_auth_type(uint32_t auth_type)
-{
-	uint32_t ret_val;
-
-	switch (auth_type) {
-	case eCSR_AUTH_TYPE_OPEN_SYSTEM:
-		ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
-		break;
-	case eCSR_AUTH_TYPE_SHARED_KEY:
-		ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
-		break;
-	case eCSR_AUTH_TYPE_WPA:
-		ret_val = QCA_WLAN_AUTH_TYPE_WPA;
-		break;
-	case eCSR_AUTH_TYPE_WPA_PSK:
-		ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
-		break;
-	case eCSR_AUTH_TYPE_AUTOSWITCH:
-		ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
-		break;
-	case eCSR_AUTH_TYPE_WPA_NONE:
-		ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
-		break;
-	case eCSR_AUTH_TYPE_RSN:
-		ret_val = QCA_WLAN_AUTH_TYPE_RSN;
-		break;
-	case eCSR_AUTH_TYPE_RSN_PSK:
-		ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
-		break;
-	case eCSR_AUTH_TYPE_FT_RSN:
-		ret_val = QCA_WLAN_AUTH_TYPE_FT;
-		break;
-	case eCSR_AUTH_TYPE_FT_RSN_PSK:
-		ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
-		break;
-	case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
-		ret_val = QCA_WLAN_AUTH_TYPE_WAI;
-		break;
-	case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
-		ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
-		break;
-	case eCSR_AUTH_TYPE_CCKM_WPA:
-		ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
-		break;
-	case eCSR_AUTH_TYPE_CCKM_RSN:
-		ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
-		break;
-	case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
-		ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
-		break;
-	case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
-		ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
-		break;
-	case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
-	case eCSR_AUTH_TYPE_FAILED:
-	case eCSR_AUTH_TYPE_NONE:
-	default:
-		ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
-		break;
-	}
-	return ret_val;
-}
-
-/**
- * hdd_map_dot_11_mode() - transform dot11mode type specific to
- * vendor command
- * @dot11mode: dot11mode
- *
- * Return: Success(0) or reason code for failure
- */
-static int hdd_convert_dot11mode(uint32_t dot11mode)
-{
-	uint32_t ret_val;
-
-	switch (dot11mode) {
-	case eCSR_CFG_DOT11_MODE_11A:
-		ret_val = QCA_WLAN_802_11_MODE_11A;
-		break;
-	case eCSR_CFG_DOT11_MODE_11B:
-		ret_val = QCA_WLAN_802_11_MODE_11B;
-		break;
-	case eCSR_CFG_DOT11_MODE_11G:
-		ret_val = QCA_WLAN_802_11_MODE_11G;
-		break;
-	case eCSR_CFG_DOT11_MODE_11N:
-		ret_val = QCA_WLAN_802_11_MODE_11N;
-		break;
-	case eCSR_CFG_DOT11_MODE_11AC:
-		ret_val = QCA_WLAN_802_11_MODE_11AC;
-		break;
-	case eCSR_CFG_DOT11_MODE_AUTO:
-	case eCSR_CFG_DOT11_MODE_ABG:
-	default:
-		ret_val = QCA_WLAN_802_11_MODE_INVALID;
-	}
-	return ret_val;
-}
-
-/**
- * hdd_add_tx_bitrate() - add tx bitrate attribute
- * @skb: pointer to sk buff
- * @hdd_sta_ctx: pointer to hdd station context
- * @idx: attribute index
- *
- * Return: Success(0) or reason code for failure
- */
-static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
-					  struct hdd_station_ctx *hdd_sta_ctx,
-					  int idx)
-{
-	struct nlattr *nla_attr;
-	uint32_t bitrate, bitrate_compat;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr) {
-		hdd_err("nla_nest_start failed");
-		goto fail;
-	}
-
-	/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
-	bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->
-						cache_conn_info.txrate);
-
-	/* report 16-bit bitrate only if we can */
-	bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
-
-	if (bitrate > 0) {
-		if (nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
-			hdd_err("put fail bitrate: %u", bitrate);
-			goto fail;
-		}
-	} else {
-		hdd_err("Invalid bitrate: %u", bitrate);
-	}
-
-	if (bitrate_compat > 0) {
-		if (nla_put_u16(skb, NL80211_RATE_INFO_BITRATE,
-				bitrate_compat)) {
-			hdd_err("put fail bitrate_compat: %u", bitrate_compat);
-			goto fail;
-		}
-	} else {
-		hdd_err("Invalid bitrate_compat: %u", bitrate_compat);
-	}
-
-	if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
-		       hdd_sta_ctx->cache_conn_info.txrate.nss)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_add_sta_info() - add station info attribute
- * @skb: pointer to sk buff
- * @hdd_sta_ctx: pointer to hdd station context
- * @idx: attribute index
- *
- * Return: Success(0) or reason code for failure
- */
-static int32_t hdd_add_sta_info(struct sk_buff *skb,
-				       struct hdd_station_ctx *hdd_sta_ctx, int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr) {
-		hdd_err("nla_nest_start failed");
-		goto fail;
-	}
-
-	if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
-		       (hdd_sta_ctx->cache_conn_info.signal + 100))) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE)) {
-		hdd_err("hdd_add_tx_bitrate failed");
-		goto fail;
-	}
-
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_add_survey_info() - add survey info attribute
- * @skb: pointer to sk buff
- * @hdd_sta_ctx: pointer to hdd station context
- * @idx: attribute index
- *
- * Return: Success(0) or reason code for failure
- */
-static int32_t hdd_add_survey_info(struct sk_buff *skb,
-					   struct hdd_station_ctx *hdd_sta_ctx,
-					   int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr)
-		goto fail;
-	if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
-			hdd_sta_ctx->cache_conn_info.freq) ||
-	    nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
-		       (hdd_sta_ctx->cache_conn_info.noise + 100))) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_add_link_standard_info() - add link info attribute
- * @skb: pointer to sk buff
- * @hdd_sta_ctx: pointer to hdd station context
- * @idx: attribute index
- *
- * Return: Success(0) or reason code for failure
- */
-static int32_t
-hdd_add_link_standard_info(struct sk_buff *skb,
-			   struct hdd_station_ctx *hdd_sta_ctx, int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr) {
-		hdd_err("nla_nest_start failed");
-		goto fail;
-	}
-
-	if (nla_put(skb,
-		    NL80211_ATTR_SSID,
-		    hdd_sta_ctx->cache_conn_info.last_ssid.SSID.length,
-		    hdd_sta_ctx->cache_conn_info.last_ssid.SSID.ssId)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	if (nla_put(skb, NL80211_ATTR_MAC, QDF_MAC_ADDR_SIZE,
-		    hdd_sta_ctx->cache_conn_info.bssId.bytes)) {
-		hdd_err("put bssid failed");
-		goto fail;
-	}
-	if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO)) {
-		hdd_err("hdd_add_survey_info failed");
-		goto fail;
-	}
-
-	if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO)) {
-		hdd_err("hdd_add_sta_info failed");
-		goto fail;
-	}
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_add_ap_standard_info() - add ap info attribute
- * @skb: pointer to sk buff
- * @hdd_sta_ctx: pointer to hdd station context
- * @idx: attribute index
- *
- * Return: Success(0) or reason code for failure
- */
-static int32_t
-hdd_add_ap_standard_info(struct sk_buff *skb,
-			 struct hdd_station_ctx *hdd_sta_ctx, int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr)
-		goto fail;
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
-		if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
-			    sizeof(hdd_sta_ctx->cache_conn_info.vht_caps),
-			    &hdd_sta_ctx->cache_conn_info.vht_caps)) {
-			hdd_err("put fail");
-			goto fail;
-		}
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
-		if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
-			    sizeof(hdd_sta_ctx->cache_conn_info.ht_caps),
-			    &hdd_sta_ctx->cache_conn_info.ht_caps)) {
-			hdd_err("put fail");
-			goto fail;
-		}
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_get_station_info() - send BSS information to supplicant
- * @hdd_ctx: pointer to hdd context
- * @adapter: pointer to adapter
- *
- * Return: 0 if success else error status
- */
-static int hdd_get_station_info(struct hdd_context *hdd_ctx,
-					 struct hdd_adapter *adapter)
-{
-	struct sk_buff *skb = NULL;
-	uint8_t *tmp_hs20 = NULL;
-	uint32_t nl_buf_len;
-	struct hdd_station_ctx *hdd_sta_ctx;
-
-	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
-
-	nl_buf_len = NLMSG_HDRLEN;
-	nl_buf_len += sizeof(hdd_sta_ctx->
-				cache_conn_info.last_ssid.SSID.length) +
-		      QDF_MAC_ADDR_SIZE +
-		      sizeof(hdd_sta_ctx->cache_conn_info.freq) +
-		      sizeof(hdd_sta_ctx->cache_conn_info.noise) +
-		      sizeof(hdd_sta_ctx->cache_conn_info.signal) +
-		      (sizeof(uint32_t) * 2) +
-		      sizeof(hdd_sta_ctx->cache_conn_info.txrate.nss) +
-		      sizeof(hdd_sta_ctx->cache_conn_info.roam_count) +
-		      sizeof(hdd_sta_ctx->cache_conn_info.last_auth_type) +
-		      sizeof(hdd_sta_ctx->cache_conn_info.dot11Mode);
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
-		nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.vht_caps);
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
-		nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.ht_caps);
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) {
-		tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->
-						cache_conn_info.hs20vendor_ie);
-		nl_buf_len += (sizeof(hdd_sta_ctx->
-					cache_conn_info.hs20vendor_ie) - 1);
-	}
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
-		nl_buf_len += sizeof(hdd_sta_ctx->
-						cache_conn_info.ht_operation);
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
-		nl_buf_len += sizeof(hdd_sta_ctx->
-						cache_conn_info.vht_operation);
-
-
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
-	if (!skb) {
-		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
-		return -ENOMEM;
-	}
-
-	if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
-				       LINK_INFO_STANDARD_NL80211_ATTR)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
-				     AP_INFO_STANDARD_NL80211_ATTR)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	if (nla_put_u32(skb, INFO_ROAM_COUNT,
-			hdd_sta_ctx->cache_conn_info.roam_count) ||
-	    nla_put_u32(skb, INFO_AKM,
-			hdd_convert_auth_type(
-			hdd_sta_ctx->cache_conn_info.last_auth_type)) ||
-	    nla_put_u32(skb, WLAN802_11_MODE,
-			hdd_convert_dot11mode(
-			hdd_sta_ctx->cache_conn_info.dot11Mode))) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
-		if (nla_put(skb, HT_OPERATION,
-			    (sizeof(hdd_sta_ctx->cache_conn_info.ht_operation)),
-			    &hdd_sta_ctx->cache_conn_info.ht_operation)) {
-			hdd_err("put fail");
-			goto fail;
-		}
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
-		if (nla_put(skb, VHT_OPERATION,
-			    (sizeof(hdd_sta_ctx->
-					cache_conn_info.vht_operation)),
-			    &hdd_sta_ctx->cache_conn_info.vht_operation)) {
-			hdd_err("put fail");
-			goto fail;
-		}
-	if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present)
-		if (nla_put(skb, AP_INFO_HS20_INDICATION,
-			    (sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie)
-			     - 1),
-			    tmp_hs20 + 1)) {
-			hdd_err("put fail");
-			goto fail;
-		}
-
-	return cfg80211_vendor_cmd_reply(skb);
-fail:
-	if (skb)
-		kfree_skb(skb);
-	return -EINVAL;
-}
-
 struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
 					 struct qdf_mac_addr mac_addr)
 {
@@ -4980,638 +4358,6 @@
 	return stainfo;
 }
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
-static inline int32_t remote_station_put_u64(struct sk_buff *skb,
-					     int32_t attrtype,
-					     uint64_t value)
-{
-	return nla_put_u64_64bit(skb, attrtype, value, REMOTE_PAD);
-}
-#else
-static inline int32_t remote_station_put_u64(struct sk_buff *skb,
-					     int32_t attrtype,
-					     uint64_t value)
-{
-	return nla_put_u64(skb, attrtype, value);
-}
-#endif
-
-/**
- * hdd_add_survey_info_sap_get_len - get data length used in
- * hdd_add_survey_info_sap()
- *
- * This function calculates the data length used in hdd_add_survey_info_sap()
- *
- * Return: total data length used in hdd_add_survey_info_sap()
- */
-static uint32_t hdd_add_survey_info_sap_get_len(void)
-{
-	return ((NLA_HDRLEN) + (sizeof(uint32_t) + NLA_HDRLEN));
-}
-
-/**
- * hdd_add_survey_info - add survey info attribute
- * @skb: pointer to response skb buffer
- * @stainfo: station information
- * @idx: attribute type index for nla_next_start()
- *
- * This function adds survey info attribute to response skb buffer
- *
- * Return : 0 on success and errno on failure
- */
-static int32_t hdd_add_survey_info_sap(struct sk_buff *skb,
-				       struct hdd_station_info *stainfo,
-				       int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr)
-		goto fail;
-	if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
-			stainfo->freq)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_add_tx_bitrate_sap_get_len - get data length used in
- * hdd_add_tx_bitrate_sap()
- *
- * This function calculates the data length used in hdd_add_tx_bitrate_sap()
- *
- * Return: total data length used in hdd_add_tx_bitrate_sap()
- */
-static uint32_t hdd_add_tx_bitrate_sap_get_len(void)
-{
-	return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN));
-}
-
-/**
- * hdd_add_tx_bitrate_sap - add vhs nss info attribute
- * @skb: pointer to response skb buffer
- * @stainfo: station information
- * @idx: attribute type index for nla_next_start()
- *
- * This function adds vht nss attribute to response skb buffer
- *
- * Return : 0 on success and errno on failure
- */
-static int hdd_add_tx_bitrate_sap(struct sk_buff *skb,
-				  struct hdd_station_info *stainfo,
-				  int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr)
-		goto fail;
-
-	if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
-		       stainfo->nss)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_add_sta_info_sap_get_len - get data length used in
- * hdd_add_sta_info_sap()
- *
- * This function calculates the data length used in hdd_add_sta_info_sap()
- *
- * Return: total data length used in hdd_add_sta_info_sap()
- */
-static uint32_t hdd_add_sta_info_sap_get_len(void)
-{
-	return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN) +
-		hdd_add_tx_bitrate_sap_get_len());
-}
-
-/**
- * hdd_add_sta_info_sap - add sta signal info attribute
- * @skb: pointer to response skb buffer
- * @stainfo: station information
- * @idx: attribute type index for nla_next_start()
- *
- * This function adds sta signal attribute to response skb buffer
- *
- * Return : 0 on success and errno on failure
- */
-static int32_t hdd_add_sta_info_sap(struct sk_buff *skb, int8_t rssi,
-				    struct hdd_station_info *stainfo, int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr)
-		goto fail;
-
-	if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL, rssi)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-	if (hdd_add_tx_bitrate_sap(skb, stainfo, NL80211_STA_INFO_TX_BITRATE))
-		goto fail;
-
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_add_link_standard_info_sap_get_len - get data length used in
- * hdd_add_link_standard_info_sap()
- *
- * This function calculates the data length used in
- * hdd_add_link_standard_info_sap()
- *
- * Return: total data length used in hdd_add_link_standard_info_sap()
- */
-static uint32_t hdd_add_link_standard_info_sap_get_len(void)
-{
-	return ((NLA_HDRLEN) +
-		hdd_add_survey_info_sap_get_len() +
-		hdd_add_sta_info_sap_get_len() +
-		(sizeof(uint32_t) + NLA_HDRLEN));
-}
-
-/**
- * hdd_add_link_standard_info_sap - add add link info attribut
- * @skb: pointer to response skb buffer
- * @stainfo: station information
- * @idx: attribute type index for nla_next_start()
- *
- * This function adds link info attribut to response skb buffer
- *
- * Return : 0 on success and errno on failure
- */
-static int hdd_add_link_standard_info_sap(struct sk_buff *skb, int8_t rssi,
-					  struct hdd_station_info *stainfo,
-					  int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr)
-		goto fail;
-	if (hdd_add_survey_info_sap(skb, stainfo, NL80211_ATTR_SURVEY_INFO))
-		goto fail;
-	if (hdd_add_sta_info_sap(skb, rssi, stainfo, NL80211_ATTR_STA_INFO))
-		goto fail;
-
-	if (nla_put_u32(skb, NL80211_ATTR_REASON_CODE, stainfo->reason_code)) {
-		hdd_err("Reason code put fail");
-		goto fail;
-	}
-
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_add_ap_standard_info_sap_get_len - get data length used in
- * hdd_add_ap_standard_info_sap()
- * @stainfo: station information
- *
- * This function calculates the data length used in
- * hdd_add_ap_standard_info_sap()
- *
- * Return: total data length used in hdd_add_ap_standard_info_sap()
- */
-static uint32_t hdd_add_ap_standard_info_sap_get_len(
-				struct hdd_station_info *stainfo)
-{
-	uint32_t len;
-
-	len = NLA_HDRLEN;
-	if (stainfo->vht_present)
-		len += (sizeof(stainfo->vht_caps) + NLA_HDRLEN);
-	if (stainfo->ht_present)
-		len += (sizeof(stainfo->ht_caps) + NLA_HDRLEN);
-
-	return len;
-}
-
-/**
- * hdd_add_ap_standard_info_sap - add HT and VHT info attributes
- * @skb: pointer to response skb buffer
- * @stainfo: station information
- * @idx: attribute type index for nla_next_start()
- *
- * This function adds HT and VHT info attributes to response skb buffer
- *
- * Return : 0 on success and errno on failure
- */
-static int hdd_add_ap_standard_info_sap(struct sk_buff *skb,
-					struct hdd_station_info *stainfo,
-					int idx)
-{
-	struct nlattr *nla_attr;
-
-	nla_attr = nla_nest_start(skb, idx);
-	if (!nla_attr)
-		goto fail;
-
-	if (stainfo->vht_present) {
-		if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
-			    sizeof(stainfo->vht_caps),
-			    &stainfo->vht_caps)) {
-			hdd_err("put fail");
-			goto fail;
-		}
-	}
-	if (stainfo->ht_present) {
-		if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
-			    sizeof(stainfo->ht_caps),
-			    &stainfo->ht_caps)) {
-			hdd_err("put fail");
-			goto fail;
-		}
-	}
-	nla_nest_end(skb, nla_attr);
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-/**
- * hdd_decode_ch_width - decode channel band width based
- * @ch_width: encoded enum value holding channel band width
- *
- * This function decodes channel band width from the given encoded enum value.
- *
- * Returns: decoded channel band width.
- */
-static uint8_t hdd_decode_ch_width(tSirMacHTChannelWidth ch_width)
-{
-	switch (ch_width) {
-	case 0:
-		return 20;
-	case 1:
-		return 40;
-	case 2:
-		return 80;
-	case 3:
-	case 4:
-		return 160;
-	default:
-		hdd_debug("invalid enum: %d", ch_width);
-		return 20;
-	}
-}
-
-/**
- * hdd_get_cached_station_remote() - get cached(deleted) peer's info
- * @hdd_ctx: hdd context
- * @adapter: hostapd interface
- * @mac_addr: mac address of requested peer
- *
- * This function collect and indicate the cached(deleted) peer's info
- *
- * Return: 0 on success, otherwise error value
- */
-
-static int hdd_get_cached_station_remote(struct hdd_context *hdd_ctx,
-					 struct hdd_adapter *adapter,
-					 struct qdf_mac_addr mac_addr)
-{
-	struct hdd_station_info *stainfo = hdd_get_stainfo(
-						adapter->cache_sta_info,
-						mac_addr);
-	struct sk_buff *skb = NULL;
-	uint32_t nl_buf_len = NLMSG_HDRLEN;
-	uint8_t channel_width;
-
-	if (!stainfo) {
-		hdd_err("peer " MAC_ADDRESS_STR " not found",
-			MAC_ADDR_ARRAY(mac_addr.bytes));
-		return -EINVAL;
-	}
-
-	nl_buf_len += hdd_add_link_standard_info_sap_get_len() +
-			hdd_add_ap_standard_info_sap_get_len(stainfo) +
-			(sizeof(stainfo->dot11_mode) + NLA_HDRLEN) +
-			(sizeof(stainfo->ch_width) + NLA_HDRLEN) +
-			(sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
-			(sizeof(stainfo->rx_rate) + NLA_HDRLEN);
-
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
-	if (!skb) {
-		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
-		return -ENOMEM;
-	}
-
-	if (hdd_add_link_standard_info_sap(skb, stainfo->rssi, stainfo,
-					   LINK_INFO_STANDARD_NL80211_ATTR)) {
-		hdd_err("link standard put fail");
-		goto fail;
-	}
-
-	if (hdd_add_ap_standard_info_sap(skb, stainfo,
-					 AP_INFO_STANDARD_NL80211_ATTR)) {
-		hdd_err("ap standard put fail");
-		goto fail;
-	}
-
-	/* upper layer expects decoded channel BW */
-	channel_width = hdd_decode_ch_width(stainfo->ch_width);
-
-	if (nla_put_u32(skb, REMOTE_SUPPORTED_MODE,
-			hdd_convert_dot11mode(
-			stainfo->mode)) ||
-	    nla_put_u8(skb, REMOTE_CH_WIDTH, channel_width)) {
-		hdd_err("remote ch put fail");
-		goto fail;
-	}
-	if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate)) {
-		hdd_err("tx rate put fail");
-		goto fail;
-	}
-	if (nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
-		hdd_err("rx rate put fail");
-		goto fail;
-	}
-
-	qdf_mem_zero(stainfo, sizeof(*stainfo));
-
-	return cfg80211_vendor_cmd_reply(skb);
-fail:
-	if (skb)
-		kfree_skb(skb);
-
-	return -EINVAL;
-}
-
-/**
- * hdd_get_cached_station_remote() - get connected peer's info
- * @hdd_ctx: hdd context
- * @adapter: hostapd interface
- * @mac_addr: mac address of requested peer
- *
- * This function collect and indicate the connected peer's info
- *
- * Return: 0 on success, otherwise error value
- */
-static int hdd_get_connected_station_info(struct hdd_context *hdd_ctx,
-					  struct hdd_adapter *adapter,
-					  struct qdf_mac_addr mac_addr,
-					  struct hdd_station_info *stainfo)
-{
-	struct sk_buff *skb = NULL;
-	uint32_t nl_buf_len;
-	struct sir_peer_info_ext peer_info;
-	bool txrx_rate = true;
-
-	nl_buf_len = NLMSG_HDRLEN;
-	nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
-		(sizeof(stainfo->tx_packets) + NLA_HDRLEN) +
-		(sizeof(stainfo->tx_bytes) + NLA_HDRLEN) +
-		(sizeof(stainfo->rx_packets) + NLA_HDRLEN) +
-		(sizeof(stainfo->rx_bytes) + NLA_HDRLEN) +
-		(sizeof(stainfo->is_qos_enabled) + NLA_HDRLEN) +
-		(sizeof(stainfo->mode) + NLA_HDRLEN);
-
-	if (!hdd_ctx->config->sap_get_peer_info ||
-	    wlan_hdd_get_peer_info(adapter, mac_addr, &peer_info)) {
-		hdd_err("fail to get tx/rx rate");
-		txrx_rate = false;
-	} else {
-		stainfo->tx_rate = peer_info.tx_rate;
-		stainfo->rx_rate = peer_info.rx_rate;
-		nl_buf_len += (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
-			(sizeof(stainfo->rx_rate) + NLA_HDRLEN);
-	}
-
-	/* below info is only valid for HT/VHT mode */
-	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
-		nl_buf_len += (sizeof(stainfo->ampdu) + NLA_HDRLEN) +
-			(sizeof(stainfo->tx_stbc) + NLA_HDRLEN) +
-			(sizeof(stainfo->rx_stbc) + NLA_HDRLEN) +
-			(sizeof(stainfo->ch_width) + NLA_HDRLEN) +
-			(sizeof(stainfo->sgi_enable) + NLA_HDRLEN);
-
-	hdd_info("buflen %d hdrlen %d", nl_buf_len, NLMSG_HDRLEN);
-
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
-						  nl_buf_len);
-	if (!skb) {
-		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
-		goto fail;
-	}
-
-	hdd_info("stainfo");
-	hdd_info("maxrate %x tx_pkts %x tx_bytes %llx",
-		 stainfo->max_phy_rate, stainfo->tx_packets,
-		 stainfo->tx_bytes);
-	hdd_info("rx_pkts %x rx_bytes %llx mode %x",
-		 stainfo->rx_packets, stainfo->rx_bytes,
-		 stainfo->mode);
-	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
-		hdd_info("ampdu %d tx_stbc %d rx_stbc %d",
-			 stainfo->ampdu, stainfo->tx_stbc,
-			 stainfo->rx_stbc);
-		hdd_info("wmm %d chwidth %d sgi %d",
-			 stainfo->is_qos_enabled,
-			 stainfo->ch_width,
-			 stainfo->sgi_enable);
-	}
-
-	if (nla_put_u32(skb, REMOTE_MAX_PHY_RATE, stainfo->max_phy_rate) ||
-	    nla_put_u32(skb, REMOTE_TX_PACKETS, stainfo->tx_packets) ||
-	    remote_station_put_u64(skb, REMOTE_TX_BYTES, stainfo->tx_bytes) ||
-	    nla_put_u32(skb, REMOTE_RX_PACKETS, stainfo->rx_packets) ||
-	    remote_station_put_u64(skb, REMOTE_RX_BYTES, stainfo->rx_bytes) ||
-	    nla_put_u8(skb, REMOTE_WMM, stainfo->is_qos_enabled) ||
-	    nla_put_u8(skb, REMOTE_SUPPORTED_MODE, stainfo->mode)) {
-		hdd_err("put fail");
-		goto fail;
-	}
-
-	if (txrx_rate) {
-		if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate) ||
-		    nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
-			hdd_err("put fail");
-			goto fail;
-		} else {
-			hdd_info("tx_rate %x rx_rate %x",
-				 stainfo->tx_rate, stainfo->rx_rate);
-		}
-	}
-
-	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
-		if (nla_put_u8(skb, REMOTE_AMPDU, stainfo->ampdu) ||
-		    nla_put_u8(skb, REMOTE_TX_STBC, stainfo->tx_stbc) ||
-		    nla_put_u8(skb, REMOTE_RX_STBC, stainfo->rx_stbc) ||
-		    nla_put_u8(skb, REMOTE_CH_WIDTH, stainfo->ch_width) ||
-		    nla_put_u8(skb, REMOTE_SGI_ENABLE, stainfo->sgi_enable)) {
-			hdd_err("put fail");
-			goto fail;
-		}
-	}
-
-	return cfg80211_vendor_cmd_reply(skb);
-
-fail:
-	if (skb)
-		kfree_skb(skb);
-
-	return -EINVAL;
-}
-
-/**
- * hdd_get_station_remote() - get remote peer's info
- * @hdd_ctx: hdd context
- * @adapter: hostapd interface
- * @mac_addr: mac address of requested peer
- *
- * This function collect and indicate the remote peer's info
- *
- * Return: 0 on success, otherwise error value
- */
-static int hdd_get_station_remote(struct hdd_context *hdd_ctx,
-				  struct hdd_adapter *adapter,
-				  struct qdf_mac_addr mac_addr)
-{
-	struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
-						      mac_addr);
-	int status = 0;
-	bool is_associated = false;
-
-	if (!stainfo) {
-		status = hdd_get_cached_station_remote(hdd_ctx, adapter,
-						       mac_addr);
-		return status;
-	}
-
-	is_associated = hdd_is_peer_associated(adapter, &mac_addr);
-	if (!is_associated) {
-		status = hdd_get_cached_station_remote(hdd_ctx, adapter,
-						       mac_addr);
-		return status;
-	}
-
-	status = hdd_get_connected_station_info(hdd_ctx, adapter,
-						mac_addr, stainfo);
-	return status;
-}
-
-/**
- * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
- * @wiphy: corestack handler
- * @wdev: wireless device
- * @data: data
- * @data_len: data length
- *
- * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
- * Validate cmd attributes and send the station info to upper layers.
- *
- * Return: Success(0) or reason code for failure
- */
-static int
-__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
-			       struct wireless_dev *wdev,
-			       const void *data,
-			       int data_len)
-{
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct net_device *dev = wdev->netdev;
-	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
-	int32_t status;
-
-	hdd_enter_dev(dev);
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
-		status = -EPERM;
-		goto out;
-	}
-
-	status = wlan_hdd_validate_context(hdd_ctx);
-	if (0 != status)
-		goto out;
-
-
-	status = wlan_cfg80211_nla_parse(tb,
-					 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
-					 data, data_len,
-					 hdd_get_station_policy);
-	if (status) {
-		hdd_err("Invalid ATTR");
-		goto out;
-	}
-
-	/* Parse and fetch Command Type*/
-	if (tb[STATION_INFO]) {
-		status = hdd_get_station_info(hdd_ctx, adapter);
-	} else if (tb[STATION_ASSOC_FAIL_REASON]) {
-		status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
-	} else if (tb[STATION_REMOTE]) {
-		struct qdf_mac_addr mac_addr;
-
-		if (adapter->device_mode != QDF_SAP_MODE &&
-		    adapter->device_mode != QDF_P2P_GO_MODE) {
-			hdd_err("invalid device_mode:%d", adapter->device_mode);
-			status = -EINVAL;
-			goto out;
-		}
-
-		nla_memcpy(mac_addr.bytes, tb[STATION_REMOTE],
-			   QDF_MAC_ADDR_SIZE);
-
-		hdd_debug("STATION_REMOTE " MAC_ADDRESS_STR,
-			  MAC_ADDR_ARRAY(mac_addr.bytes));
-
-		status = hdd_get_station_remote(hdd_ctx, adapter, mac_addr);
-	} else {
-		hdd_err("get station info cmd type failed");
-		status = -EINVAL;
-		goto out;
-	}
-	hdd_exit();
-out:
-	return status;
-}
-
-/**
- * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
- * @wiphy: corestack handler
- * @wdev: wireless device
- * @data: data
- * @data_len: data length
- *
- * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
- * Validate cmd attributes and send the station info to upper layers.
- *
- * Return: Success(0) or reason code for failure
- */
-static int32_t
-hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
-			     struct wireless_dev *wdev,
-			     const void *data,
-			     int data_len)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
 /*
  * undef short names defined for get station command
  * used by __wlan_hdd_cfg80211_get_station_cmd()
@@ -8342,202 +7088,6 @@
 }
 #endif
 
-/*
- * define short names for the global vendor params
- * used by __wlan_hdd_cfg80211_monitor_rssi()
- */
-#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
-#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
-#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
-#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
-#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
-
-/**
- * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Return: 0 on success, negative errno on failure
- */
-static int
-__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
-				 struct wireless_dev *wdev,
-				 const void *data,
-				 int data_len)
-{
-	struct net_device *dev = wdev->netdev;
-	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct nlattr *tb[PARAM_MAX + 1];
-	struct rssi_monitor_req req;
-	QDF_STATUS status;
-	int ret;
-	uint32_t control;
-	mac_handle_t mac_handle;
-	static const struct nla_policy policy[PARAM_MAX + 1] = {
-			[PARAM_REQUEST_ID] = { .type = NLA_U32 },
-			[PARAM_CONTROL] = { .type = NLA_U32 },
-			[PARAM_MIN_RSSI] = { .type = NLA_S8 },
-			[PARAM_MAX_RSSI] = { .type = NLA_S8 },
-	};
-
-	hdd_enter_dev(dev);
-
-	if (wlan_hdd_validate_session_id(adapter->session_id))
-		return -EINVAL;
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
-		hdd_err("Not in Connected state!");
-		return -ENOTSUPP;
-	}
-
-	if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
-		hdd_err("Invalid ATTR");
-		return -EINVAL;
-	}
-
-	if (!tb[PARAM_REQUEST_ID]) {
-		hdd_err("attr request id failed");
-		return -EINVAL;
-	}
-
-	if (!tb[PARAM_CONTROL]) {
-		hdd_err("attr control failed");
-		return -EINVAL;
-	}
-
-	req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
-	req.session_id = adapter->session_id;
-	control = nla_get_u32(tb[PARAM_CONTROL]);
-
-	if (control == QCA_WLAN_RSSI_MONITORING_START) {
-		req.control = true;
-		if (!tb[PARAM_MIN_RSSI]) {
-			hdd_err("attr min rssi failed");
-			return -EINVAL;
-		}
-
-		if (!tb[PARAM_MAX_RSSI]) {
-			hdd_err("attr max rssi failed");
-			return -EINVAL;
-		}
-
-		req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
-		req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
-
-		if (!(req.min_rssi < req.max_rssi)) {
-			hdd_warn("min_rssi: %d must be less than max_rssi: %d",
-					req.min_rssi, req.max_rssi);
-			return -EINVAL;
-		}
-		hdd_debug("Min_rssi: %d Max_rssi: %d",
-			req.min_rssi, req.max_rssi);
-
-	} else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
-		req.control = false;
-	else {
-		hdd_err("Invalid control cmd: %d", control);
-		return -EINVAL;
-	}
-	hdd_debug("Request Id: %u Session_id: %d Control: %d",
-			req.request_id, req.session_id, req.control);
-
-	mac_handle = hdd_ctx->mac_handle;
-	status = sme_set_rssi_monitoring(mac_handle, &req);
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
-		hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*
- * done with short names for the global vendor params
- * used by __wlan_hdd_cfg80211_monitor_rssi()
- */
-#undef PARAM_MAX
-#undef PARAM_CONTROL
-#undef PARAM_REQUEST_ID
-#undef PARAM_MAX_RSSI
-#undef PARAM_MIN_RSSI
-
-/**
- * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
- * @wiphy:    wiphy structure pointer
- * @wdev:     Wireless device structure pointer
- * @data:     Pointer to the data received
- * @data_len: Length of @data
- *
- * Return: 0 on success; errno on failure
- */
-static int
-wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
-			       const void *data, int data_len)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-void hdd_rssi_threshold_breached(hdd_handle_t hdd_handle,
-				 struct rssi_breach_event *data)
-{
-	struct hdd_context *hdd_ctx  = hdd_handle_to_context(hdd_handle);
-	struct sk_buff *skb;
-
-	hdd_enter();
-
-	if (wlan_hdd_validate_context(hdd_ctx))
-		return;
-	if (!data) {
-		hdd_err("data is null");
-		return;
-	}
-
-	skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
-				  NULL,
-				  EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
-				  QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
-				  GFP_KERNEL);
-
-	if (!skb) {
-		hdd_err("mem alloc failed");
-		return;
-	}
-
-	hdd_debug("Req Id: %u Current rssi: %d",
-		  data->request_id, data->curr_rssi);
-	hdd_debug("Current BSSID: " MAC_ADDRESS_STR,
-		  MAC_ADDR_ARRAY(data->curr_bssid.bytes));
-
-	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
-			data->request_id) ||
-	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
-		    sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
-	    nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
-		       data->curr_rssi)) {
-		hdd_err("nla put fail");
-		goto fail;
-	}
-
-	cfg80211_vendor_event(skb, GFP_KERNEL);
-	return;
-
-fail:
-	kfree_skb(skb);
-}
-
 #ifdef WLAN_NS_OFFLOAD
 static const struct nla_policy
 ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
@@ -9070,1104 +7620,6 @@
 	return ret;
 }
 
-static const struct
-nla_policy
-qca_wlan_vendor_ota_test_policy
-[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
-	[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
-};
-
-/**
- * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Return: 0 on success, negative errno on failure
- */
-static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	struct net_device *dev = wdev->netdev;
-	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
-	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
-	uint8_t ota_enable = 0;
-	QDF_STATUS status;
-	uint32_t current_roam_state;
-	mac_handle_t mac_handle;
-
-	hdd_enter_dev(dev);
-
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EPERM;
-	}
-
-	if (0 != wlan_hdd_validate_context(hdd_ctx))
-		return -EINVAL;
-
-	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
-				    data, data_len,
-				    qca_wlan_vendor_ota_test_policy)) {
-		hdd_err("invalid attr");
-		return -EINVAL;
-	}
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
-		hdd_err("attr ota test failed");
-		return -EINVAL;
-	}
-
-	ota_enable = nla_get_u8(
-		tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
-
-	hdd_debug(" OTA test enable = %d", ota_enable);
-	if (ota_enable != 1) {
-		hdd_err("Invalid value, only enable test mode is supported!");
-		return -EINVAL;
-	}
-
-	mac_handle = hdd_ctx->mac_handle;
-	current_roam_state =
-		sme_get_current_roam_state(mac_handle, adapter->session_id);
-	status = sme_stop_roaming(mac_handle, adapter->session_id,
-				  eCsrHddIssued);
-	if (status != QDF_STATUS_SUCCESS) {
-		hdd_err("Enable/Disable roaming failed");
-		return -EINVAL;
-	}
-
-	status = sme_ps_enable_disable(mac_handle, adapter->session_id,
-				       SME_PS_DISABLE);
-	if (status != QDF_STATUS_SUCCESS) {
-		hdd_err("Enable/Disable power save failed");
-		/* restore previous roaming setting */
-		if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
-		    current_roam_state == eCSR_ROAMING_STATE_JOINED)
-			status = sme_start_roaming(mac_handle,
-						   adapter->session_id,
-						   eCsrHddIssued);
-		else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
-			 current_roam_state == eCSR_ROAMING_STATE_IDLE)
-			status = sme_stop_roaming(mac_handle,
-						  adapter->session_id,
-						  eCsrHddIssued);
-
-		if (status != QDF_STATUS_SUCCESS)
-			hdd_err("Restoring roaming state failed");
-
-		return -EINVAL;
-	}
-
-
-	return 0;
-}
-
-/**
- * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Return: 0 on success, negative errno on failure
- */
-static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
-					struct wireless_dev *wdev,
-					const void *data,
-					int data_len)
-{
-	int ret = 0;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-static const struct nla_policy
-txpower_scale_policy[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1] = {
-	[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE] = { .type = NLA_U8 },
-};
-
-/**
- * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Return: 0 on success, negative errno on failure
- */
-static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct net_device *dev = wdev->netdev;
-	struct hdd_adapter *adapter;
-	int ret;
-	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
-	uint8_t scale_value;
-	QDF_STATUS status;
-
-	hdd_enter_dev(dev);
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-
-	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
-				    data, data_len, txpower_scale_policy)) {
-		hdd_err("Invalid ATTR");
-		return -EINVAL;
-	}
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
-		hdd_err("attr tx power scale failed");
-		return -EINVAL;
-	}
-
-	scale_value = nla_get_u8(tb
-		    [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
-
-	if (scale_value > MAX_TXPOWER_SCALE) {
-		hdd_err("Invalid tx power scale level");
-		return -EINVAL;
-	}
-
-	status = wma_set_tx_power_scale(adapter->session_id, scale_value);
-
-	if (QDF_STATUS_SUCCESS != status) {
-		hdd_err("Set tx power scale failed");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Return: 0 on success, negative errno on failure
- */
-static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
-						data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-static const struct nla_policy txpower_scale_decr_db_policy
-[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1] = {
-	[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB] = { .type = NLA_U8 },
-};
-
-/**
- * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Return: 0 on success, negative errno on failure
- */
-static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct net_device *dev = wdev->netdev;
-	struct hdd_adapter *adapter;
-	int ret;
-	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
-	uint8_t scale_value;
-	QDF_STATUS status;
-
-	hdd_enter_dev(dev);
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-
-	if (wlan_cfg80211_nla_parse(tb,
-				 QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
-				 data, data_len,
-				 txpower_scale_decr_db_policy)) {
-		hdd_err("Invalid ATTR");
-		return -EINVAL;
-	}
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
-		hdd_err("attr tx power decrease db value failed");
-		return -EINVAL;
-	}
-
-	scale_value = nla_get_u8(tb
-		    [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
-
-	status = wma_set_tx_power_scale_decr_db(adapter->session_id,
-							scale_value);
-
-	if (QDF_STATUS_SUCCESS != status) {
-		hdd_err("Set tx power decrease db failed");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Return: 0 on success, negative errno on failure
- */
-static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
-						data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-/**
- * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Processes the conditional channel switch request and invokes the helper
- * APIs to process the channel switch request.
- *
- * Return: 0 on success, negative errno on failure
- */
-static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	int ret;
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct net_device *dev = wdev->netdev;
-	struct hdd_adapter *adapter;
-	struct nlattr
-		*tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
-	uint32_t freq_len, i;
-	uint32_t *freq;
-	uint8_t chans[QDF_MAX_NUM_CHAN] = {0};
-
-	hdd_enter_dev(dev);
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	if (!hdd_ctx->config->enableDFSMasterCap) {
-		hdd_err("DFS master capability is not present in the driver");
-		return -EINVAL;
-	}
-
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EPERM;
-	}
-
-	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	if (adapter->device_mode != QDF_SAP_MODE) {
-		hdd_err("Invalid device mode %d", adapter->device_mode);
-		return -EINVAL;
-	}
-
-	/*
-	 * audit note: it is ok to pass a NULL policy here since only
-	 * one attribute is parsed which is array of frequencies and
-	 * it is explicitly validated for both under read and over read
-	 */
-	if (wlan_cfg80211_nla_parse(tb,
-			   QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
-			   data, data_len, NULL)) {
-		hdd_err("Invalid ATTR");
-		return -EINVAL;
-	}
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
-		hdd_err("Frequency list is missing");
-		return -EINVAL;
-	}
-
-	freq_len = nla_len(
-		tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
-		sizeof(uint32_t);
-
-	if (freq_len > QDF_MAX_NUM_CHAN) {
-		hdd_err("insufficient space to hold channels");
-		return -ENOMEM;
-	}
-
-	hdd_debug("freq_len=%d", freq_len);
-
-	freq = nla_data(
-		tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
-
-
-	for (i = 0; i < freq_len; i++) {
-		if (freq[i] == 0)
-			chans[i] = 0;
-		else
-			chans[i] = ieee80211_frequency_to_channel(freq[i]);
-
-		hdd_debug("freq[%d]=%d", i, freq[i]);
-	}
-
-	/*
-	 * The input frequency list from user space is designed to be a
-	 * priority based frequency list. This is only to accommodate any
-	 * future request. But, current requirement is only to perform CAC
-	 * on a single channel. So, the first entry from the list is picked.
-	 *
-	 * If channel is zero, any channel in the available outdoor regulatory
-	 * domain will be selected.
-	 */
-	ret = wlan_hdd_request_pre_cac(chans[0]);
-	if (ret) {
-		hdd_err("pre cac request failed with reason:%d", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-/* P2P listen offload device types parameters length in bytes */
-#define P2P_LO_MAX_REQ_DEV_TYPE_COUNT (10)
-#define P2P_LO_WPS_DEV_TYPE_LEN (8)
-#define P2P_LO_DEV_TYPE_MAX_LEN \
-	(P2P_LO_MAX_REQ_DEV_TYPE_COUNT * P2P_LO_WPS_DEV_TYPE_LEN)
-
-static const struct nla_policy
-p2p_listen_offload_policy[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1] = {
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] = { .type = NLA_U32 },
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] = { .type = NLA_U32 },
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] = {
-							.type = NLA_U32 },
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] = { .type = NLA_U32 },
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] = {
-					.type = NLA_BINARY,
-					.len = P2P_LO_DEV_TYPE_MAX_LEN },
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE] = {
-					.type = NLA_BINARY,
-					.len = MAX_GENIE_LEN },
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG] = {
-					.type = NLA_U32 },
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] = { .type = NLA_U32 },
-	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON] = {
-						.type = NLA_U8 },
-};
-
-/**
- * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * This function is to process the p2p listen offload start vendor
- * command. It parses the input parameters and invoke WMA API to
- * send the command to firmware.
- *
- * Return: 0 on success, negative errno on failure
- */
-static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	int ret;
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct net_device *dev = wdev->netdev;
-	struct hdd_adapter *adapter;
-	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
-	struct sir_p2p_lo_start params;
-
-	hdd_enter_dev(dev);
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EPERM;
-	}
-
-	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
-	    (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
-	    (adapter->device_mode != QDF_P2P_GO_MODE)) {
-		hdd_err("Invalid device mode %d", adapter->device_mode);
-		return -EINVAL;
-	}
-
-	if (wlan_cfg80211_nla_parse(tb,
-				    QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
-				    data, data_len,
-				    p2p_listen_offload_policy)) {
-		hdd_err("Invalid ATTR");
-		return -EINVAL;
-	}
-
-	memset(&params, 0, sizeof(params));
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
-		params.ctl_flags = 1;  /* set to default value */
-	else
-		params.ctl_flags = nla_get_u32(tb
-			[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
-	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
-	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
-	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
-	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
-	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
-		hdd_err("Attribute parsing failed");
-		return -EINVAL;
-	}
-
-	params.vdev_id = adapter->session_id;
-	params.freq = nla_get_u32(tb
-		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
-	if ((params.freq != 2412) && (params.freq != 2437) &&
-		(params.freq != 2462)) {
-		hdd_err("Invalid listening channel: %d", params.freq);
-		return -EINVAL;
-	}
-
-	params.period = nla_get_u32(tb
-		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
-	if (!((params.period > 0) && (params.period < UINT_MAX))) {
-		hdd_err("Invalid period: %d", params.period);
-		return -EINVAL;
-	}
-
-	params.interval = nla_get_u32(tb
-		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
-	if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
-		hdd_err("Invalid interval: %d", params.interval);
-		return -EINVAL;
-	}
-
-	params.count = nla_get_u32(tb
-		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
-	if (!((params.count >= 0) && (params.count < UINT_MAX))) {
-		hdd_err("Invalid count: %d", params.count);
-		return -EINVAL;
-	}
-
-	params.device_types = nla_data(tb
-		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
-	if (params.device_types == NULL) {
-		hdd_err("Invalid device types");
-		return -EINVAL;
-	}
-
-	params.dev_types_len = nla_len(tb
-		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
-	/* device type length has to be multiple of P2P_LO_WPS_DEV_TYPE_LEN */
-	if (0 != (params.dev_types_len % P2P_LO_WPS_DEV_TYPE_LEN)) {
-		hdd_err("Invalid device type length: %d", params.dev_types_len);
-		return -EINVAL;
-	}
-
-	params.probe_resp_tmplt = nla_data(tb
-		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
-	if (params.probe_resp_tmplt == NULL) {
-		hdd_err("Invalid probe response template");
-		return -EINVAL;
-	}
-
-	/*
-	 * IEs minimum length should be 2 bytes: 1 byte for element id
-	 * and 1 byte for element id length.
-	 */
-	params.probe_resp_len = nla_len(tb
-		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
-	if (params.probe_resp_len < MIN_GENIE_LEN) {
-		hdd_err("Invalid probe resp template length: %d",
-				params.probe_resp_len);
-		return -EINVAL;
-	}
-
-	hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
-		  params.freq, params.period, params.interval, params.count);
-
-	return wlan_hdd_listen_offload_start(adapter, &params);
-}
-
-
-/**
- * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
- * to process p2p listen offload start vendor command.
- *
- * Return: 0 on success, negative errno on failure
- */
-static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	int ret = 0;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
-					data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-/**
- * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * This function is to process the p2p listen offload stop vendor
- * command. It invokes WMA API to send command to firmware.
- *
- * Return: 0 on success, negative errno on failure
- */
-static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	struct hdd_adapter *adapter;
-	struct net_device *dev = wdev->netdev;
-
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EPERM;
-	}
-
-	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
-	    (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
-	    (adapter->device_mode != QDF_P2P_GO_MODE)) {
-		hdd_err("Invalid device mode");
-		return -EINVAL;
-	}
-
-	return wlan_hdd_listen_offload_stop(adapter);
-}
-
-/**
- * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
- * to process p2p listen offload stop vendor command.
- *
- * Return: 0 on success, negative errno on failure
- */
-static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	int ret = 0;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
-						data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-/**
- * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Data length
- *
- * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
- * to process the conditional channel switch request.
- *
- * Return: 0 on success, negative errno on failure
- */
-static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data,
-						int data_len)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
-						data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-/**
- * wlan_hdd_set_pre_cac_status() - Set the pre cac status
- * @pre_cac_adapter: AP adapter used for pre cac
- * @status: Status (true or false)
- * @handle: Global handle
- *
- * Sets the status of pre cac i.e., whether the pre cac is active or not
- *
- * Return: Zero on success, non-zero on failure
- */
-static int wlan_hdd_set_pre_cac_status(struct hdd_adapter *pre_cac_adapter,
-				bool status, mac_handle_t handle)
-{
-	QDF_STATUS ret;
-
-	ret = wlan_sap_set_pre_cac_status(
-		WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
-	if (QDF_IS_STATUS_ERROR(ret))
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
- * @ap_adapter: AP adapter
- * @chan_before_pre_cac: Channel
- *
- * Saves the channel which the AP was beaconing on before moving to the pre
- * cac channel. If radar is detected on the pre cac channel, this saved
- * channel will be used for AP operations.
- *
- * Return: Zero on success, non-zero on failure
- */
-static int wlan_hdd_set_chan_before_pre_cac(struct hdd_adapter *ap_adapter,
-			uint8_t chan_before_pre_cac)
-{
-	QDF_STATUS ret;
-
-	ret = wlan_sap_set_chan_before_pre_cac(
-		WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
-	if (QDF_IS_STATUS_ERROR(ret))
-		return -EINVAL;
-
-	return 0;
-}
-
-int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
-				       uint32_t *channel_count,
-				       uint8_t *channel_list,
-				       enum band_info band)
-{
-	tsap_config_t *sap_config;
-	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
-	uint32_t chan_count;
-	uint8_t i;
-	QDF_STATUS status;
-	struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
-	uint8_t tmp_chan;
-
-	sap_config = &adapter->session.ap.sap_config;
-
-	status =
-		policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
-					   tmp_chan_list,
-					   &chan_count);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("Failed to get channel list");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < chan_count; i++) {
-		tmp_chan = tmp_chan_list[i];
-		if (*channel_count < QDF_MAX_NUM_CHAN) {
-			if ((BAND_2G == band) &&
-			    (WLAN_REG_IS_24GHZ_CH(tmp_chan)) &&
-			    (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
-				channel_list[*channel_count] = tmp_chan;
-				*channel_count += 1;
-			} else if ((BAND_5G == band) &&
-				(WLAN_REG_IS_5GHZ_CH(tmp_chan)) &&
-				(!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
-				channel_list[*channel_count] = tmp_chan;
-				*channel_count += 1;
-			}
-		} else {
-			break;
-		}
-	}
-
-	if (*channel_count == 0) {
-		hdd_err("no valid channel found");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
- * @hdd_ctx: HDD context
- * @ap_adapter: AP adapter
- * @channel: Channel requested by userspace
- * @pre_cac_chan: Pointer to the pre CAC channel
- *
- * Validates the channel provided by userspace. If user provided channel 0,
- * a valid outdoor channel must be selected from the regulatory channel.
- *
- * Return: Zero on success and non zero value on error
- */
-static int wlan_hdd_validate_and_get_pre_cac_ch(struct hdd_context *hdd_ctx,
-						struct hdd_adapter *ap_adapter,
-						uint8_t channel,
-						uint8_t *pre_cac_chan)
-{
-	uint32_t i;
-	QDF_STATUS status;
-	uint32_t weight_len = 0;
-	uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
-	uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
-	uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
-	mac_handle_t mac_handle;
-
-	if (0 == channel) {
-		/* Channel is not obtained from PCL because PCL may not have
-		 * the entire channel list. For example: if SAP is up on
-		 * channel 6 and PCL is queried for the next SAP interface,
-		 * if SCC is preferred, the PCL will contain only the channel
-		 * 6. But, we are in need of a DFS channel. So, going with the
-		 * first channel from the valid channel list.
-		 */
-		status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
-				channel_list, &len);
-		if (QDF_IS_STATUS_ERROR(status)) {
-			hdd_err("Failed to get channel list");
-			return -EINVAL;
-		}
-		policy_mgr_update_with_safe_channel_list(hdd_ctx->hdd_psoc,
-				channel_list, &len, pcl_weights, weight_len);
-		for (i = 0; i < len; i++) {
-			if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
-						channel_list[i])) {
-				*pre_cac_chan = channel_list[i];
-				break;
-			}
-		}
-		if (*pre_cac_chan == 0) {
-			hdd_err("unable to find outdoor channel");
-			return -EINVAL;
-		}
-	} else {
-		/* Only when driver selects a channel, check is done for
-		 * unnsafe and NOL channels. When user provides a fixed channel
-		 * the user is expected to take care of this.
-		 */
-		mac_handle = hdd_ctx->mac_handle;
-		if (!sme_is_channel_valid(mac_handle, channel) ||
-			!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
-			hdd_err("Invalid channel for pre cac:%d", channel);
-			return -EINVAL;
-		}
-		*pre_cac_chan = channel;
-	}
-	hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
-	return 0;
-}
-
-/**
- * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
- * @channel: Channel option provided by userspace
- *
- * Sets the driver to the required hardware mode and start an adapter for
- * pre CAC which will mimic an AP.
- *
- * Return: Zero on success, non-zero value on error
- */
-int wlan_hdd_request_pre_cac(uint8_t channel)
-{
-	uint8_t pre_cac_chan = 0, *mac_addr;
-	struct hdd_context *hdd_ctx;
-	int ret;
-	struct hdd_adapter *ap_adapter, *pre_cac_adapter;
-	struct hdd_ap_ctx *hdd_ap_ctx;
-	QDF_STATUS status;
-	struct wiphy *wiphy;
-	struct net_device *dev;
-	struct cfg80211_chan_def chandef;
-	enum nl80211_channel_type channel_type;
-	uint32_t freq;
-	struct ieee80211_channel *chan;
-	mac_handle_t mac_handle;
-	bool val;
-
-	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
-	if (0 != wlan_hdd_validate_context(hdd_ctx))
-		return -EINVAL;
-
-	if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
-		hdd_err("pre cac not allowed in concurrency");
-		return -EINVAL;
-	}
-
-	ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
-	if (!ap_adapter) {
-		hdd_err("unable to get SAP adapter");
-		return -EINVAL;
-	}
-
-	mac_handle = hdd_ctx->mac_handle;
-	val = wlan_sap_is_pre_cac_active(mac_handle);
-	if (val) {
-		hdd_err("pre cac is already in progress");
-		return -EINVAL;
-	}
-
-	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
-	if (!hdd_ap_ctx) {
-		hdd_err("SAP context is NULL");
-		return -EINVAL;
-	}
-
-	if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
-				hdd_ap_ctx->operating_channel)) {
-		hdd_err("SAP is already on DFS channel:%d",
-			hdd_ap_ctx->operating_channel);
-		return -EINVAL;
-	}
-
-	if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operating_channel)) {
-		hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
-			hdd_ap_ctx->operating_channel);
-		return -EINVAL;
-	}
-
-	mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
-	if (!mac_addr) {
-		hdd_err("can't add virtual intf: Not getting valid mac addr");
-		return -EINVAL;
-	}
-
-	hdd_debug("channel:%d", channel);
-
-	ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
-							&pre_cac_chan);
-	if (ret != 0) {
-		hdd_err("can't validate pre-cac channel");
-		goto release_intf_addr_and_return_failure;
-	}
-
-	hdd_debug("starting pre cac SAP  adapter");
-
-	/* Starting a SAP adapter:
-	 * Instead of opening an adapter, we could just do a SME open session
-	 * for AP type. But, start BSS would still need an adapter.
-	 * So, this option is not taken.
-	 *
-	 * hdd open adapter is going to register this precac interface with
-	 * user space. This interface though exposed to user space will be in
-	 * DOWN state. Consideration was done to avoid this registration to the
-	 * user space. But, as part of SAP operations multiple events are sent
-	 * to user space. Some of these events received from unregistered
-	 * interface was causing crashes. So, retaining the registration.
-	 *
-	 * So, this interface would remain registered and will remain in DOWN
-	 * state for the CAC duration. We will add notes in the feature
-	 * announcement to not use this temporary interface for any activity
-	 * from user space.
-	 */
-	pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
-					   mac_addr, NET_NAME_UNKNOWN, true);
-	if (!pre_cac_adapter) {
-		hdd_err("error opening the pre cac adapter");
-		goto release_intf_addr_and_return_failure;
-	}
-
-	/*
-	 * This interface is internally created by the driver. So, no interface
-	 * up comes for this interface from user space and hence starting
-	 * the adapter internally.
-	 */
-	if (hdd_start_adapter(pre_cac_adapter)) {
-		hdd_err("error starting the pre cac adapter");
-		goto close_pre_cac_adapter;
-	}
-
-	hdd_debug("preparing for start ap/bss on the pre cac adapter");
-
-	wiphy = hdd_ctx->wiphy;
-	dev = pre_cac_adapter->dev;
-
-	/* Since this is only a dummy interface lets us use the IEs from the
-	 * other active SAP interface. In regular scenarios, these IEs would
-	 * come from the user space entity
-	 */
-	pre_cac_adapter->session.ap.beacon = qdf_mem_malloc(
-			sizeof(*ap_adapter->session.ap.beacon));
-	if (!pre_cac_adapter->session.ap.beacon) {
-		hdd_err("failed to alloc mem for beacon");
-		goto stop_close_pre_cac_adapter;
-	}
-	qdf_mem_copy(pre_cac_adapter->session.ap.beacon,
-			ap_adapter->session.ap.beacon,
-			sizeof(*pre_cac_adapter->session.ap.beacon));
-	pre_cac_adapter->session.ap.sap_config.ch_width_orig =
-			ap_adapter->session.ap.sap_config.ch_width_orig;
-	pre_cac_adapter->session.ap.sap_config.authType =
-			ap_adapter->session.ap.sap_config.authType;
-
-	/* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
-	 * to operate on the same bandwidth as that of the 2.4GHz operations.
-	 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
-	 */
-	switch (ap_adapter->session.ap.sap_config.ch_width_orig) {
-	case CH_WIDTH_20MHZ:
-		channel_type = NL80211_CHAN_HT20;
-		break;
-	case CH_WIDTH_40MHZ:
-		if (ap_adapter->session.ap.sap_config.sec_ch >
-				ap_adapter->session.ap.sap_config.channel)
-			channel_type = NL80211_CHAN_HT40PLUS;
-		else
-			channel_type = NL80211_CHAN_HT40MINUS;
-		break;
-	default:
-		channel_type = NL80211_CHAN_NO_HT;
-		break;
-	}
-
-	freq = cds_chan_to_freq(pre_cac_chan);
-	chan = ieee80211_get_channel(wiphy, freq);
-	if (!chan) {
-		hdd_err("channel converion failed");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	cfg80211_chandef_create(&chandef, chan, channel_type);
-
-	hdd_debug("orig width:%d channel_type:%d freq:%d",
-		ap_adapter->session.ap.sap_config.ch_width_orig,
-		channel_type, freq);
-	/*
-	 * Doing update after opening and starting pre-cac adapter will make
-	 * sure that driver won't do hardware mode change if there are any
-	 * initial hick-ups or issues in pre-cac adapter's configuration.
-	 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
-	 * connection update should result in DBS mode
-	 */
-	status = policy_mgr_update_and_wait_for_connection_update(
-					hdd_ctx->hdd_psoc,
-					ap_adapter->session_id,
-					pre_cac_chan,
-					POLICY_MGR_UPDATE_REASON_PRE_CAC);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("error in moving to DBS mode");
-		goto stop_close_pre_cac_adapter;
-	}
-
-
-	ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
-	if (0 != ret) {
-		hdd_err("failed to set channel");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
-			PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
-			NL80211_HIDDEN_SSID_NOT_IN_USE, false);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("start bss failed");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	/*
-	 * The pre cac status is set here. But, it would not be reset explicitly
-	 * anywhere, since after the pre cac success/failure, the pre cac
-	 * adapter itself would be removed.
-	 */
-	ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, mac_handle);
-	if (0 != ret) {
-		hdd_err("failed to set pre cac status");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
-				hdd_ap_ctx->operating_channel);
-	if (0 != ret) {
-		hdd_err("failed to set channel before pre cac");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	ap_adapter->pre_cac_chan = pre_cac_chan;
-
-	return 0;
-
-stop_close_pre_cac_adapter:
-	hdd_stop_adapter(hdd_ctx, pre_cac_adapter);
-	qdf_mem_free(pre_cac_adapter->session.ap.beacon);
-	pre_cac_adapter->session.ap.beacon = NULL;
-close_pre_cac_adapter:
-	hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
-release_intf_addr_and_return_failure:
-	/*
-	 * Release the interface address as the adapter
-	 * failed to start, if you don't release then next
-	 * adapter which is trying to come wouldn't get valid
-	 * mac address. Remember we have limited pool of mac addresses
-	 */
-	wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
-	return -EINVAL;
-}
-
 static const struct nla_policy
 wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
@@ -10181,13 +7633,6 @@
 	[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
 };
 
-static const struct nla_policy
-wlan_hdd_set_limit_off_channel_param_policy
-[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX + 1] = {
-	[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS] = {.type = NLA_U8 },
-	[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START] = {.type = NLA_U8 },
-};
-
 /**
  * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
  * @wiphy: Pointer to wireless phy
@@ -11753,51 +9198,6 @@
 	return ret;
 }
 
-static u32 hdd_sar_wmi_to_nl_enable(uint32_t wmi_value)
-{
-	switch (wmi_value) {
-	default:
-	case WMI_SAR_FEATURE_OFF:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
-	case WMI_SAR_FEATURE_ON_SET_0:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
-	case WMI_SAR_FEATURE_ON_SET_1:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1;
-	case WMI_SAR_FEATURE_ON_SET_2:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2;
-	case WMI_SAR_FEATURE_ON_SET_3:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3;
-	case WMI_SAR_FEATURE_ON_SET_4:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
-	case WMI_SAR_FEATURE_ON_USER_DEFINED:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER;
-	case WMI_SAR_FEATURE_ON_SAR_V2_0:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
-	}
-}
-
-static u32 hdd_sar_wmi_to_nl_band(uint32_t wmi_value)
-{
-	switch (wmi_value) {
-	default:
-	case WMI_SAR_2G_ID:
-		return HDD_NL80211_BAND_2GHZ;
-	case WMI_SAR_5G_ID:
-		return HDD_NL80211_BAND_5GHZ;
-	}
-}
-
-static u32 hdd_sar_wmi_to_nl_modulation(uint32_t wmi_value)
-{
-	switch (wmi_value) {
-	default:
-	case WMI_SAR_MOD_CCK:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK;
-	case WMI_SAR_MOD_OFDM:
-		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM;
-	}
-}
-
 static const struct nla_policy
 sar_limits_policy[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
@@ -11809,260 +9209,6 @@
 	[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX] = {.type = NLA_U32},
 };
 
-#define WLAN_WAIT_TIME_SAR 5000
-
-/**
- * hdd_sar_context - hdd sar context
- * @event: sar limit event
- */
-struct hdd_sar_context {
-	struct sar_limit_event event;
-};
-
-/**
- * hdd_sar_cb () - sar response message handler
- * @cookie: hdd request cookie
- * @event: sar response event
- *
- * Return: none
- */
-static void hdd_sar_cb(void *cookie,
-		       struct sar_limit_event *event)
-{
-	struct osif_request *request;
-	struct hdd_sar_context *context;
-
-	hdd_enter();
-
-	if (!event) {
-		hdd_err("response is NULL");
-		return;
-	}
-
-	request = osif_request_get(cookie);
-	if (!request) {
-		hdd_debug("Obsolete request");
-		return;
-	}
-
-	context = osif_request_priv(request);
-	context->event = *event;
-	osif_request_complete(request);
-	osif_request_put(request);
-
-	hdd_exit();
-}
-
-static uint32_t hdd_sar_get_response_len(const struct sar_limit_event *event)
-{
-	uint32_t len;
-	uint32_t row_len;
-
-	len = NLMSG_HDRLEN;
-	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE */
-	len += NLA_HDRLEN + sizeof(u32);
-	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS */
-	len += NLA_HDRLEN + sizeof(u32);
-
-	/* nest */
-	row_len = NLA_HDRLEN;
-	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND */
-	row_len += NLA_HDRLEN + sizeof(u32);
-	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN */
-	row_len += NLA_HDRLEN + sizeof(u32);
-	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION */
-	row_len += NLA_HDRLEN + sizeof(u32);
-	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT */
-	row_len += NLA_HDRLEN + sizeof(u32);
-
-	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC */
-	len += NLA_HDRLEN + (row_len * event->num_limit_rows);
-
-	return len;
-}
-
-static int hdd_sar_fill_response(struct sk_buff *skb,
-				 const struct sar_limit_event *event)
-{
-	int errno;
-	u32 value;
-	u32 attr;
-	struct nlattr *nla_spec_attr;
-	struct nlattr *nla_row_attr;
-	uint32_t row;
-	const struct sar_limit_event_row *event_row;
-
-	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE;
-	value = hdd_sar_wmi_to_nl_enable(event->sar_enable);
-	errno = nla_put_u32(skb, attr, value);
-	if (errno)
-		return errno;
-
-	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS;
-	value = event->num_limit_rows;
-	errno = nla_put_u32(skb, attr, value);
-	if (errno)
-		return errno;
-
-	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC;
-	nla_spec_attr = nla_nest_start(skb, attr);
-	if (!nla_spec_attr)
-		return -EINVAL;
-
-	for (row = 0, event_row = event->sar_limit_row;
-	     row < event->num_limit_rows;
-	     row++, event_row++) {
-		nla_row_attr = nla_nest_start(skb, attr);
-		if (!nla_row_attr)
-			return -EINVAL;
-
-		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND;
-		value = hdd_sar_wmi_to_nl_band(event_row->band_id);
-		errno = nla_put_u32(skb, attr, value);
-		if (errno)
-			return errno;
-
-		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN;
-		value = event_row->chain_id;
-		errno = nla_put_u32(skb, attr, value);
-		if (errno)
-			return errno;
-
-		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION;
-		value = hdd_sar_wmi_to_nl_modulation(event_row->mod_id);
-		errno = nla_put_u32(skb, attr, value);
-		if (errno)
-			return errno;
-
-		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT;
-		value = event_row->limit_value;
-		errno = nla_put_u32(skb, attr, value);
-		if (errno)
-			return errno;
-
-		nla_nest_end(skb, nla_row_attr);
-	}
-	nla_nest_end(skb, nla_spec_attr);
-
-	return 0;
-}
-
-static int hdd_sar_send_response(struct wiphy *wiphy,
-				 const struct sar_limit_event *event)
-{
-	uint32_t len;
-	struct sk_buff *skb;
-	int errno;
-
-	len = hdd_sar_get_response_len(event);
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
-	if (!skb) {
-		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
-		return -ENOMEM;
-	}
-
-	errno = hdd_sar_fill_response(skb, event);
-	if (errno) {
-		kfree_skb(skb);
-		return errno;
-	}
-
-	return cfg80211_vendor_cmd_reply(skb);
-}
-
-/**
- * __wlan_hdd_get_sar_power_limits() - Get SAR power limits
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Length of @data
- *
- * This function is used to retrieve Specific Absorption Rate limit specs.
- *
- * Return: 0 on success, negative errno on failure
- */
-static int __wlan_hdd_get_sar_power_limits(struct wiphy *wiphy,
-					   struct wireless_dev *wdev,
-					   const void *data, int data_len)
-{
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct osif_request *request;
-	struct hdd_sar_context *context;
-	mac_handle_t mac_handle;
-	void *cookie;
-	QDF_STATUS status;
-	int ret;
-	static const struct osif_request_params params = {
-		.priv_size = sizeof(*context),
-		.timeout_ms = WLAN_WAIT_TIME_SAR,
-	};
-
-	hdd_enter();
-
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EPERM;
-	}
-
-	if (wlan_hdd_validate_context(hdd_ctx))
-		return -EINVAL;
-
-	request = osif_request_alloc(&params);
-	if (!request) {
-		hdd_err("Request allocation failure");
-		return -ENOMEM;
-	}
-
-	cookie = osif_request_cookie(request);
-
-	mac_handle = hdd_ctx->mac_handle;
-	status = sme_get_sar_power_limits(mac_handle, hdd_sar_cb, cookie);
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
-		hdd_err("Unable to post sar message");
-		ret = -EINVAL;
-		goto cleanup;
-	}
-
-	ret = osif_request_wait_for_response(request);
-	if (ret) {
-		hdd_err("Target response timed out");
-		goto cleanup;
-	}
-
-	context = osif_request_priv(request);
-	ret = hdd_sar_send_response(wiphy, &context->event);
-
-cleanup:
-	osif_request_put(request);
-
-	return ret;
-}
-
-/**
- * wlan_hdd_cfg80211_get_sar_power_limits() - Get SAR power limits
- * @wiphy: Pointer to wireless phy
- * @wdev: Pointer to wireless device
- * @data: Pointer to data
- * @data_len: Length of @data
- *
- * Wrapper function of __wlan_hdd_cfg80211_get_sar_power_limits()
- *
- * Return: 0 on success, negative errno on failure
- */
-static int wlan_hdd_cfg80211_get_sar_power_limits(struct wiphy *wiphy,
-						  struct wireless_dev *wdev,
-						  const void *data,
-						  int data_len)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_get_sar_power_limits(wiphy, wdev, data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
 /**
  * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
  * @wiphy: Pointer to wireless phy
@@ -13527,21 +10673,6 @@
 		 hdd_ctx->bt_vo_active);
 }
 
-
-/**
- * wlan_hdd_is_bt_in_progress() - check if bt activity is in progress
- * @hdd_ctx : HDD context
- *
- * Return: true if BT activity is in progress else false
- */
-static inline bool wlan_hdd_is_bt_in_progress(struct hdd_context *hdd_ctx)
-{
-	if (hdd_ctx->bt_a2dp_active || hdd_ctx->bt_vo_active)
-		return true;
-
-	return false;
-}
-
 struct chain_rssi_priv {
 	struct chain_rssi_result chain_rssi;
 };
@@ -13734,331 +10865,6 @@
 }
 
 /**
- * __wlan_hdd_cfg80211_set_limit_offchan_param() - set limit off-channel cmd
- * parameters
- * @wiphy: pointer to wireless wiphy structure.
- * @wdev: pointer to wireless_dev structure.
- * @data: pointer to limit off-channel command parameters.
- * @data_len: the length in byte of  limit off-channel command parameters.
- *
- * This is called when application wants to limit the off channel time due to
- * active voip traffic.
- *
- * Return: An error code or 0 on success.
- */
-static int __wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
-		struct wireless_dev *wdev, const void *data, int data_len)
-{
-	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX + 1];
-	struct net_device   *dev = wdev->netdev;
-	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	int ret = 0;
-	uint8_t tos;
-	uint8_t tos_status;
-
-	hdd_enter();
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret < 0)
-		return ret;
-
-	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX,
-				 data, data_len,
-				 wlan_hdd_set_limit_off_channel_param_policy)) {
-		hdd_err("Invalid ATTR");
-		return -EINVAL;
-	}
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS]) {
-		hdd_err("attr tos failed");
-		goto fail;
-	}
-
-	tos = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS]);
-	if (tos >= HDD_MAX_AC) {
-		hdd_err("tos value %d exceeded Max value %d",
-			tos, HDD_MAX_AC);
-		goto fail;
-	}
-	hdd_debug("tos %d", tos);
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START]) {
-		hdd_err("attr tos active failed");
-		goto fail;
-	}
-	tos_status = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START]);
-
-	hdd_debug("tos status %d", tos_status);
-	ret = hdd_set_limit_off_chan_for_tos(adapter, tos, tos_status);
-
-fail:
-	return ret;
-}
-
-/**
- * wlan_hdd_cfg80211_set_limit_offchan_param() - set limit off-channel cmd
- * parameters
- * @wiphy: pointer to wireless wiphy structure.
- * @wdev: pointer to wireless_dev structure.
- * @data: pointer to limit off-channel command parameters.
- * @data_len: the length in byte of  limit off-channel command parameters.
- *
- * This is called when application wants to limit the off channel time due to
- * active voip traffic.
- *
- * Return: An error code or 0 on success.
- */
-static int wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
-		struct wireless_dev *wdev,
-		const void *data, int data_len)
-
-{
-	int ret = 0;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_set_limit_offchan_param(wiphy, wdev, data,
-			data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-/**
- * wlan_hdd_fill_btm_resp() - Fill bss candidate response buffer
- * @reply_skb : pointer to reply_skb
- * @info : bss candidate information
- * @index : attribute type index for nla_next_start()
- *
- * Return : 0 on success and errno on failure
- */
-static int wlan_hdd_fill_btm_resp(struct sk_buff *reply_skb,
-				  struct bss_candidate_info *info,
-				  int index)
-{
-	struct nlattr *attr;
-
-	attr = nla_nest_start(reply_skb, index);
-	if (!attr) {
-		hdd_err("nla_nest_start failed");
-		kfree_skb(reply_skb);
-		return -EINVAL;
-	}
-
-	if (nla_put(reply_skb,
-		  QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID,
-		  ETH_ALEN, info->bssid.bytes) ||
-	    nla_put_u32(reply_skb,
-		 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS,
-		 info->status)) {
-		hdd_err("nla_put failed");
-		kfree_skb(reply_skb);
-		return -EINVAL;
-	}
-
-	nla_nest_end(reply_skb, attr);
-
-	return 0;
-}
-
-/**
- * __wlan_hdd_cfg80211_fetch_bss_transition_status() - fetch bss transition
- * status
- * @wiphy : WIPHY structure pointer
- * @wdev : Wireless device structure pointer
- * @data : Pointer to the data received
- * @data_len : Length of the data received
- *
- * This function is used to fetch transition status for candidate bss. The
- * transition status is either accept or reason for reject.
- *
- * Return : 0 on success and errno on failure
- */
-static int __wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data, int data_len)
-{
-	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
-	struct nlattr *tb_msg[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1];
-	uint8_t transition_reason;
-	struct nlattr *attr;
-	struct sk_buff *reply_skb;
-	int rem, j;
-	int ret;
-	bool is_bt_in_progress;
-	struct bss_candidate_info candidate_info[MAX_CANDIDATE_INFO];
-	uint16_t nof_candidates, i = 0;
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct net_device *dev = wdev->netdev;
-	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	struct hdd_station_ctx *hdd_sta_ctx =
-					WLAN_HDD_GET_STATION_CTX_PTR(adapter);
-	mac_handle_t mac_handle;
-
-	const struct nla_policy
-	btm_params_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
-		[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON] = {
-							.type = NLA_U8},
-		[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO] = {
-							.type = NLA_NESTED},
-	};
-	const struct nla_policy
-	btm_cand_list_policy[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1]
-		= {[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID] = {
-						.len = QDF_MAC_ADDR_SIZE},
-		   [QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS] = {
-							.type = NLA_U32},
-		};
-
-	hdd_enter();
-
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EINVAL;
-	}
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	if (adapter->device_mode != QDF_STA_MODE ||
-	    hdd_sta_ctx->conn_info.connState != eConnectionState_Associated) {
-		hdd_err("Command is either not invoked for STA mode (device mode: %d) or STA is not associated (Connection state: %d)",
-			adapter->device_mode, hdd_sta_ctx->conn_info.connState);
-		return -EINVAL;
-	}
-
-	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
-				      data_len, btm_params_policy);
-	if (ret) {
-		hdd_err("Attribute parse failed");
-		return -EINVAL;
-	}
-
-	if (!tb[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON] ||
-	    !tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO]) {
-		hdd_err("Missing attributes");
-		return -EINVAL;
-	}
-
-	transition_reason = nla_get_u8(
-			    tb[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON]);
-
-	nla_for_each_nested(attr,
-			    tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO],
-			    rem) {
-		ret = wlan_cfg80211_nla_parse_nested(tb_msg,
-				    QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX,
-				    attr, btm_cand_list_policy);
-		if (ret) {
-			hdd_err("Attribute parse failed");
-			return -EINVAL;
-		}
-
-		if (!tb_msg[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]) {
-			hdd_err("Missing BSSID attribute");
-			return -EINVAL;
-		}
-
-		qdf_mem_copy((void *)candidate_info[i].bssid.bytes,
-			     nla_data(tb_msg[
-			     QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]),
-			     QDF_MAC_ADDR_SIZE);
-		i++;
-		if (i == MAX_CANDIDATE_INFO)
-			break;
-	}
-
-	/*
-	 * Determine status for each candidate and fill in the status field.
-	 * Also arrange the candidates in the order of preference.
-	 */
-	nof_candidates = i;
-
-	is_bt_in_progress = wlan_hdd_is_bt_in_progress(hdd_ctx);
-
-	mac_handle = hdd_ctx->mac_handle;
-	ret = sme_get_bss_transition_status(mac_handle, transition_reason,
-					    &hdd_sta_ctx->conn_info.bssId,
-					    candidate_info,
-					    nof_candidates,
-					    is_bt_in_progress);
-	if (ret)
-		return -EINVAL;
-
-	/* Prepare the reply and send it to userspace */
-	reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
-			((QDF_MAC_ADDR_SIZE + sizeof(uint32_t)) *
-			 nof_candidates) + NLMSG_HDRLEN);
-	if (!reply_skb) {
-		hdd_err("reply buffer alloc failed");
-		return -ENOMEM;
-	}
-
-	attr = nla_nest_start(reply_skb,
-			      QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO);
-	if (!attr) {
-		hdd_err("nla_nest_start failed");
-		kfree_skb(reply_skb);
-		return -EINVAL;
-	}
-
-	/*
-	 * Order candidates as - accepted candidate list followed by rejected
-	 * candidate list
-	 */
-	for (i = 0, j = 0; i < nof_candidates; i++) {
-		/* copy accepted candidate list */
-		if (candidate_info[i].status == QCA_STATUS_ACCEPT) {
-			if (wlan_hdd_fill_btm_resp(reply_skb,
-						   &candidate_info[i], j))
-				return -EINVAL;
-			j++;
-		}
-	}
-	for (i = 0; i < nof_candidates; i++) {
-		/* copy rejected candidate list */
-		if (candidate_info[i].status != QCA_STATUS_ACCEPT) {
-			if (wlan_hdd_fill_btm_resp(reply_skb,
-						   &candidate_info[i], j))
-				return -EINVAL;
-			j++;
-		}
-	}
-	nla_nest_end(reply_skb, attr);
-
-	hdd_exit();
-
-	return cfg80211_vendor_cmd_reply(reply_skb);
-}
-
-/**
- * wlan_hdd_cfg80211_fetch_bss_transition_status() - fetch bss transition status
- * @wiphy : WIPHY structure pointer
- * @wdev : Wireless device structure pointer
- * @data : Pointer to the data received
- * @data_len : Length of the data received
- *
- * This function is used to fetch transition status for candidate bss. The
- * transition status is either accept or reason for reject.
- *
- * Return : 0 on success and errno on failure
- */
-static int wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
-						struct wireless_dev *wdev,
-						const void *data, int data_len)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_cfg80211_fetch_bss_transition_status(wiphy, wdev,
-							      data, data_len);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-/**
  * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
  * @skb: Pointer to skb
  * @info: mac mode info
@@ -14388,12 +11194,9 @@
 			WIPHY_VENDOR_CMD_NEED_RUNNING,
 		.doit = wlan_hdd_cfg80211_set_scanning_mac_oui
 	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
-		.doit = wlan_hdd_cfg80211_get_concurrency_matrix
-	},
+
+	FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
+
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
@@ -14410,14 +11213,9 @@
 			WIPHY_VENDOR_CMD_NEED_RUNNING,
 		.doit = wlan_hdd_cfg80211_handle_wisa_cmd
 	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-			WIPHY_VENDOR_CMD_NEED_NETDEV |
-			WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = hdd_cfg80211_get_station_cmd
-	},
+
+	FEATURE_STATION_INFO_VENDOR_COMMANDS
+
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
@@ -14561,14 +11359,8 @@
 		.doit = wlan_hdd_cfg80211_offloaded_packets
 	},
 #endif
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-			WIPHY_VENDOR_CMD_NEED_NETDEV |
-			WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_monitor_rssi
-	},
+	FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
+
 #ifdef WLAN_NS_OFFLOAD
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
@@ -14679,14 +11471,9 @@
 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
 		.doit = wlan_hdd_cfg80211_get_link_properties
 	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-				 WIPHY_VENDOR_CMD_NEED_NETDEV |
-				 WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_set_ota_test
-	},
+
+	FEATURE_OTA_TEST_VENDOR_COMMANDS
+
 #ifdef FEATURE_LFR_SUBNET_DETECTION
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
@@ -14697,23 +11484,9 @@
 		.doit = wlan_hdd_cfg80211_set_gateway_params
 	},
 #endif /* FEATURE_LFR_SUBNET_DETECTION */
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-				 WIPHY_VENDOR_CMD_NEED_NETDEV |
-				 WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_txpower_scale
-	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd =
-			QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-				 WIPHY_VENDOR_CMD_NEED_NETDEV |
-				 WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_txpower_scale_decr_db
-	},
+
+	FEATURE_TX_POWER_VENDOR_COMMANDS
+
 #ifdef FEATURE_WLAN_APF
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
@@ -14758,33 +11531,10 @@
 			WIPHY_VENDOR_CMD_NEED_RUNNING,
 		.doit = wlan_hdd_cfg80211_sap_configuration_set
 	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd =
-			QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-				WIPHY_VENDOR_CMD_NEED_NETDEV |
-				WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_p2p_lo_start
-	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd =
-			QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-				WIPHY_VENDOR_CMD_NEED_NETDEV |
-				WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_p2p_lo_stop
-	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd =
-			QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-				WIPHY_VENDOR_CMD_NEED_NETDEV |
-				WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_conditional_chan_switch
-	},
+
+	FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
+
+	FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
 #ifdef WLAN_FEATURE_NAN_DATAPATH
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
@@ -14857,13 +11607,8 @@
 		.doit = wlan_hdd_cfg80211_configure_tdls_mode
 	},
 #endif
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-			 WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_get_sar_power_limits
-	},
+	FEATURE_SAR_LIMITS_VENDOR_COMMANDS
+
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
@@ -14904,15 +11649,8 @@
 			WIPHY_VENDOR_CMD_NEED_RUNNING,
 		.doit = wlan_hdd_cfg80211_get_nud_stats
 	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd =
-			QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-			 WIPHY_VENDOR_CMD_NEED_NETDEV |
-			 WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_fetch_bss_transition_status
-	},
+
+	FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
 	FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
 #ifdef WLAN_UMAC_CONVERGENCE
 	COMMON_VENDOR_COMMANDS
@@ -14927,14 +11665,8 @@
 			WIPHY_VENDOR_CMD_NEED_RUNNING,
 		.doit = wlan_hdd_cfg80211_get_chain_rssi
 	},
-	{
-		.info.vendor_id = QCA_NL80211_VENDOR_ID,
-		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS,
-		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
-			WIPHY_VENDOR_CMD_NEED_NETDEV |
-			WIPHY_VENDOR_CMD_NEED_RUNNING,
-		.doit = wlan_hdd_cfg80211_set_limit_offchan_param
-	},
+
+	FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
 
 };
 
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index bca4157..2eac435 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -369,19 +369,6 @@
 void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
 				struct rso_cmd_status *rso_status);
 
-/**
- * hdd_rssi_threshold_breached() - rssi breached NL event
- * @hdd_handle: HDD handle
- * @data: rssi breached event data
- *
- * This function reads the rssi breached event %data and fill in the skb with
- * NL attributes and send up the NL event.
- *
- * Return: none
- */
-void hdd_rssi_threshold_breached(hdd_handle_t hdd_handle,
-				 struct rssi_breach_event *data);
-
 struct cfg80211_bss *
 wlan_hdd_cfg80211_update_bss_list(struct hdd_adapter *adapter,
 				  tSirMacAddr bssid);
diff --git a/core/hdd/src/wlan_hdd_concurrency_matrix.c b/core/hdd/src/wlan_hdd_concurrency_matrix.c
new file mode 100644
index 0000000..bb96208
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_concurrency_matrix.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_concurrency_matrix.c
+ *
+ * WLAN concurrency matrix functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <wlan_hdd_concurrency_matrix.h>
+
+#define CDS_MAX_FEATURE_SET   8
+#define MAX_CONCURRENT_MATRIX \
+	QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX
+#define MATRIX_CONFIG_PARAM_SET_SIZE_MAX \
+	QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX
+static const struct nla_policy
+wlan_hdd_get_concurrency_matrix_policy[MAX_CONCURRENT_MATRIX + 1] = {
+	[MATRIX_CONFIG_PARAM_SET_SIZE_MAX] = {.type = NLA_U32},
+};
+
+/**
+ * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
+ * @wiphy: pointer phy adapter
+ * @wdev: pointer to wireless device structure
+ * @data: pointer to data buffer
+ * @data_len: length of data
+ *
+ * This routine will give concurrency matrix
+ *
+ * Return: int status code
+ */
+static int
+__wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
+					   struct wireless_dev *wdev,
+					   const void *data,
+					   int data_len)
+{
+	uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
+	uint8_t i, feature_sets, max_feature_sets;
+	struct nlattr *tb[MAX_CONCURRENT_MATRIX + 1];
+	struct sk_buff *reply_skb;
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	int ret;
+
+	hdd_enter_dev(wdev->netdev);
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (wlan_cfg80211_nla_parse(tb, MAX_CONCURRENT_MATRIX, data, data_len,
+				    wlan_hdd_get_concurrency_matrix_policy)) {
+		hdd_err("Invalid ATTR");
+		return -EINVAL;
+	}
+
+	/* Parse and fetch max feature set */
+	if (!tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
+		hdd_err("Attr max feature set size failed");
+		return -EINVAL;
+	}
+	max_feature_sets = nla_get_u32(tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
+	hdd_debug("Max feature set size: %d", max_feature_sets);
+
+	/* Fill feature combination matrix */
+	feature_sets = 0;
+	feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
+						WIFI_FEATURE_P2P;
+	feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
+						WIFI_FEATURE_NAN;
+	/* Add more feature combinations here */
+
+	feature_sets = QDF_MIN(feature_sets, max_feature_sets);
+	hdd_debug("Number of feature sets: %d", feature_sets);
+	hdd_debug("Feature set matrix");
+	for (i = 0; i < feature_sets; i++)
+		hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
+
+	reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
+			sizeof(u32) * feature_sets + NLMSG_HDRLEN);
+	if (!reply_skb) {
+		hdd_err("Feature set matrix: buffer alloc fail");
+		return -ENOMEM;
+	}
+
+	if (nla_put_u32(reply_skb,
+		QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
+		feature_sets) ||
+	    nla_put(reply_skb,
+		    QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
+		    sizeof(u32) * feature_sets,
+		    feature_set_matrix)) {
+		hdd_err("nla put fail");
+		kfree_skb(reply_skb);
+		return -EINVAL;
+	}
+	return cfg80211_vendor_cmd_reply(reply_skb);
+}
+
+#undef MAX_CONCURRENT_MATRIX
+#undef MATRIX_CONFIG_PARAM_SET_SIZE_MAX
+
+int wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
+					     struct wireless_dev *wdev,
+					     const void *data,
+					     int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
+							 data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_concurrency_matrix.h b/core/hdd/src/wlan_hdd_concurrency_matrix.h
new file mode 100644
index 0000000..1bdc6f7
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_concurrency_matrix.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_CONCURRENCY_MATRIX_H
+#define __WLAN_HDD_CONCURRENCY_MATRIX_H
+
+/**
+ * DOC: wlan_hdd_concurrency_matrix_h
+ *
+ * WLAN Host Device Driver concurrency matrix API specification
+ */
+
+#ifdef FEATURE_CONCURRENCY_MATRIX
+/**
+ * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
+ * @wiphy:   pointer to wireless wiphy structure.
+ * @wdev:    pointer to wireless_dev structure.
+ * @data:    Pointer to the data to be passed via vendor interface
+ * @data_len:Length of the data to be passed
+ *
+ * Retrieves the concurrency feature set matrix
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
+					     struct wireless_dev *wdev,
+					     const void *data,
+					     int data_len);
+
+#define FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS			\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,\
+	.doit = wlan_hdd_cfg80211_get_concurrency_matrix		\
+},
+#else /* FEATURE_CONCURRENCY_MATRIX */
+#define FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
+#endif /* FEATURE_CONCURRENCY_MATRIX */
+
+#endif /* __WLAN_HDD_CONCURRENCY_MATRIX_H */
+
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 6e86046..effbe3a 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -138,6 +138,7 @@
 #include "wlan_mlme_main.h"
 #include "wlan_p2p_cfg_api.h"
 #include "wlan_tdls_cfg_api.h"
+#include <wlan_hdd_rssi_monitor.h>
 
 #ifdef CNSS_GENL
 #include <net/cnss_nl.h>
@@ -300,13 +301,6 @@
 	[QDF_MODULE_ID_CONFIG] = {QDF_TRACE_LEVEL_ALL},
 };
 
-int limit_off_chan_tbl[HDD_MAX_AC][HDD_MAX_OFF_CHAN_ENTRIES] = {
-	{ HDD_AC_BK_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_BK },
-	{ HDD_AC_BE_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_BE },
-	{ HDD_AC_VI_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_VI },
-	{ HDD_AC_VO_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_VO },
-};
-
 struct notifier_block hdd_netdev_notifier;
 struct notifier_block system_reboot_notifier;
 
@@ -14130,76 +14124,6 @@
 }
 
 /**
- * hdd_set_limit_off_chan_for_tos() - set limit off-channel command parameters
- * @adapter - HDD adapter
- * @tos - type of service
- * @status - status of the traffic
- *
- * Return: 0 on success and non zero value on failure
- */
-
-int hdd_set_limit_off_chan_for_tos(struct hdd_adapter *adapter, enum tos tos,
-		bool is_tos_active)
-{
-	int ac_bit;
-	struct hdd_context *hdd_ctx;
-	uint32_t max_off_chan_time = 0;
-	QDF_STATUS status;
-	int ret;
-
-	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	ret = wlan_hdd_validate_context(hdd_ctx);
-
-	if (ret < 0) {
-		hdd_err("failed to set limit off chan params");
-		return ret;
-	}
-
-	ac_bit = limit_off_chan_tbl[tos][HDD_AC_BIT_INDX];
-
-	if (is_tos_active)
-		adapter->active_ac |= ac_bit;
-	else
-		adapter->active_ac &= ~ac_bit;
-
-	if (adapter->active_ac) {
-		if (adapter->active_ac & HDD_AC_VO_BIT) {
-			max_off_chan_time =
-				limit_off_chan_tbl[TOS_VO][HDD_DWELL_TIME_INDX];
-			policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
-					PM_LATENCY);
-		} else if (adapter->active_ac & HDD_AC_VI_BIT) {
-			max_off_chan_time =
-				limit_off_chan_tbl[TOS_VI][HDD_DWELL_TIME_INDX];
-			policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
-					PM_LATENCY);
-		} else {
-			/*ignore this command if only BE/BK is active */
-			is_tos_active = false;
-			policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
-					hdd_ctx->config->conc_system_pref);
-		}
-	} else {
-		/* No active tos */
-		policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
-				hdd_ctx->config->conc_system_pref);
-	}
-
-	status = sme_send_limit_off_channel_params(hdd_ctx->mac_handle,
-						   adapter->session_id,
-						   is_tos_active,
-						   max_off_chan_time,
-						   hdd_ctx->config->nRestTimeConc,
-						   true);
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
-		hdd_err("failed to set limit off chan params");
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-/**
  * hdd_reset_limit_off_chan() - reset limit off-channel command parameters
  * @adapter - HDD adapter
  *
diff --git a/core/hdd/src/wlan_hdd_ota_test.c b/core/hdd/src/wlan_hdd_ota_test.c
new file mode 100644
index 0000000..ef54c99
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_ota_test.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_ota_test.c
+ *
+ * WLAN OTA test functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <sme_power_save_api.h>
+#include <wlan_hdd_ota_test.h>
+
+static const struct
+nla_policy
+qca_wlan_vendor_ota_test_policy
+[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
+};
+
+/**
+ * __wlan_hdd_cfg80211_set_ota_test() - enable/disable OTA test
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data,
+					    int data_len)
+{
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
+	uint8_t ota_enable = 0;
+	QDF_STATUS status;
+	uint32_t current_roam_state;
+	mac_handle_t mac_handle;
+
+	hdd_enter_dev(dev);
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	if (wlan_hdd_validate_context(hdd_ctx) != 0)
+		return -EINVAL;
+
+	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
+				    data, data_len,
+				    qca_wlan_vendor_ota_test_policy)) {
+		hdd_err("invalid attr");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
+		hdd_err("attr ota test failed");
+		return -EINVAL;
+	}
+
+	ota_enable = nla_get_u8(
+		tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
+
+	hdd_debug(" OTA test enable = %d", ota_enable);
+	if (ota_enable != 1) {
+		hdd_err("Invalid value, only enable test mode is supported!");
+		return -EINVAL;
+	}
+
+	mac_handle = hdd_ctx->mac_handle;
+	current_roam_state =
+		sme_get_current_roam_state(mac_handle, adapter->session_id);
+	status = sme_stop_roaming(mac_handle, adapter->session_id,
+				  eCsrHddIssued);
+	if (status != QDF_STATUS_SUCCESS) {
+		hdd_err("Enable/Disable roaming failed");
+		return -EINVAL;
+	}
+
+	status = sme_ps_enable_disable(mac_handle, adapter->session_id,
+				       SME_PS_DISABLE);
+	if (status != QDF_STATUS_SUCCESS) {
+		hdd_err("Enable/Disable power save failed");
+		/* restore previous roaming setting */
+		if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
+		    current_roam_state == eCSR_ROAMING_STATE_JOINED)
+			status = sme_start_roaming(mac_handle,
+						   adapter->session_id,
+						   eCsrHddIssued);
+		else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
+			 current_roam_state == eCSR_ROAMING_STATE_IDLE)
+			status = sme_stop_roaming(mac_handle,
+						  adapter->session_id,
+						  eCsrHddIssued);
+
+		if (status != QDF_STATUS_SUCCESS)
+			hdd_err("Restoring roaming state failed");
+
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
+				   struct wireless_dev *wdev,
+				   const void *data,
+				   int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_ota_test.h b/core/hdd/src/wlan_hdd_ota_test.h
new file mode 100644
index 0000000..9d950b8
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_ota_test.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_OTA_TEST_H
+#define __WLAN_HDD_OTA_TEST_H
+
+/**
+ * DOC: wlan_hdd_ota_test_h
+ *
+ * WLAN Host Device Driver OTA test API specification
+ */
+
+#ifdef FEATURE_OTA_TEST
+/**
+ * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
+				   struct wireless_dev *wdev,
+				   const void *data,
+				   int data_len);
+
+#define FEATURE_OTA_TEST_VENDOR_COMMANDS			\
+{								\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,		\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |			\
+			 WIPHY_VENDOR_CMD_NEED_NETDEV |		\
+			 WIPHY_VENDOR_CMD_NEED_RUNNING,		\
+	.doit = wlan_hdd_cfg80211_set_ota_test			\
+},
+#else /* FEATURE_OTA_TEST */
+#define FEATURE_OTA_TEST_VENDOR_COMMANDS
+#endif /* FEATURE_OTA_TEST */
+
+#endif /* __WLAN_HDD_OTA_TEST_H */
+
diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c
index 2027cc1..580223a 100644
--- a/core/hdd/src/wlan_hdd_p2p.c
+++ b/core/hdd/src/wlan_hdd_p2p.c
@@ -1040,70 +1040,6 @@
 	return qdf_status_to_os_return(status);
 }
 
-int wlan_hdd_listen_offload_start(struct hdd_adapter *adapter,
-	struct sir_p2p_lo_start *params)
-{
-	struct wlan_objmgr_psoc *psoc;
-	struct p2p_lo_start lo_start;
-	struct hdd_context *hdd_ctx;
-	QDF_STATUS status;
-
-	if (!adapter || !params) {
-		hdd_err("null param, adapter:%pK, params:%pK",
-			adapter, params);
-		return -EINVAL;
-	}
-
-	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	psoc = hdd_ctx->hdd_psoc;
-	if (!psoc) {
-		hdd_err("psoc is null");
-		return -EINVAL;
-	}
-
-	lo_start.vdev_id = params->vdev_id;
-	lo_start.ctl_flags = params->ctl_flags;
-	lo_start.freq = params->freq;
-	lo_start.period = params->period;
-	lo_start.interval = params->interval;
-	lo_start.count = params->count;
-	lo_start.device_types = params->device_types;
-	lo_start.dev_types_len = params->dev_types_len;
-	lo_start.probe_resp_tmplt = params->probe_resp_tmplt;
-	lo_start.probe_resp_len = params->probe_resp_len;
-
-	status = ucfg_p2p_lo_start(psoc, &lo_start);
-	hdd_debug("p2p listen offload start, status:%d", status);
-
-	return qdf_status_to_os_return(status);
-}
-
-int wlan_hdd_listen_offload_stop(struct hdd_adapter *adapter)
-{
-	struct wlan_objmgr_psoc *psoc;
-	struct hdd_context *hdd_ctx;
-	uint32_t vdev_id;
-	QDF_STATUS status;
-
-	if (!adapter) {
-		hdd_err("adapter is null, adapter:%pK", adapter);
-		return -EINVAL;
-	}
-
-	vdev_id = (uint32_t)adapter->session_id;
-	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	psoc = hdd_ctx->hdd_psoc;
-	if (!psoc) {
-		hdd_err("psoc is null");
-		return -EINVAL;
-	}
-
-	status = ucfg_p2p_lo_stop(psoc, vdev_id);
-	hdd_debug("p2p listen offload stop, status:%d", status);
-
-	return qdf_status_to_os_return(status);
-}
-
 /**
  * wlan_hdd_update_mcc_adaptive_scheduler() - Function to update
  * MAS value to FW
diff --git a/core/hdd/src/wlan_hdd_p2p_listen_offload.c b/core/hdd/src/wlan_hdd_p2p_listen_offload.c
new file mode 100644
index 0000000..fe5e843
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_p2p_listen_offload.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_vendor_p2p_listen_offload.c
+ *
+ * WLAN p2p listen offload functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <wlan_hdd_p2p.h>
+#include <wlan_p2p_ucfg_api.h>
+#include <wlan_hdd_p2p_listen_offload.h>
+
+/* P2P listen offload device types parameters length in bytes */
+#define P2P_LO_MAX_REQ_DEV_TYPE_COUNT (10)
+#define P2P_LO_WPS_DEV_TYPE_LEN (8)
+#define P2P_LO_DEV_TYPE_MAX_LEN \
+	(P2P_LO_MAX_REQ_DEV_TYPE_COUNT * P2P_LO_WPS_DEV_TYPE_LEN)
+
+static const struct nla_policy
+p2p_listen_offload_policy[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] = { .type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] = { .type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] = {
+							.type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] = { .type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] = {
+					.type = NLA_BINARY,
+					.len = P2P_LO_DEV_TYPE_MAX_LEN },
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE] = {
+					.type = NLA_BINARY,
+					.len = MAX_GENIE_LEN },
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG] = {
+					.type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] = { .type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON] = {
+						.type = NLA_U8 },
+};
+
+/**
+ * wlan_hdd_listen_offload_start() - hdd set listen offload start
+ * @adapter: adapter context
+ * @params: listen offload parameters
+ *
+ * This function sets listen offload start parameters.
+ *
+ * Return: 0 on success, others on failure
+ */
+static int wlan_hdd_listen_offload_start(struct hdd_adapter *adapter,
+					 struct sir_p2p_lo_start *params)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct p2p_lo_start lo_start;
+	struct hdd_context *hdd_ctx;
+	QDF_STATUS status;
+
+	if (!adapter || !params) {
+		hdd_err("null param, adapter:%pK, params:%pK",
+			adapter, params);
+		return -EINVAL;
+	}
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	psoc = hdd_ctx->hdd_psoc;
+	if (!psoc) {
+		hdd_err("psoc is null");
+		return -EINVAL;
+	}
+
+	lo_start.vdev_id = params->vdev_id;
+	lo_start.ctl_flags = params->ctl_flags;
+	lo_start.freq = params->freq;
+	lo_start.period = params->period;
+	lo_start.interval = params->interval;
+	lo_start.count = params->count;
+	lo_start.device_types = params->device_types;
+	lo_start.dev_types_len = params->dev_types_len;
+	lo_start.probe_resp_tmplt = params->probe_resp_tmplt;
+	lo_start.probe_resp_len = params->probe_resp_len;
+
+	status = ucfg_p2p_lo_start(psoc, &lo_start);
+	hdd_debug("p2p listen offload start, status:%d", status);
+
+	return qdf_status_to_os_return(status);
+}
+
+/**
+ * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * This function is to process the p2p listen offload start vendor
+ * command. It parses the input parameters and invoke WMA API to
+ * send the command to firmware.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data,
+					    int data_len)
+{
+	int ret;
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter;
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
+	struct sir_p2p_lo_start params;
+
+	hdd_enter_dev(dev);
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
+	    (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
+	    (adapter->device_mode != QDF_P2P_GO_MODE)) {
+		hdd_err("Invalid device mode %d", adapter->device_mode);
+		return -EINVAL;
+	}
+
+	if (wlan_cfg80211_nla_parse(tb,
+				    QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
+				    data, data_len,
+				    p2p_listen_offload_policy)) {
+		hdd_err("Invalid ATTR");
+		return -EINVAL;
+	}
+
+	memset(&params, 0, sizeof(params));
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
+		params.ctl_flags = 1;  /* set to default value */
+	else
+		params.ctl_flags = nla_get_u32(tb
+			[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
+	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
+	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
+	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
+	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
+	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
+		hdd_err("Attribute parsing failed");
+		return -EINVAL;
+	}
+
+	params.vdev_id = adapter->session_id;
+	params.freq = nla_get_u32(tb
+		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
+	if ((params.freq != 2412) && (params.freq != 2437) &&
+	    (params.freq != 2462)) {
+		hdd_err("Invalid listening channel: %d", params.freq);
+		return -EINVAL;
+	}
+
+	params.period = nla_get_u32(tb
+		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
+	if (!((params.period > 0) && (params.period < UINT_MAX))) {
+		hdd_err("Invalid period: %d", params.period);
+		return -EINVAL;
+	}
+
+	params.interval = nla_get_u32(tb
+		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
+	if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
+		hdd_err("Invalid interval: %d", params.interval);
+		return -EINVAL;
+	}
+
+	params.count = nla_get_u32(tb
+		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
+	if (!((params.count >= 0) && (params.count < UINT_MAX))) {
+		hdd_err("Invalid count: %d", params.count);
+		return -EINVAL;
+	}
+
+	params.device_types = nla_data(tb
+		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
+	if (!params.device_types) {
+		hdd_err("Invalid device types");
+		return -EINVAL;
+	}
+
+	params.dev_types_len = nla_len(tb
+		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
+	/* device type length has to be multiple of P2P_LO_WPS_DEV_TYPE_LEN */
+	if (0 != (params.dev_types_len % P2P_LO_WPS_DEV_TYPE_LEN)) {
+		hdd_err("Invalid device type length: %d", params.dev_types_len);
+		return -EINVAL;
+	}
+
+	params.probe_resp_tmplt = nla_data(tb
+		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
+	if (!params.probe_resp_tmplt) {
+		hdd_err("Invalid probe response template");
+		return -EINVAL;
+	}
+
+	/*
+	 * IEs minimum length should be 2 bytes: 1 byte for element id
+	 * and 1 byte for element id length.
+	 */
+	params.probe_resp_len = nla_len(tb
+		[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
+	if (params.probe_resp_len < MIN_GENIE_LEN) {
+		hdd_err("Invalid probe resp template length: %d",
+			params.probe_resp_len);
+		return -EINVAL;
+	}
+
+	hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
+		  params.freq, params.period, params.interval, params.count);
+
+	return wlan_hdd_listen_offload_start(adapter, &params);
+}
+
+int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
+				   struct wireless_dev *wdev,
+				   const void *data,
+				   int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
+					       data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
+/**
+ * wlan_hdd_listen_offload_stop() - hdd set listen offload stop
+ * @adapter: adapter context
+ *
+ * This function sets listen offload stop parameters.
+ *
+ * Return: 0 on success, others on failure
+ */
+static int wlan_hdd_listen_offload_stop(struct hdd_adapter *adapter)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct hdd_context *hdd_ctx;
+	uint32_t vdev_id;
+	QDF_STATUS status;
+
+	if (!adapter) {
+		hdd_err("adapter is null, adapter:%pK", adapter);
+		return -EINVAL;
+	}
+
+	vdev_id = (uint32_t)adapter->session_id;
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	psoc = hdd_ctx->hdd_psoc;
+	if (!psoc) {
+		hdd_err("psoc is null");
+		return -EINVAL;
+	}
+
+	status = ucfg_p2p_lo_stop(psoc, vdev_id);
+	hdd_debug("p2p listen offload stop, status:%d", status);
+
+	return qdf_status_to_os_return(status);
+}
+
+/**
+ * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * This function is to process the p2p listen offload stop vendor
+ * command. It invokes WMA API to send command to firmware.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
+					   struct wireless_dev *wdev,
+					   const void *data,
+					   int data_len)
+{
+	struct hdd_adapter *adapter;
+	struct net_device *dev = wdev->netdev;
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
+	    (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
+	    (adapter->device_mode != QDF_P2P_GO_MODE)) {
+		hdd_err("Invalid device mode");
+		return -EINVAL;
+	}
+
+	return wlan_hdd_listen_offload_stop(adapter);
+}
+
+int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
+				  struct wireless_dev *wdev,
+				  const void *data,
+				  int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
+					      data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_p2p_listen_offload.h b/core/hdd/src/wlan_hdd_p2p_listen_offload.h
new file mode 100644
index 0000000..f039aca
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_p2p_listen_offload.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_P2P_LISTEN_OFFLOAD_H
+#define __WLAN_HDD_P2P_LISTEN_OFFLOAD_H
+
+/**
+ * DOC: wlan_hdd_p2p_listen_offload_h
+ *
+ * WLAN Host Device Driver p2p listen offload API specification
+ */
+
+#ifdef FEATURE_P2P_LISTEN_OFFLOAD
+/**
+ * __wlan_hdd_cfg80211_p2p_lo_start() - start P2P Listen Offload
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * This function is to process the p2p listen offload start vendor
+ * command. It parses the input parameters and invoke WMA API to
+ * send the command to firmware.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
+				   struct wireless_dev *wdev,
+				   const void *data,
+				   int data_len);
+
+/**
+ * wlan_hdd_cfg80211_p2p_lo_stop() - stop P2P Listen Offload
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
+ * to process p2p listen offload stop vendor command.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
+				  struct wireless_dev *wdev,
+				  const void *data,
+				  int data_len);
+
+#define FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS			\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd =							\
+		QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+			WIPHY_VENDOR_CMD_NEED_NETDEV |			\
+			WIPHY_VENDOR_CMD_NEED_RUNNING,			\
+	.doit = wlan_hdd_cfg80211_p2p_lo_start				\
+},									\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd =							\
+		QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+			WIPHY_VENDOR_CMD_NEED_NETDEV |			\
+			WIPHY_VENDOR_CMD_NEED_RUNNING,			\
+	.doit = wlan_hdd_cfg80211_p2p_lo_stop				\
+},
+#else /* FEATURE_P2P_LISTEN_OFFLOAD */
+#define FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
+#endif /* FEATURE_P2P_LISTEN_OFFLOAD */
+
+#endif /* __WLAN_HDD_P2P_LISTEN_OFFLOAD_H */
+
diff --git a/core/hdd/src/wlan_hdd_rssi_monitor.c b/core/hdd/src/wlan_hdd_rssi_monitor.c
new file mode 100644
index 0000000..b78116f
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_rssi_monitor.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_rssi_monitor.c
+ *
+ * WLAN rssi monitoring functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <wlan_hdd_ext_scan.h>
+#include <wlan_hdd_rssi_monitor.h>
+
+/*
+ * define short names for the global vendor params
+ * used by __wlan_hdd_cfg80211_monitor_rssi()
+ */
+#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
+#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
+#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
+#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
+#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
+
+/**
+ * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int
+__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
+				 struct wireless_dev *wdev,
+				 const void *data,
+				 int data_len)
+{
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct nlattr *tb[PARAM_MAX + 1];
+	struct rssi_monitor_req req;
+	QDF_STATUS status;
+	int ret;
+	uint32_t control;
+	mac_handle_t mac_handle;
+	static const struct nla_policy policy[PARAM_MAX + 1] = {
+			[PARAM_REQUEST_ID] = { .type = NLA_U32 },
+			[PARAM_CONTROL] = { .type = NLA_U32 },
+			[PARAM_MIN_RSSI] = { .type = NLA_S8 },
+			[PARAM_MAX_RSSI] = { .type = NLA_S8 },
+	};
+
+	hdd_enter_dev(dev);
+
+	if (wlan_hdd_validate_session_id(adapter->session_id)) {
+		hdd_err("invalid session id: %d", adapter->session_id);
+		return -EINVAL;
+	}
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
+		hdd_err("Not in Connected state!");
+		return -ENOTSUPP;
+	}
+
+	if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
+		hdd_err("Invalid ATTR");
+		return -EINVAL;
+	}
+
+	if (!tb[PARAM_REQUEST_ID]) {
+		hdd_err("attr request id failed");
+		return -EINVAL;
+	}
+
+	if (!tb[PARAM_CONTROL]) {
+		hdd_err("attr control failed");
+		return -EINVAL;
+	}
+
+	req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
+	req.session_id = adapter->session_id;
+	control = nla_get_u32(tb[PARAM_CONTROL]);
+
+	if (control == QCA_WLAN_RSSI_MONITORING_START) {
+		req.control = true;
+		if (!tb[PARAM_MIN_RSSI]) {
+			hdd_err("attr min rssi failed");
+			return -EINVAL;
+		}
+
+		if (!tb[PARAM_MAX_RSSI]) {
+			hdd_err("attr max rssi failed");
+			return -EINVAL;
+		}
+
+		req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
+		req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
+
+		if (!(req.min_rssi < req.max_rssi)) {
+			hdd_warn("min_rssi: %d must be less than max_rssi: %d",
+				 req.min_rssi, req.max_rssi);
+			return -EINVAL;
+		}
+		hdd_debug("Min_rssi: %d Max_rssi: %d",
+			  req.min_rssi, req.max_rssi);
+
+	} else if (control == QCA_WLAN_RSSI_MONITORING_STOP) {
+		req.control = false;
+	} else {
+		hdd_err("Invalid control cmd: %d", control);
+		return -EINVAL;
+	}
+	hdd_debug("Request Id: %u Session_id: %d Control: %d",
+		  req.request_id, req.session_id, req.control);
+
+	mac_handle = hdd_ctx->mac_handle;
+	status = sme_set_rssi_monitoring(mac_handle, &req);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * done with short names for the global vendor params
+ * used by __wlan_hdd_cfg80211_monitor_rssi()
+ */
+#undef PARAM_MAX
+#undef PARAM_CONTROL
+#undef PARAM_REQUEST_ID
+#undef PARAM_MAX_RSSI
+#undef PARAM_MIN_RSSI
+
+int
+wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
+			       const void *data, int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
+void hdd_rssi_threshold_breached(hdd_handle_t hdd_handle,
+				 struct rssi_breach_event *data)
+{
+	struct hdd_context *hdd_ctx  = hdd_handle_to_context(hdd_handle);
+	struct sk_buff *skb;
+
+	hdd_enter();
+
+	if (wlan_hdd_validate_context(hdd_ctx))
+		return;
+	if (!data) {
+		hdd_err("data is null");
+		return;
+	}
+
+	skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
+				  NULL,
+				  EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
+				  QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
+				  GFP_KERNEL);
+
+	if (!skb) {
+		hdd_err("mem alloc failed");
+		return;
+	}
+
+	hdd_debug("Req Id: %u Current rssi: %d",
+		  data->request_id, data->curr_rssi);
+	hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
+		  MAC_ADDR_ARRAY(data->curr_bssid.bytes));
+
+	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
+			data->request_id) ||
+	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
+		    sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
+	    nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
+		       data->curr_rssi)) {
+		hdd_err("nla put fail");
+		goto fail;
+	}
+
+	cfg80211_vendor_event(skb, GFP_KERNEL);
+	return;
+
+fail:
+	kfree_skb(skb);
+}
+
diff --git a/core/hdd/src/wlan_hdd_rssi_monitor.h b/core/hdd/src/wlan_hdd_rssi_monitor.h
new file mode 100644
index 0000000..ac621c4
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_rssi_monitor.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_RSSI_MONITOR_H
+#define __WLAN_HDD_RSSI_MONITOR_H
+
+/**
+ * DOC: wlan_hdd_rssi_monitor_h
+ *
+ * WLAN Host Device Driver RSSI monitoring API specification
+ */
+
+#ifdef FEATURE_RSSI_MONITOR
+/**
+ * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
+ * @wiphy:    wiphy structure pointer
+ * @wdev:     Wireless device structure pointer
+ * @data:     Pointer to the data received
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success; errno on failure
+ */
+int
+wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
+			       const void *data, int data_len);
+
+/**
+ * hdd_rssi_threshold_breached() - rssi breached NL event
+ * @hdd_handle: HDD handle
+ * @data: rssi breached event data
+ *
+ * This function reads the rssi breached event %data and fill in the skb with
+ * NL attributes and send up the NL event.
+ *
+ * Return: none
+ */
+void hdd_rssi_threshold_breached(hdd_handle_t hdd_handle,
+				 struct rssi_breach_event *data);
+
+#define FEATURE_RSSI_MONITOR_VENDOR_EVENTS			\
+[QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {		\
+	.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI	\
+},
+
+#define FEATURE_RSSI_MONITOR_VENDOR_COMMANDS			\
+{								\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,		\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |			\
+		WIPHY_VENDOR_CMD_NEED_NETDEV |			\
+		WIPHY_VENDOR_CMD_NEED_RUNNING,			\
+	.doit = wlan_hdd_cfg80211_monitor_rssi			\
+},
+
+#else /* FEATURE_RSSI_MONITOR */
+static inline
+void hdd_rssi_threshold_breached(hdd_handle_t hdd_handle,
+				 struct rssi_breach_event *data)
+{
+}
+
+#define FEATURE_RSSI_MONITOR_VENDOR_EVENTS
+#define FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
+#endif /* FEATURE_RSSI_MONITOR */
+
+#endif /* __WLAN_HDD_RSSI_MONITOR_H */
+
diff --git a/core/hdd/src/wlan_hdd_sap_cond_chan_switch.c b/core/hdd/src/wlan_hdd_sap_cond_chan_switch.c
new file mode 100644
index 0000000..60274d2
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_sap_cond_chan_switch.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_sap_cond_chan_switch.c
+ *
+ * WLAN SAP conditional channel switch functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <cds_utils.h>
+#include <qdf_str.h>
+#include <wlan_hdd_sap_cond_chan_switch.h>
+
+/**
+ * wlan_hdd_set_pre_cac_status() - Set the pre cac status
+ * @pre_cac_adapter: AP adapter used for pre cac
+ * @status: Status (true or false)
+ * @handle: Global handle
+ *
+ * Sets the status of pre cac i.e., whether the pre cac is active or not
+ *
+ * Return: Zero on success, non-zero on failure
+ */
+static int wlan_hdd_set_pre_cac_status(struct hdd_adapter *pre_cac_adapter,
+				       bool status, mac_handle_t handle)
+{
+	QDF_STATUS ret;
+
+	ret = wlan_sap_set_pre_cac_status(
+		WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
+	if (QDF_IS_STATUS_ERROR(ret))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
+ * @ap_adapter: AP adapter
+ * @chan_before_pre_cac: Channel
+ *
+ * Saves the channel which the AP was beaconing on before moving to the pre
+ * cac channel. If radar is detected on the pre cac channel, this saved
+ * channel will be used for AP operations.
+ *
+ * Return: Zero on success, non-zero on failure
+ */
+static int wlan_hdd_set_chan_before_pre_cac(struct hdd_adapter *ap_adapter,
+					    uint8_t chan_before_pre_cac)
+{
+	QDF_STATUS ret;
+
+	ret = wlan_sap_set_chan_before_pre_cac(
+		WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
+	if (QDF_IS_STATUS_ERROR(ret))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
+ * @hdd_ctx: HDD context
+ * @ap_adapter: AP adapter
+ * @channel: Channel requested by userspace
+ * @pre_cac_chan: Pointer to the pre CAC channel
+ *
+ * Validates the channel provided by userspace. If user provided channel 0,
+ * a valid outdoor channel must be selected from the regulatory channel.
+ *
+ * Return: Zero on success and non zero value on error
+ */
+static int wlan_hdd_validate_and_get_pre_cac_ch(struct hdd_context *hdd_ctx,
+						struct hdd_adapter *ap_adapter,
+						uint8_t channel,
+						uint8_t *pre_cac_chan)
+{
+	uint32_t i;
+	QDF_STATUS status;
+	uint32_t weight_len = 0;
+	uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+	uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
+	uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
+	mac_handle_t mac_handle;
+
+	if (channel == 0) {
+		/* Channel is not obtained from PCL because PCL may not have
+		 * the entire channel list. For example: if SAP is up on
+		 * channel 6 and PCL is queried for the next SAP interface,
+		 * if SCC is preferred, the PCL will contain only the channel
+		 * 6. But, we are in need of a DFS channel. So, going with the
+		 * first channel from the valid channel list.
+		 */
+		status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
+						    channel_list, &len);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			hdd_err("Failed to get channel list");
+			return -EINVAL;
+		}
+		policy_mgr_update_with_safe_channel_list(hdd_ctx->hdd_psoc,
+							 channel_list, &len,
+							 pcl_weights,
+							 weight_len);
+		for (i = 0; i < len; i++) {
+			if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
+					       channel_list[i])) {
+				*pre_cac_chan = channel_list[i];
+				break;
+			}
+		}
+		if (*pre_cac_chan == 0) {
+			hdd_err("unable to find outdoor channel");
+			return -EINVAL;
+		}
+	} else {
+		/* Only when driver selects a channel, check is done for
+		 * unnsafe and NOL channels. When user provides a fixed channel
+		 * the user is expected to take care of this.
+		 */
+		mac_handle = hdd_ctx->mac_handle;
+		if (!sme_is_channel_valid(mac_handle, channel) ||
+		    !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
+			hdd_err("Invalid channel for pre cac:%d", channel);
+			return -EINVAL;
+		}
+		*pre_cac_chan = channel;
+	}
+	hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
+	return 0;
+}
+
+/**
+ * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
+ * @channel: Channel option provided by userspace
+ *
+ * Sets the driver to the required hardware mode and start an adapter for
+ * pre CAC which will mimic an AP.
+ *
+ * Return: Zero on success, non-zero value on error
+ */
+int wlan_hdd_request_pre_cac(uint8_t channel)
+{
+	uint8_t pre_cac_chan = 0, *mac_addr;
+	struct hdd_context *hdd_ctx;
+	int ret;
+	struct hdd_adapter *ap_adapter, *pre_cac_adapter;
+	struct hdd_ap_ctx *hdd_ap_ctx;
+	QDF_STATUS status;
+	struct wiphy *wiphy;
+	struct net_device *dev;
+	struct cfg80211_chan_def chandef;
+	enum nl80211_channel_type channel_type;
+	uint32_t freq;
+	struct ieee80211_channel *chan;
+	mac_handle_t mac_handle;
+	bool val;
+
+	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	if (wlan_hdd_validate_context(hdd_ctx) != 0)
+		return -EINVAL;
+
+	if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
+		hdd_err("pre cac not allowed in concurrency");
+		return -EINVAL;
+	}
+
+	ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
+	if (!ap_adapter) {
+		hdd_err("unable to get SAP adapter");
+		return -EINVAL;
+	}
+
+	mac_handle = hdd_ctx->mac_handle;
+	val = wlan_sap_is_pre_cac_active(mac_handle);
+	if (val) {
+		hdd_err("pre cac is already in progress");
+		return -EINVAL;
+	}
+
+	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
+	if (!hdd_ap_ctx) {
+		hdd_err("SAP context is NULL");
+		return -EINVAL;
+	}
+
+	if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
+			       hdd_ap_ctx->operating_channel)) {
+		hdd_err("SAP is already on DFS channel:%d",
+			hdd_ap_ctx->operating_channel);
+		return -EINVAL;
+	}
+
+	if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operating_channel)) {
+		hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
+			hdd_ap_ctx->operating_channel);
+		return -EINVAL;
+	}
+
+	mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
+	if (!mac_addr) {
+		hdd_err("can't add virtual intf: Not getting valid mac addr");
+		return -EINVAL;
+	}
+
+	hdd_debug("channel:%d", channel);
+
+	ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
+						   &pre_cac_chan);
+	if (ret != 0) {
+		hdd_err("can't validate pre-cac channel");
+		goto release_intf_addr_and_return_failure;
+	}
+
+	hdd_debug("starting pre cac SAP  adapter");
+
+	/* Starting a SAP adapter:
+	 * Instead of opening an adapter, we could just do a SME open session
+	 * for AP type. But, start BSS would still need an adapter.
+	 * So, this option is not taken.
+	 *
+	 * hdd open adapter is going to register this precac interface with
+	 * user space. This interface though exposed to user space will be in
+	 * DOWN state. Consideration was done to avoid this registration to the
+	 * user space. But, as part of SAP operations multiple events are sent
+	 * to user space. Some of these events received from unregistered
+	 * interface was causing crashes. So, retaining the registration.
+	 *
+	 * So, this interface would remain registered and will remain in DOWN
+	 * state for the CAC duration. We will add notes in the feature
+	 * announcement to not use this temporary interface for any activity
+	 * from user space.
+	 */
+	pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
+					   mac_addr, NET_NAME_UNKNOWN, true);
+	if (!pre_cac_adapter) {
+		hdd_err("error opening the pre cac adapter");
+		goto release_intf_addr_and_return_failure;
+	}
+
+	/*
+	 * This interface is internally created by the driver. So, no interface
+	 * up comes for this interface from user space and hence starting
+	 * the adapter internally.
+	 */
+	if (hdd_start_adapter(pre_cac_adapter)) {
+		hdd_err("error starting the pre cac adapter");
+		goto close_pre_cac_adapter;
+	}
+
+	hdd_debug("preparing for start ap/bss on the pre cac adapter");
+
+	wiphy = hdd_ctx->wiphy;
+	dev = pre_cac_adapter->dev;
+
+	/* Since this is only a dummy interface lets us use the IEs from the
+	 * other active SAP interface. In regular scenarios, these IEs would
+	 * come from the user space entity
+	 */
+	pre_cac_adapter->session.ap.beacon = qdf_mem_malloc(
+			sizeof(*ap_adapter->session.ap.beacon));
+	if (!pre_cac_adapter->session.ap.beacon) {
+		hdd_err("failed to alloc mem for beacon");
+		goto stop_close_pre_cac_adapter;
+	}
+	qdf_mem_copy(pre_cac_adapter->session.ap.beacon,
+		     ap_adapter->session.ap.beacon,
+		     sizeof(*pre_cac_adapter->session.ap.beacon));
+	pre_cac_adapter->session.ap.sap_config.ch_width_orig =
+			ap_adapter->session.ap.sap_config.ch_width_orig;
+	pre_cac_adapter->session.ap.sap_config.authType =
+			ap_adapter->session.ap.sap_config.authType;
+
+	/* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
+	 * to operate on the same bandwidth as that of the 2.4GHz operations.
+	 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
+	 */
+	switch (ap_adapter->session.ap.sap_config.ch_width_orig) {
+	case CH_WIDTH_20MHZ:
+		channel_type = NL80211_CHAN_HT20;
+		break;
+	case CH_WIDTH_40MHZ:
+		if (ap_adapter->session.ap.sap_config.sec_ch >
+				ap_adapter->session.ap.sap_config.channel)
+			channel_type = NL80211_CHAN_HT40PLUS;
+		else
+			channel_type = NL80211_CHAN_HT40MINUS;
+		break;
+	default:
+		channel_type = NL80211_CHAN_NO_HT;
+		break;
+	}
+
+	freq = cds_chan_to_freq(pre_cac_chan);
+	chan = ieee80211_get_channel(wiphy, freq);
+	if (!chan) {
+		hdd_err("channel converion failed");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	cfg80211_chandef_create(&chandef, chan, channel_type);
+
+	hdd_debug("orig width:%d channel_type:%d freq:%d",
+		  ap_adapter->session.ap.sap_config.ch_width_orig,
+		  channel_type, freq);
+	/*
+	 * Doing update after opening and starting pre-cac adapter will make
+	 * sure that driver won't do hardware mode change if there are any
+	 * initial hick-ups or issues in pre-cac adapter's configuration.
+	 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
+	 * connection update should result in DBS mode
+	 */
+	status = policy_mgr_update_and_wait_for_connection_update(
+					hdd_ctx->hdd_psoc,
+					ap_adapter->session_id,
+					pre_cac_chan,
+					POLICY_MGR_UPDATE_REASON_PRE_CAC);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("error in moving to DBS mode");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
+	if (ret != 0) {
+		hdd_err("failed to set channel");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
+			PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
+			NL80211_HIDDEN_SSID_NOT_IN_USE, false);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("start bss failed");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	/*
+	 * The pre cac status is set here. But, it would not be reset explicitly
+	 * anywhere, since after the pre cac success/failure, the pre cac
+	 * adapter itself would be removed.
+	 */
+	ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, mac_handle);
+	if (ret != 0) {
+		hdd_err("failed to set pre cac status");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
+					       hdd_ap_ctx->operating_channel);
+	if (ret != 0) {
+		hdd_err("failed to set channel before pre cac");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	ap_adapter->pre_cac_chan = pre_cac_chan;
+
+	return 0;
+
+stop_close_pre_cac_adapter:
+	hdd_stop_adapter(hdd_ctx, pre_cac_adapter);
+	qdf_mem_free(pre_cac_adapter->session.ap.beacon);
+	pre_cac_adapter->session.ap.beacon = NULL;
+close_pre_cac_adapter:
+	hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
+release_intf_addr_and_return_failure:
+	/*
+	 * Release the interface address as the adapter
+	 * failed to start, if you don't release then next
+	 * adapter which is trying to come wouldn't get valid
+	 * mac address. Remember we have limited pool of mac addresses
+	 */
+	wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
+	return -EINVAL;
+}
+
+/**
+ * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Processes the conditional channel switch request and invokes the helper
+ * APIs to process the channel switch request.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int
+__wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data,
+					    int data_len)
+{
+	int ret;
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter;
+	struct nlattr
+		*tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
+	uint32_t freq_len, i;
+	uint32_t *freq;
+	uint8_t chans[QDF_MAX_NUM_CHAN] = {0};
+
+	hdd_enter_dev(dev);
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (!hdd_ctx->config->enableDFSMasterCap) {
+		hdd_err("DFS master capability is not present in the driver");
+		return -EINVAL;
+	}
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	if (adapter->device_mode != QDF_SAP_MODE) {
+		hdd_err("Invalid device mode %d", adapter->device_mode);
+		return -EINVAL;
+	}
+
+	/*
+	 * audit note: it is ok to pass a NULL policy here since only
+	 * one attribute is parsed which is array of frequencies and
+	 * it is explicitly validated for both under read and over read
+	 */
+	if (wlan_cfg80211_nla_parse(tb,
+			   QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
+			   data, data_len, NULL)) {
+		hdd_err("Invalid ATTR");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
+		hdd_err("Frequency list is missing");
+		return -EINVAL;
+	}
+
+	freq_len = nla_len(
+		tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
+		sizeof(uint32_t);
+
+	if (freq_len > QDF_MAX_NUM_CHAN) {
+		hdd_err("insufficient space to hold channels");
+		return -ENOMEM;
+	}
+
+	hdd_debug("freq_len=%d", freq_len);
+
+	freq = nla_data(
+		tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
+
+	for (i = 0; i < freq_len; i++) {
+		if (freq[i] == 0)
+			chans[i] = 0;
+		else
+			chans[i] = ieee80211_frequency_to_channel(freq[i]);
+
+		hdd_debug("freq[%d]=%d", i, freq[i]);
+	}
+
+	/*
+	 * The input frequency list from user space is designed to be a
+	 * priority based frequency list. This is only to accommodate any
+	 * future request. But, current requirement is only to perform CAC
+	 * on a single channel. So, the first entry from the list is picked.
+	 *
+	 * If channel is zero, any channel in the available outdoor regulatory
+	 * domain will be selected.
+	 */
+	ret = wlan_hdd_request_pre_cac(chans[0]);
+	if (ret) {
+		hdd_err("pre cac request failed with reason:%d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
+					      struct wireless_dev *wdev,
+					      const void *data,
+					      int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
+							  data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_sap_cond_chan_switch.h b/core/hdd/src/wlan_hdd_sap_cond_chan_switch.h
new file mode 100644
index 0000000..1ea89eb
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_sap_cond_chan_switch.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_SAP_COND_CHAN_SWITCH_H
+#define __WLAN_HDD_SAP_COND_CHAN_SWITCH_H
+
+/**
+ * DOC: wlan_hdd_sap_cond_chan_switch_h
+ *
+ * WLAN Host Device Driver SAP conditional channel switch API specification
+ */
+
+#ifdef FEATURE_SAP_COND_CHAN_SWITCH
+/**
+ * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Invokes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
+ * to process the conditional channel switch request.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
+					      struct wireless_dev *wdev,
+					      const void *data,
+					      int data_len);
+
+#define FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS			\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd =							\
+		QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+			WIPHY_VENDOR_CMD_NEED_NETDEV |			\
+			WIPHY_VENDOR_CMD_NEED_RUNNING,			\
+	.doit = wlan_hdd_cfg80211_conditional_chan_switch		\
+},
+#else /* FEATURE_SAP_COND_CHAN_SWITCH */
+#define FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
+#endif /* FEATURE_SAP_COND_CHAN_SWITCH */
+
+#endif /* __WLAN_HDD_SAP_COND_CHAN_SWITCH_H */
+
diff --git a/core/hdd/src/wlan_hdd_sar_limits.c b/core/hdd/src/wlan_hdd_sar_limits.c
new file mode 100644
index 0000000..c500ddc
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_sar_limits.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_vendor_sar_limits.c
+ *
+ * WLAN SAR limits functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <wlan_osif_request_manager.h>
+#include <wlan_hdd_sar_limits.h>
+
+#define WLAN_WAIT_TIME_SAR 5000
+/**
+ * hdd_sar_context - hdd sar context
+ * @event: sar limit event
+ */
+struct hdd_sar_context {
+	struct sar_limit_event event;
+};
+
+static u32 hdd_sar_wmi_to_nl_enable(uint32_t wmi_value)
+{
+	switch (wmi_value) {
+	default:
+	case WMI_SAR_FEATURE_OFF:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
+	case WMI_SAR_FEATURE_ON_SET_0:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
+	case WMI_SAR_FEATURE_ON_SET_1:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1;
+	case WMI_SAR_FEATURE_ON_SET_2:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2;
+	case WMI_SAR_FEATURE_ON_SET_3:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3;
+	case WMI_SAR_FEATURE_ON_SET_4:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
+	case WMI_SAR_FEATURE_ON_USER_DEFINED:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER;
+	case WMI_SAR_FEATURE_ON_SAR_V2_0:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
+	}
+}
+
+static u32 hdd_sar_wmi_to_nl_band(uint32_t wmi_value)
+{
+	switch (wmi_value) {
+	default:
+	case WMI_SAR_2G_ID:
+		return HDD_NL80211_BAND_2GHZ;
+	case WMI_SAR_5G_ID:
+		return HDD_NL80211_BAND_5GHZ;
+	}
+}
+
+static u32 hdd_sar_wmi_to_nl_modulation(uint32_t wmi_value)
+{
+	switch (wmi_value) {
+	default:
+	case WMI_SAR_MOD_CCK:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK;
+	case WMI_SAR_MOD_OFDM:
+		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM;
+	}
+}
+
+/**
+ * hdd_sar_cb () - sar response message handler
+ * @cookie: hdd request cookie
+ * @event: sar response event
+ *
+ * Return: none
+ */
+static void hdd_sar_cb(void *cookie,
+		       struct sar_limit_event *event)
+{
+	struct osif_request *request;
+	struct hdd_sar_context *context;
+
+	hdd_enter();
+
+	if (!event) {
+		hdd_err("response is NULL");
+		return;
+	}
+
+	request = osif_request_get(cookie);
+	if (!request) {
+		hdd_debug("Obsolete request");
+		return;
+	}
+
+	context = osif_request_priv(request);
+	context->event = *event;
+	osif_request_complete(request);
+	osif_request_put(request);
+
+	hdd_exit();
+}
+
+static uint32_t hdd_sar_get_response_len(const struct sar_limit_event *event)
+{
+	uint32_t len;
+	uint32_t row_len;
+
+	len = NLMSG_HDRLEN;
+	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE */
+	len += NLA_HDRLEN + sizeof(u32);
+	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS */
+	len += NLA_HDRLEN + sizeof(u32);
+
+	/* nest */
+	row_len = NLA_HDRLEN;
+	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND */
+	row_len += NLA_HDRLEN + sizeof(u32);
+	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN */
+	row_len += NLA_HDRLEN + sizeof(u32);
+	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION */
+	row_len += NLA_HDRLEN + sizeof(u32);
+	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT */
+	row_len += NLA_HDRLEN + sizeof(u32);
+
+	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC */
+	len += NLA_HDRLEN + (row_len * event->num_limit_rows);
+
+	return len;
+}
+
+static int hdd_sar_fill_response(struct sk_buff *skb,
+				 const struct sar_limit_event *event)
+{
+	int errno;
+	u32 value;
+	u32 attr;
+	struct nlattr *nla_spec_attr;
+	struct nlattr *nla_row_attr;
+	uint32_t row;
+	const struct sar_limit_event_row *event_row;
+
+	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE;
+	value = hdd_sar_wmi_to_nl_enable(event->sar_enable);
+	errno = nla_put_u32(skb, attr, value);
+	if (errno)
+		return errno;
+
+	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS;
+	value = event->num_limit_rows;
+	errno = nla_put_u32(skb, attr, value);
+	if (errno)
+		return errno;
+
+	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC;
+	nla_spec_attr = nla_nest_start(skb, attr);
+	if (!nla_spec_attr)
+		return -EINVAL;
+
+	for (row = 0, event_row = event->sar_limit_row;
+	     row < event->num_limit_rows;
+	     row++, event_row++) {
+		nla_row_attr = nla_nest_start(skb, attr);
+		if (!nla_row_attr)
+			return -EINVAL;
+
+		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND;
+		value = hdd_sar_wmi_to_nl_band(event_row->band_id);
+		errno = nla_put_u32(skb, attr, value);
+		if (errno)
+			return errno;
+
+		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN;
+		value = event_row->chain_id;
+		errno = nla_put_u32(skb, attr, value);
+		if (errno)
+			return errno;
+
+		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION;
+		value = hdd_sar_wmi_to_nl_modulation(event_row->mod_id);
+		errno = nla_put_u32(skb, attr, value);
+		if (errno)
+			return errno;
+
+		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT;
+		value = event_row->limit_value;
+		errno = nla_put_u32(skb, attr, value);
+		if (errno)
+			return errno;
+
+		nla_nest_end(skb, nla_row_attr);
+	}
+	nla_nest_end(skb, nla_spec_attr);
+
+	return 0;
+}
+
+static int hdd_sar_send_response(struct wiphy *wiphy,
+				 const struct sar_limit_event *event)
+{
+	uint32_t len;
+	struct sk_buff *skb;
+	int errno;
+
+	len = hdd_sar_get_response_len(event);
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
+	if (!skb) {
+		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+		return -ENOMEM;
+	}
+
+	errno = hdd_sar_fill_response(skb, event);
+	if (errno) {
+		kfree_skb(skb);
+		return errno;
+	}
+
+	return cfg80211_vendor_cmd_reply(skb);
+}
+
+/**
+ * __wlan_hdd_get_sar_power_limits() - Get SAR power limits
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Length of @data
+ *
+ * This function is used to retrieve Specific Absorption Rate limit specs.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int __wlan_hdd_get_sar_power_limits(struct wiphy *wiphy,
+					   struct wireless_dev *wdev,
+					   const void *data, int data_len)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct osif_request *request;
+	struct hdd_sar_context *context;
+	mac_handle_t mac_handle;
+	void *cookie;
+	QDF_STATUS status;
+	int ret;
+	static const struct osif_request_params params = {
+		.priv_size = sizeof(*context),
+		.timeout_ms = WLAN_WAIT_TIME_SAR,
+	};
+
+	hdd_enter();
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	if (wlan_hdd_validate_context(hdd_ctx))
+		return -EINVAL;
+
+	request = osif_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+
+	cookie = osif_request_cookie(request);
+
+	mac_handle = hdd_ctx->mac_handle;
+	status = sme_get_sar_power_limits(mac_handle, hdd_sar_cb, cookie);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		hdd_err("Unable to post sar message");
+		ret = -EINVAL;
+		goto cleanup;
+	}
+
+	ret = osif_request_wait_for_response(request);
+	if (ret) {
+		hdd_err("Target response timed out");
+		goto cleanup;
+	}
+
+	context = osif_request_priv(request);
+	ret = hdd_sar_send_response(wiphy, &context->event);
+
+cleanup:
+	osif_request_put(request);
+
+	return ret;
+}
+
+int wlan_hdd_cfg80211_get_sar_power_limits(struct wiphy *wiphy,
+					   struct wireless_dev *wdev,
+					   const void *data,
+					   int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_get_sar_power_limits(wiphy, wdev, data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_sar_limits.h b/core/hdd/src/wlan_hdd_sar_limits.h
new file mode 100644
index 0000000..2a49a46
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_sar_limits.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_SAR_LIMITS_H
+#define __WLAN_HDD_SAR_LIMITS_H
+
+/**
+ * DOC: wlan_hdd_sar_limits_h
+ *
+ * WLAN Host Device Driver SAR limits API specification
+ */
+
+#ifdef FEATURE_SAR_LIMITS
+/**
+ * wlan_hdd_cfg80211_get_sar_power_limits() - Get SAR power limits
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Length of @data
+ *
+ * Wrapper function of __wlan_hdd_cfg80211_get_sar_power_limits()
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int wlan_hdd_cfg80211_get_sar_power_limits(struct wiphy *wiphy,
+					   struct wireless_dev *wdev,
+					   const void *data,
+					   int data_len);
+
+#define FEATURE_SAR_LIMITS_VENDOR_COMMANDS				\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+		 WIPHY_VENDOR_CMD_NEED_RUNNING,				\
+	.doit = wlan_hdd_cfg80211_get_sar_power_limits			\
+},
+#else /* FEATURE_SAR_LIMITS */
+#define FEATURE_SAR_LIMITS_VENDOR_COMMANDS
+#endif /* FEATURE_SAR_LIMITS */
+
+#endif /* __WLAN_HDD_SAR_LIMITS_H */
+
diff --git a/core/hdd/src/wlan_hdd_station_info.c b/core/hdd/src/wlan_hdd_station_info.c
new file mode 100644
index 0000000..35af7f3
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_station_info.c
@@ -0,0 +1,1222 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_station_info.c
+ *
+ * WLAN station info functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <wlan_cp_stats_mc_ucfg_api.h>
+#include <wlan_hdd_stats.h>
+#include <wlan_hdd_hostapd.h>
+#include <wlan_hdd_station_info.h>
+
+/*
+ * define short names for the global vendor params
+ * used by __wlan_hdd_cfg80211_get_station_cmd()
+ */
+#define STATION_INVALID \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
+#define STATION_INFO \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
+#define STATION_ASSOC_FAIL_REASON \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
+#define STATION_REMOTE \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE
+#define STATION_MAX \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
+
+/* define short names for get station info attributes */
+#define LINK_INFO_STANDARD_NL80211_ATTR \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
+#define AP_INFO_STANDARD_NL80211_ATTR \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR
+#define INFO_ROAM_COUNT \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT
+#define INFO_AKM \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
+#define WLAN802_11_MODE \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE
+#define AP_INFO_HS20_INDICATION \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION
+#define HT_OPERATION \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
+#define VHT_OPERATION \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
+#define INFO_ASSOC_FAIL_REASON \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON
+#define REMOTE_MAX_PHY_RATE \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE
+#define REMOTE_TX_PACKETS \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS
+#define REMOTE_TX_BYTES \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES
+#define REMOTE_RX_PACKETS \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS
+#define REMOTE_RX_BYTES \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BYTES
+#define REMOTE_LAST_TX_RATE \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_TX_RATE
+#define REMOTE_LAST_RX_RATE \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE
+#define REMOTE_WMM \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_WMM
+#define REMOTE_SUPPORTED_MODE \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE
+#define REMOTE_AMPDU \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AMPDU
+#define REMOTE_TX_STBC \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_STBC
+#define REMOTE_RX_STBC \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC
+#define REMOTE_CH_WIDTH\
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH
+#define REMOTE_SGI_ENABLE\
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
+	#define REMOTE_PAD\
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD
+#endif
+
+static const struct nla_policy
+hdd_get_station_policy[STATION_MAX + 1] = {
+	[STATION_INFO] = {.type = NLA_FLAG},
+	[STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
+	[STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
+};
+
+#ifdef QCA_SUPPORT_CP_STATS
+static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
+				  uint32_t *congestion)
+{
+	QDF_STATUS status;
+	struct cca_stats cca_stats;
+
+	status = ucfg_mc_cp_stats_cca_stats_get(adapter->hdd_vdev, &cca_stats);
+	if (QDF_IS_STATUS_ERROR(status))
+		return -EINVAL;
+
+	*congestion = cca_stats.congestion;
+	return 0;
+}
+#else
+static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
+				  uint32_t *congestion)
+{
+	struct hdd_station_ctx *hdd_sta_ctx;
+
+	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+	*congestion = hdd_sta_ctx->conn_info.cca;
+	return 0;
+}
+#endif
+
+/**
+ * hdd_get_station_assoc_fail() - Handle get station assoc fail
+ * @hdd_ctx: HDD context within host driver
+ * @wdev: wireless device
+ *
+ * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
+ * Validate cmd attributes and send the station info to upper layers.
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int hdd_get_station_assoc_fail(struct hdd_context *hdd_ctx,
+				      struct hdd_adapter *adapter)
+{
+	struct sk_buff *skb = NULL;
+	uint32_t nl_buf_len;
+	struct hdd_station_ctx *hdd_sta_ctx;
+	uint32_t congestion;
+
+	nl_buf_len = NLMSG_HDRLEN;
+	nl_buf_len += sizeof(uint32_t);
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
+
+	if (!skb) {
+		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+		return -ENOMEM;
+	}
+
+	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+	if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
+			hdd_sta_ctx->conn_info.assoc_status_code)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+
+	if (hdd_get_sta_congestion(adapter, &congestion))
+		congestion = 0;
+
+	hdd_info("congestion:%d", congestion);
+	if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
+			congestion)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+
+	return cfg80211_vendor_cmd_reply(skb);
+fail:
+	if (skb)
+		kfree_skb(skb);
+	return -EINVAL;
+}
+
+/**
+ * hdd_map_auth_type() - transform auth type specific to
+ * vendor command
+ * @auth_type: csr auth type
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int hdd_convert_auth_type(uint32_t auth_type)
+{
+	uint32_t ret_val;
+
+	switch (auth_type) {
+	case eCSR_AUTH_TYPE_OPEN_SYSTEM:
+		ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
+		break;
+	case eCSR_AUTH_TYPE_SHARED_KEY:
+		ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
+		break;
+	case eCSR_AUTH_TYPE_WPA:
+		ret_val = QCA_WLAN_AUTH_TYPE_WPA;
+		break;
+	case eCSR_AUTH_TYPE_WPA_PSK:
+		ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
+		break;
+	case eCSR_AUTH_TYPE_AUTOSWITCH:
+		ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
+		break;
+	case eCSR_AUTH_TYPE_WPA_NONE:
+		ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
+		break;
+	case eCSR_AUTH_TYPE_RSN:
+		ret_val = QCA_WLAN_AUTH_TYPE_RSN;
+		break;
+	case eCSR_AUTH_TYPE_RSN_PSK:
+		ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
+		break;
+	case eCSR_AUTH_TYPE_FT_RSN:
+		ret_val = QCA_WLAN_AUTH_TYPE_FT;
+		break;
+	case eCSR_AUTH_TYPE_FT_RSN_PSK:
+		ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
+		break;
+	case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
+		ret_val = QCA_WLAN_AUTH_TYPE_WAI;
+		break;
+	case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
+		ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
+		break;
+	case eCSR_AUTH_TYPE_CCKM_WPA:
+		ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
+		break;
+	case eCSR_AUTH_TYPE_CCKM_RSN:
+		ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
+		break;
+	case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
+		ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
+		break;
+	case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
+		ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
+		break;
+	case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
+	case eCSR_AUTH_TYPE_FAILED:
+	case eCSR_AUTH_TYPE_NONE:
+	default:
+		ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
+		break;
+	}
+	return ret_val;
+}
+
+/**
+ * hdd_map_dot_11_mode() - transform dot11mode type specific to
+ * vendor command
+ * @dot11mode: dot11mode
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int hdd_convert_dot11mode(uint32_t dot11mode)
+{
+	uint32_t ret_val;
+
+	switch (dot11mode) {
+	case eCSR_CFG_DOT11_MODE_11A:
+		ret_val = QCA_WLAN_802_11_MODE_11A;
+		break;
+	case eCSR_CFG_DOT11_MODE_11B:
+		ret_val = QCA_WLAN_802_11_MODE_11B;
+		break;
+	case eCSR_CFG_DOT11_MODE_11G:
+		ret_val = QCA_WLAN_802_11_MODE_11G;
+		break;
+	case eCSR_CFG_DOT11_MODE_11N:
+		ret_val = QCA_WLAN_802_11_MODE_11N;
+		break;
+	case eCSR_CFG_DOT11_MODE_11AC:
+		ret_val = QCA_WLAN_802_11_MODE_11AC;
+		break;
+	case eCSR_CFG_DOT11_MODE_AUTO:
+	case eCSR_CFG_DOT11_MODE_ABG:
+	default:
+		ret_val = QCA_WLAN_802_11_MODE_INVALID;
+	}
+	return ret_val;
+}
+
+/**
+ * hdd_add_tx_bitrate() - add tx bitrate attribute
+ * @skb: pointer to sk buff
+ * @hdd_sta_ctx: pointer to hdd station context
+ * @idx: attribute index
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
+				  struct hdd_station_ctx *hdd_sta_ctx,
+				  int idx)
+{
+	struct nlattr *nla_attr;
+	uint32_t bitrate, bitrate_compat;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr) {
+		hdd_err("nla_nest_start failed");
+		goto fail;
+	}
+
+	/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
+	bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->
+						cache_conn_info.txrate);
+
+	/* report 16-bit bitrate only if we can */
+	bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
+
+	if (bitrate > 0) {
+		if (nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
+			hdd_err("put fail bitrate: %u", bitrate);
+			goto fail;
+		}
+	} else {
+		hdd_err("Invalid bitrate: %u", bitrate);
+	}
+
+	if (bitrate_compat > 0) {
+		if (nla_put_u16(skb, NL80211_RATE_INFO_BITRATE,
+				bitrate_compat)) {
+			hdd_err("put fail bitrate_compat: %u", bitrate_compat);
+			goto fail;
+		}
+	} else {
+		hdd_err("Invalid bitrate_compat: %u", bitrate_compat);
+	}
+
+	if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
+		       hdd_sta_ctx->cache_conn_info.txrate.nss)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_add_sta_info() - add station info attribute
+ * @skb: pointer to sk buff
+ * @hdd_sta_ctx: pointer to hdd station context
+ * @idx: attribute index
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int32_t hdd_add_sta_info(struct sk_buff *skb,
+				struct hdd_station_ctx *hdd_sta_ctx,
+				int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr) {
+		hdd_err("nla_nest_start failed");
+		goto fail;
+	}
+
+	if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
+		       (hdd_sta_ctx->cache_conn_info.signal + 100))) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE)) {
+		hdd_err("hdd_add_tx_bitrate failed");
+		goto fail;
+	}
+
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_add_survey_info() - add survey info attribute
+ * @skb: pointer to sk buff
+ * @hdd_sta_ctx: pointer to hdd station context
+ * @idx: attribute index
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int32_t hdd_add_survey_info(struct sk_buff *skb,
+				   struct hdd_station_ctx *hdd_sta_ctx,
+				   int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr)
+		goto fail;
+	if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
+			hdd_sta_ctx->cache_conn_info.freq) ||
+	    nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
+		       (hdd_sta_ctx->cache_conn_info.noise + 100))) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_add_link_standard_info() - add link info attribute
+ * @skb: pointer to sk buff
+ * @hdd_sta_ctx: pointer to hdd station context
+ * @idx: attribute index
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int32_t
+hdd_add_link_standard_info(struct sk_buff *skb,
+			   struct hdd_station_ctx *hdd_sta_ctx, int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr) {
+		hdd_err("nla_nest_start failed");
+		goto fail;
+	}
+
+	if (nla_put(skb,
+		    NL80211_ATTR_SSID,
+		    hdd_sta_ctx->cache_conn_info.last_ssid.SSID.length,
+		    hdd_sta_ctx->cache_conn_info.last_ssid.SSID.ssId)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	if (nla_put(skb, NL80211_ATTR_MAC, QDF_MAC_ADDR_SIZE,
+		    hdd_sta_ctx->cache_conn_info.bssId.bytes)) {
+		hdd_err("put bssid failed");
+		goto fail;
+	}
+	if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO)) {
+		hdd_err("hdd_add_survey_info failed");
+		goto fail;
+	}
+
+	if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO)) {
+		hdd_err("hdd_add_sta_info failed");
+		goto fail;
+	}
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_add_ap_standard_info() - add ap info attribute
+ * @skb: pointer to sk buff
+ * @hdd_sta_ctx: pointer to hdd station context
+ * @idx: attribute index
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int32_t
+hdd_add_ap_standard_info(struct sk_buff *skb,
+			 struct hdd_station_ctx *hdd_sta_ctx, int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr)
+		goto fail;
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
+		if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
+			    sizeof(hdd_sta_ctx->cache_conn_info.vht_caps),
+			    &hdd_sta_ctx->cache_conn_info.vht_caps)) {
+			hdd_err("put fail");
+			goto fail;
+		}
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
+		if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
+			    sizeof(hdd_sta_ctx->cache_conn_info.ht_caps),
+			    &hdd_sta_ctx->cache_conn_info.ht_caps)) {
+			hdd_err("put fail");
+			goto fail;
+		}
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_get_station_info() - send BSS information to supplicant
+ * @hdd_ctx: pointer to hdd context
+ * @adapter: pointer to adapter
+ *
+ * Return: 0 if success else error status
+ */
+static int hdd_get_station_info(struct hdd_context *hdd_ctx,
+				struct hdd_adapter *adapter)
+{
+	struct sk_buff *skb = NULL;
+	uint8_t *tmp_hs20 = NULL;
+	uint32_t nl_buf_len;
+	struct hdd_station_ctx *hdd_sta_ctx;
+
+	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+	nl_buf_len = NLMSG_HDRLEN;
+	nl_buf_len += sizeof(hdd_sta_ctx->
+				cache_conn_info.last_ssid.SSID.length) +
+		      QDF_MAC_ADDR_SIZE +
+		      sizeof(hdd_sta_ctx->cache_conn_info.freq) +
+		      sizeof(hdd_sta_ctx->cache_conn_info.noise) +
+		      sizeof(hdd_sta_ctx->cache_conn_info.signal) +
+		      (sizeof(uint32_t) * 2) +
+		      sizeof(hdd_sta_ctx->cache_conn_info.txrate.nss) +
+		      sizeof(hdd_sta_ctx->cache_conn_info.roam_count) +
+		      sizeof(hdd_sta_ctx->cache_conn_info.last_auth_type) +
+		      sizeof(hdd_sta_ctx->cache_conn_info.dot11Mode);
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
+		nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.vht_caps);
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
+		nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.ht_caps);
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) {
+		tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->
+						cache_conn_info.hs20vendor_ie);
+		nl_buf_len += (sizeof(hdd_sta_ctx->
+					cache_conn_info.hs20vendor_ie) - 1);
+	}
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
+		nl_buf_len += sizeof(hdd_sta_ctx->
+						cache_conn_info.ht_operation);
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
+		nl_buf_len += sizeof(hdd_sta_ctx->
+						cache_conn_info.vht_operation);
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
+	if (!skb) {
+		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+		return -ENOMEM;
+	}
+
+	if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
+				       LINK_INFO_STANDARD_NL80211_ATTR)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
+				     AP_INFO_STANDARD_NL80211_ATTR)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	if (nla_put_u32(skb, INFO_ROAM_COUNT,
+			hdd_sta_ctx->cache_conn_info.roam_count) ||
+	    nla_put_u32(skb, INFO_AKM,
+			hdd_convert_auth_type(
+			hdd_sta_ctx->cache_conn_info.last_auth_type)) ||
+	    nla_put_u32(skb, WLAN802_11_MODE,
+			hdd_convert_dot11mode(
+			hdd_sta_ctx->cache_conn_info.dot11Mode))) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
+		if (nla_put(skb, HT_OPERATION,
+			    (sizeof(hdd_sta_ctx->cache_conn_info.ht_operation)),
+			    &hdd_sta_ctx->cache_conn_info.ht_operation)) {
+			hdd_err("put fail");
+			goto fail;
+		}
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
+		if (nla_put(skb, VHT_OPERATION,
+			    (sizeof(hdd_sta_ctx->
+					cache_conn_info.vht_operation)),
+			    &hdd_sta_ctx->cache_conn_info.vht_operation)) {
+			hdd_err("put fail");
+			goto fail;
+		}
+	if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present)
+		if (nla_put(skb, AP_INFO_HS20_INDICATION,
+			    (sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie)
+			     - 1),
+			    tmp_hs20 + 1)) {
+			hdd_err("put fail");
+			goto fail;
+		}
+
+	return cfg80211_vendor_cmd_reply(skb);
+fail:
+	if (skb)
+		kfree_skb(skb);
+	return -EINVAL;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
+static inline int32_t remote_station_put_u64(struct sk_buff *skb,
+					     int32_t attrtype,
+					     uint64_t value)
+{
+	return nla_put_u64_64bit(skb, attrtype, value, REMOTE_PAD);
+}
+#else
+static inline int32_t remote_station_put_u64(struct sk_buff *skb,
+					     int32_t attrtype,
+					     uint64_t value)
+{
+	return nla_put_u64(skb, attrtype, value);
+}
+#endif
+
+/**
+ * hdd_add_survey_info_sap_get_len - get data length used in
+ * hdd_add_survey_info_sap()
+ *
+ * This function calculates the data length used in hdd_add_survey_info_sap()
+ *
+ * Return: total data length used in hdd_add_survey_info_sap()
+ */
+static uint32_t hdd_add_survey_info_sap_get_len(void)
+{
+	return ((NLA_HDRLEN) + (sizeof(uint32_t) + NLA_HDRLEN));
+}
+
+/**
+ * hdd_add_survey_info - add survey info attribute
+ * @skb: pointer to response skb buffer
+ * @stainfo: station information
+ * @idx: attribute type index for nla_next_start()
+ *
+ * This function adds survey info attribute to response skb buffer
+ *
+ * Return : 0 on success and errno on failure
+ */
+static int32_t hdd_add_survey_info_sap(struct sk_buff *skb,
+				       struct hdd_station_info *stainfo,
+				       int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr)
+		goto fail;
+	if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
+			stainfo->freq)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_add_tx_bitrate_sap_get_len - get data length used in
+ * hdd_add_tx_bitrate_sap()
+ *
+ * This function calculates the data length used in hdd_add_tx_bitrate_sap()
+ *
+ * Return: total data length used in hdd_add_tx_bitrate_sap()
+ */
+static uint32_t hdd_add_tx_bitrate_sap_get_len(void)
+{
+	return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN));
+}
+
+/**
+ * hdd_add_tx_bitrate_sap - add vhs nss info attribute
+ * @skb: pointer to response skb buffer
+ * @stainfo: station information
+ * @idx: attribute type index for nla_next_start()
+ *
+ * This function adds vht nss attribute to response skb buffer
+ *
+ * Return : 0 on success and errno on failure
+ */
+static int hdd_add_tx_bitrate_sap(struct sk_buff *skb,
+				  struct hdd_station_info *stainfo,
+				  int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr)
+		goto fail;
+
+	if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
+		       stainfo->nss)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_add_sta_info_sap_get_len - get data length used in
+ * hdd_add_sta_info_sap()
+ *
+ * This function calculates the data length used in hdd_add_sta_info_sap()
+ *
+ * Return: total data length used in hdd_add_sta_info_sap()
+ */
+static uint32_t hdd_add_sta_info_sap_get_len(void)
+{
+	return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN) +
+		hdd_add_tx_bitrate_sap_get_len());
+}
+
+/**
+ * hdd_add_sta_info_sap - add sta signal info attribute
+ * @skb: pointer to response skb buffer
+ * @stainfo: station information
+ * @idx: attribute type index for nla_next_start()
+ *
+ * This function adds sta signal attribute to response skb buffer
+ *
+ * Return : 0 on success and errno on failure
+ */
+static int32_t hdd_add_sta_info_sap(struct sk_buff *skb, int8_t rssi,
+				    struct hdd_station_info *stainfo, int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr)
+		goto fail;
+
+	if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL, rssi)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+	if (hdd_add_tx_bitrate_sap(skb, stainfo, NL80211_STA_INFO_TX_BITRATE))
+		goto fail;
+
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_add_link_standard_info_sap_get_len - get data length used in
+ * hdd_add_link_standard_info_sap()
+ *
+ * This function calculates the data length used in
+ * hdd_add_link_standard_info_sap()
+ *
+ * Return: total data length used in hdd_add_link_standard_info_sap()
+ */
+static uint32_t hdd_add_link_standard_info_sap_get_len(void)
+{
+	return ((NLA_HDRLEN) +
+		hdd_add_survey_info_sap_get_len() +
+		hdd_add_sta_info_sap_get_len() +
+		(sizeof(uint32_t) + NLA_HDRLEN));
+}
+
+/**
+ * hdd_add_link_standard_info_sap - add add link info attribut
+ * @skb: pointer to response skb buffer
+ * @stainfo: station information
+ * @idx: attribute type index for nla_next_start()
+ *
+ * This function adds link info attribut to response skb buffer
+ *
+ * Return : 0 on success and errno on failure
+ */
+static int hdd_add_link_standard_info_sap(struct sk_buff *skb, int8_t rssi,
+					  struct hdd_station_info *stainfo,
+					  int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr)
+		goto fail;
+	if (hdd_add_survey_info_sap(skb, stainfo, NL80211_ATTR_SURVEY_INFO))
+		goto fail;
+	if (hdd_add_sta_info_sap(skb, rssi, stainfo, NL80211_ATTR_STA_INFO))
+		goto fail;
+
+	if (nla_put_u32(skb, NL80211_ATTR_REASON_CODE, stainfo->reason_code)) {
+		hdd_err("Reason code put fail");
+		goto fail;
+	}
+
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_add_ap_standard_info_sap_get_len - get data length used in
+ * hdd_add_ap_standard_info_sap()
+ * @stainfo: station information
+ *
+ * This function calculates the data length used in
+ * hdd_add_ap_standard_info_sap()
+ *
+ * Return: total data length used in hdd_add_ap_standard_info_sap()
+ */
+static uint32_t hdd_add_ap_standard_info_sap_get_len(
+				struct hdd_station_info *stainfo)
+{
+	uint32_t len;
+
+	len = NLA_HDRLEN;
+	if (stainfo->vht_present)
+		len += (sizeof(stainfo->vht_caps) + NLA_HDRLEN);
+	if (stainfo->ht_present)
+		len += (sizeof(stainfo->ht_caps) + NLA_HDRLEN);
+
+	return len;
+}
+
+/**
+ * hdd_add_ap_standard_info_sap - add HT and VHT info attributes
+ * @skb: pointer to response skb buffer
+ * @stainfo: station information
+ * @idx: attribute type index for nla_next_start()
+ *
+ * This function adds HT and VHT info attributes to response skb buffer
+ *
+ * Return : 0 on success and errno on failure
+ */
+static int hdd_add_ap_standard_info_sap(struct sk_buff *skb,
+					struct hdd_station_info *stainfo,
+					int idx)
+{
+	struct nlattr *nla_attr;
+
+	nla_attr = nla_nest_start(skb, idx);
+	if (!nla_attr)
+		goto fail;
+
+	if (stainfo->vht_present) {
+		if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
+			    sizeof(stainfo->vht_caps),
+			    &stainfo->vht_caps)) {
+			hdd_err("put fail");
+			goto fail;
+		}
+	}
+	if (stainfo->ht_present) {
+		if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
+			    sizeof(stainfo->ht_caps),
+			    &stainfo->ht_caps)) {
+			hdd_err("put fail");
+			goto fail;
+		}
+	}
+	nla_nest_end(skb, nla_attr);
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/**
+ * hdd_decode_ch_width - decode channel band width based
+ * @ch_width: encoded enum value holding channel band width
+ *
+ * This function decodes channel band width from the given encoded enum value.
+ *
+ * Returns: decoded channel band width.
+ */
+static uint8_t hdd_decode_ch_width(tSirMacHTChannelWidth ch_width)
+{
+	switch (ch_width) {
+	case 0:
+		return 20;
+	case 1:
+		return 40;
+	case 2:
+		return 80;
+	case 3:
+	case 4:
+		return 160;
+	default:
+		hdd_debug("invalid enum: %d", ch_width);
+		return 20;
+	}
+}
+
+/**
+ * hdd_get_cached_station_remote() - get cached(deleted) peer's info
+ * @hdd_ctx: hdd context
+ * @adapter: hostapd interface
+ * @mac_addr: mac address of requested peer
+ *
+ * This function collect and indicate the cached(deleted) peer's info
+ *
+ * Return: 0 on success, otherwise error value
+ */
+
+static int hdd_get_cached_station_remote(struct hdd_context *hdd_ctx,
+					 struct hdd_adapter *adapter,
+					 struct qdf_mac_addr mac_addr)
+{
+	struct hdd_station_info *stainfo = hdd_get_stainfo(
+						adapter->cache_sta_info,
+						mac_addr);
+	struct sk_buff *skb = NULL;
+	uint32_t nl_buf_len = NLMSG_HDRLEN;
+	uint8_t channel_width;
+
+	if (!stainfo) {
+		hdd_err("peer " MAC_ADDRESS_STR " not found",
+			MAC_ADDR_ARRAY(mac_addr.bytes));
+		return -EINVAL;
+	}
+
+	nl_buf_len += hdd_add_link_standard_info_sap_get_len() +
+			hdd_add_ap_standard_info_sap_get_len(stainfo) +
+			(sizeof(stainfo->dot11_mode) + NLA_HDRLEN) +
+			(sizeof(stainfo->ch_width) + NLA_HDRLEN) +
+			(sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
+			(sizeof(stainfo->rx_rate) + NLA_HDRLEN);
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
+	if (!skb) {
+		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+		return -ENOMEM;
+	}
+
+	if (hdd_add_link_standard_info_sap(skb, stainfo->rssi, stainfo,
+					   LINK_INFO_STANDARD_NL80211_ATTR)) {
+		hdd_err("link standard put fail");
+		goto fail;
+	}
+
+	if (hdd_add_ap_standard_info_sap(skb, stainfo,
+					 AP_INFO_STANDARD_NL80211_ATTR)) {
+		hdd_err("ap standard put fail");
+		goto fail;
+	}
+
+	/* upper layer expects decoded channel BW */
+	channel_width = hdd_decode_ch_width(stainfo->ch_width);
+
+	if (nla_put_u32(skb, REMOTE_SUPPORTED_MODE,
+			hdd_convert_dot11mode(
+			stainfo->mode)) ||
+	    nla_put_u8(skb, REMOTE_CH_WIDTH, channel_width)) {
+		hdd_err("remote ch put fail");
+		goto fail;
+	}
+	if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate)) {
+		hdd_err("tx rate put fail");
+		goto fail;
+	}
+	if (nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
+		hdd_err("rx rate put fail");
+		goto fail;
+	}
+
+	qdf_mem_zero(stainfo, sizeof(*stainfo));
+
+	return cfg80211_vendor_cmd_reply(skb);
+fail:
+	if (skb)
+		kfree_skb(skb);
+
+	return -EINVAL;
+}
+
+/**
+ * hdd_get_cached_station_remote() - get connected peer's info
+ * @hdd_ctx: hdd context
+ * @adapter: hostapd interface
+ * @mac_addr: mac address of requested peer
+ *
+ * This function collect and indicate the connected peer's info
+ *
+ * Return: 0 on success, otherwise error value
+ */
+static int hdd_get_connected_station_info(struct hdd_context *hdd_ctx,
+					  struct hdd_adapter *adapter,
+					  struct qdf_mac_addr mac_addr,
+					  struct hdd_station_info *stainfo)
+{
+	struct sk_buff *skb = NULL;
+	uint32_t nl_buf_len;
+	struct sir_peer_info_ext peer_info;
+	bool txrx_rate = true;
+
+	nl_buf_len = NLMSG_HDRLEN;
+	nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
+		(sizeof(stainfo->tx_packets) + NLA_HDRLEN) +
+		(sizeof(stainfo->tx_bytes) + NLA_HDRLEN) +
+		(sizeof(stainfo->rx_packets) + NLA_HDRLEN) +
+		(sizeof(stainfo->rx_bytes) + NLA_HDRLEN) +
+		(sizeof(stainfo->is_qos_enabled) + NLA_HDRLEN) +
+		(sizeof(stainfo->mode) + NLA_HDRLEN);
+
+	if (!hdd_ctx->config->sap_get_peer_info ||
+	    wlan_hdd_get_peer_info(adapter, mac_addr, &peer_info)) {
+		hdd_err("fail to get tx/rx rate");
+		txrx_rate = false;
+	} else {
+		stainfo->tx_rate = peer_info.tx_rate;
+		stainfo->rx_rate = peer_info.rx_rate;
+		nl_buf_len += (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
+			(sizeof(stainfo->rx_rate) + NLA_HDRLEN);
+	}
+
+	/* below info is only valid for HT/VHT mode */
+	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
+		nl_buf_len += (sizeof(stainfo->ampdu) + NLA_HDRLEN) +
+			(sizeof(stainfo->tx_stbc) + NLA_HDRLEN) +
+			(sizeof(stainfo->rx_stbc) + NLA_HDRLEN) +
+			(sizeof(stainfo->ch_width) + NLA_HDRLEN) +
+			(sizeof(stainfo->sgi_enable) + NLA_HDRLEN);
+
+	hdd_info("buflen %d hdrlen %d", nl_buf_len, NLMSG_HDRLEN);
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
+						  nl_buf_len);
+	if (!skb) {
+		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+		goto fail;
+	}
+
+	hdd_info("stainfo");
+	hdd_info("maxrate %x tx_pkts %x tx_bytes %llx",
+		 stainfo->max_phy_rate, stainfo->tx_packets,
+		 stainfo->tx_bytes);
+	hdd_info("rx_pkts %x rx_bytes %llx mode %x",
+		 stainfo->rx_packets, stainfo->rx_bytes,
+		 stainfo->mode);
+	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
+		hdd_info("ampdu %d tx_stbc %d rx_stbc %d",
+			 stainfo->ampdu, stainfo->tx_stbc,
+			 stainfo->rx_stbc);
+		hdd_info("wmm %d chwidth %d sgi %d",
+			 stainfo->is_qos_enabled,
+			 stainfo->ch_width,
+			 stainfo->sgi_enable);
+	}
+
+	if (nla_put_u32(skb, REMOTE_MAX_PHY_RATE, stainfo->max_phy_rate) ||
+	    nla_put_u32(skb, REMOTE_TX_PACKETS, stainfo->tx_packets) ||
+	    remote_station_put_u64(skb, REMOTE_TX_BYTES, stainfo->tx_bytes) ||
+	    nla_put_u32(skb, REMOTE_RX_PACKETS, stainfo->rx_packets) ||
+	    remote_station_put_u64(skb, REMOTE_RX_BYTES, stainfo->rx_bytes) ||
+	    nla_put_u8(skb, REMOTE_WMM, stainfo->is_qos_enabled) ||
+	    nla_put_u8(skb, REMOTE_SUPPORTED_MODE, stainfo->mode)) {
+		hdd_err("put fail");
+		goto fail;
+	}
+
+	if (txrx_rate) {
+		if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate) ||
+		    nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
+			hdd_err("put fail");
+			goto fail;
+		} else {
+			hdd_info("tx_rate %x rx_rate %x",
+				 stainfo->tx_rate, stainfo->rx_rate);
+		}
+	}
+
+	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
+		if (nla_put_u8(skb, REMOTE_AMPDU, stainfo->ampdu) ||
+		    nla_put_u8(skb, REMOTE_TX_STBC, stainfo->tx_stbc) ||
+		    nla_put_u8(skb, REMOTE_RX_STBC, stainfo->rx_stbc) ||
+		    nla_put_u8(skb, REMOTE_CH_WIDTH, stainfo->ch_width) ||
+		    nla_put_u8(skb, REMOTE_SGI_ENABLE, stainfo->sgi_enable)) {
+			hdd_err("put fail");
+			goto fail;
+		}
+	}
+
+	return cfg80211_vendor_cmd_reply(skb);
+
+fail:
+	if (skb)
+		kfree_skb(skb);
+
+	return -EINVAL;
+}
+
+/**
+ * hdd_get_station_remote() - get remote peer's info
+ * @hdd_ctx: hdd context
+ * @adapter: hostapd interface
+ * @mac_addr: mac address of requested peer
+ *
+ * This function collect and indicate the remote peer's info
+ *
+ * Return: 0 on success, otherwise error value
+ */
+static int hdd_get_station_remote(struct hdd_context *hdd_ctx,
+				  struct hdd_adapter *adapter,
+				  struct qdf_mac_addr mac_addr)
+{
+	struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
+							   mac_addr);
+	int status = 0;
+	bool is_associated = false;
+
+	if (!stainfo) {
+		status = hdd_get_cached_station_remote(hdd_ctx, adapter,
+						       mac_addr);
+		return status;
+	}
+
+	is_associated = hdd_is_peer_associated(adapter, &mac_addr);
+	if (!is_associated) {
+		status = hdd_get_cached_station_remote(hdd_ctx, adapter,
+						       mac_addr);
+		return status;
+	}
+
+	status = hdd_get_connected_station_info(hdd_ctx, adapter,
+						mac_addr, stainfo);
+	return status;
+}
+
+/**
+ * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
+ * @wiphy: corestack handler
+ * @wdev: wireless device
+ * @data: data
+ * @data_len: data length
+ *
+ * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
+ * Validate cmd attributes and send the station info to upper layers.
+ *
+ * Return: Success(0) or reason code for failure
+ */
+static int
+__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
+			       struct wireless_dev *wdev,
+			       const void *data,
+			       int data_len)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
+	int32_t status;
+
+	hdd_enter_dev(dev);
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		status = -EPERM;
+		goto out;
+	}
+
+	status = wlan_hdd_validate_context(hdd_ctx);
+	if (status != 0)
+		goto out;
+
+	status = wlan_cfg80211_nla_parse(tb,
+					 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
+					 data, data_len,
+					 hdd_get_station_policy);
+	if (status) {
+		hdd_err("Invalid ATTR");
+		goto out;
+	}
+
+	/* Parse and fetch Command Type*/
+	if (tb[STATION_INFO]) {
+		status = hdd_get_station_info(hdd_ctx, adapter);
+	} else if (tb[STATION_ASSOC_FAIL_REASON]) {
+		status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
+	} else if (tb[STATION_REMOTE]) {
+		struct qdf_mac_addr mac_addr;
+
+		if (adapter->device_mode != QDF_SAP_MODE &&
+		    adapter->device_mode != QDF_P2P_GO_MODE) {
+			hdd_err("invalid device_mode:%d", adapter->device_mode);
+			status = -EINVAL;
+			goto out;
+		}
+
+		nla_memcpy(mac_addr.bytes, tb[STATION_REMOTE],
+			   QDF_MAC_ADDR_SIZE);
+
+		hdd_debug("STATION_REMOTE " MAC_ADDRESS_STR,
+			  MAC_ADDR_ARRAY(mac_addr.bytes));
+
+		status = hdd_get_station_remote(hdd_ctx, adapter, mac_addr);
+	} else {
+		hdd_err("get station info cmd type failed");
+		status = -EINVAL;
+		goto out;
+	}
+	hdd_exit();
+out:
+	return status;
+}
+
+int32_t hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data,
+				     int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_station_info.h b/core/hdd/src/wlan_hdd_station_info.h
new file mode 100644
index 0000000..84e2c86
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_station_info.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_STATION_INFO_H
+#define __WLAN_HDD_STATION_INFO_H
+
+/**
+ * DOC: wlan_hdd_station_info_h
+ *
+ * WLAN Host Device Driver STATION info API specification
+ */
+
+#ifdef FEATURE_STATION_INFO
+/**
+ * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
+ * @wiphy: corestack handler
+ * @wdev: wireless device
+ * @data: data
+ * @data_len: data length
+ *
+ * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
+ * Validate cmd attributes and send the station info to upper layers.
+ *
+ * Return: Success(0) or reason code for failure
+ */
+int32_t hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data,
+				     int data_len);
+
+#define FEATURE_STATION_INFO_VENDOR_COMMANDS				\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,		\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+		WIPHY_VENDOR_CMD_NEED_NETDEV |				\
+		WIPHY_VENDOR_CMD_NEED_RUNNING,				\
+	.doit = hdd_cfg80211_get_station_cmd				\
+},
+#else /* FEATURE_STATION_INFO */
+#define FEATURE_STATION_INFO_VENDOR_COMMANDS
+#endif /* FEATURE_STATION_INFO */
+
+#endif /* __WLAN_HDD_STATION_INFO_H */
+
diff --git a/core/hdd/src/wlan_hdd_tx_power.c b/core/hdd/src/wlan_hdd_tx_power.c
new file mode 100644
index 0000000..5ed261a
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_tx_power.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2012-2018 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: wlan_hdd_tx_power.c
+ *
+ * WLAN tx power setting functions
+ *
+ */
+
+#include <wlan_hdd_includes.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <wma_api.h>
+#include <wlan_hdd_tx_power.h>
+
+#define MAX_TXPOWER_SCALE 4
+
+static const struct nla_policy
+txpower_scale_policy[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE] = { .type = NLA_U8 },
+};
+
+/**
+ * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
+					     struct wireless_dev *wdev,
+					     const void *data,
+					     int data_len)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter;
+	int ret;
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
+	uint8_t scale_value;
+	QDF_STATUS status;
+
+	hdd_enter_dev(dev);
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
+				    data, data_len, txpower_scale_policy)) {
+		hdd_err("Invalid ATTR");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
+		hdd_err("attr tx power scale failed");
+		return -EINVAL;
+	}
+
+	scale_value = nla_get_u8(tb
+		    [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
+
+	if (scale_value > MAX_TXPOWER_SCALE) {
+		hdd_err("Invalid tx power scale level");
+		return -EINVAL;
+	}
+
+	status = wma_set_tx_power_scale(adapter->session_id, scale_value);
+
+	if (status != QDF_STATUS_SUCCESS) {
+		hdd_err("Set tx power scale failed");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
+				    struct wireless_dev *wdev,
+				    const void *data,
+				    int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
+						data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
+static const struct nla_policy txpower_scale_decr_db_policy
+[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB] = { .type = NLA_U8 },
+};
+
+/**
+ * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int
+__wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
+					  struct wireless_dev *wdev,
+					  const void *data,
+					  int data_len)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter;
+	int ret;
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
+	uint8_t scale_value;
+	QDF_STATUS status;
+
+	hdd_enter_dev(dev);
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+	if (wlan_cfg80211_nla_parse(tb,
+				QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
+				data, data_len,
+				txpower_scale_decr_db_policy)) {
+		hdd_err("Invalid ATTR");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
+		hdd_err("attr tx power decrease db value failed");
+		return -EINVAL;
+	}
+
+	scale_value = nla_get_u8(tb
+		    [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
+
+	status = wma_set_tx_power_scale_decr_db(adapter->session_id,
+						scale_value);
+
+	if (status != QDF_STATUS_SUCCESS) {
+		hdd_err("Set tx power decrease db failed");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data,
+					    int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
+							data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_tx_power.h b/core/hdd/src/wlan_hdd_tx_power.h
new file mode 100644
index 0000000..3ba2792
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_tx_power.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012-2018 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_HDD_TX_POWER_H
+#define __WLAN_HDD_TX_POWER_H
+
+/**
+ * DOC: wlan_hdd_tx_power_h
+ *
+ * WLAN Host Device Driver TX power setting API specification
+ */
+
+#ifdef FEATURE_TX_POWER
+/**
+ * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
+				    struct wireless_dev *wdev,
+				    const void *data,
+				    int data_len);
+
+/**
+ * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data,
+					    int data_len);
+
+#define FEATURE_TX_POWER_VENDOR_COMMANDS				\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+			 WIPHY_VENDOR_CMD_NEED_NETDEV |			\
+			 WIPHY_VENDOR_CMD_NEED_RUNNING,			\
+	.doit = wlan_hdd_cfg80211_txpower_scale				\
+},									\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd =							\
+		QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+			 WIPHY_VENDOR_CMD_NEED_NETDEV |			\
+			 WIPHY_VENDOR_CMD_NEED_RUNNING,			\
+	.doit = wlan_hdd_cfg80211_txpower_scale_decr_db			\
+},
+#else /* FEATURE_TX_POWER */
+#define FEATURE_TX_POWER_VENDOR_COMMANDS
+#endif /* FEATURE_TX_POWER */
+
+#endif /* __WLAN_HDD_TX_POWER_H */
+
diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c
index 1771441..5938221 100644
--- a/core/sap/src/sap_module.c
+++ b/core/sap/src/sap_module.c
@@ -1525,6 +1525,7 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef FEATURE_SAP_COND_CHAN_SWITCH
 QDF_STATUS wlan_sap_set_pre_cac_status(struct sap_context *sap_ctx,
 				       bool status, tHalHandle handle)
 {
@@ -1561,6 +1562,7 @@
 	sap_ctx->chan_before_pre_cac = chan_before_pre_cac;
 	return QDF_STATUS_SUCCESS;
 }
+#endif /* FEATURE_SAP_COND_CHAN_SWITCH */
 
 QDF_STATUS wlan_sap_set_pre_cac_complete_status(struct sap_context *sap_ctx,
 						bool status)
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index d72b73b..19545bf 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -910,12 +910,27 @@
 QDF_STATUS sme_get_channel_bonding_mode5_g(tHalHandle hHal, uint32_t *mode);
 QDF_STATUS sme_get_channel_bonding_mode24_g(tHalHandle hHal, uint32_t *mode);
 
-#ifdef WLAN_FEATURE_STATS_EXT
+/**
+ * sme_send_unit_test_cmd() - send unit test command to lower layer
+ * @session_id: sme session id to be filled while forming the command
+ * @module_id: module id given by user to be filled in the command
+ * @arg_count: number of argument count
+ * @arg: pointer to argument list
+ *
+ * This API exposed to HDD layer which takes the argument from user and sends
+ * down to lower layer for further processing
+ *
+ * Return: QDF_STATUS based on overall success
+ */
+QDF_STATUS sme_send_unit_test_cmd(uint32_t vdev_id, uint32_t module_id,
+				  uint32_t arg_count, uint32_t *arg);
+
 typedef struct sStatsExtRequestReq {
 	uint32_t request_data_len;
 	uint8_t *request_data;
 } tStatsExtRequestReq, *tpStatsExtRequestReq;
 
+#ifdef WLAN_FEATURE_STATS_EXT
 /**
  * sme_stats_ext_register_callback() - Register stats ext callback
  * @mac_handle: Opaque handle to the MAC context
@@ -951,23 +966,19 @@
 
 QDF_STATUS sme_stats_ext_request(uint8_t session_id,
 				 tpStatsExtRequestReq input);
+#else
+static inline void
+sme_stats_ext_register_callback(mac_handle_t mac_handle,
+				stats_ext_cb callback)
+{
+}
+
+static inline void
+sme_stats_ext2_register_callback(tHalHandle hal_handle,
+				 stats_ext2_cb callback)
+{
+}
 #endif /* WLAN_FEATURE_STATS_EXT */
-
-/**
- * sme_send_unit_test_cmd() - send unit test command to lower layer
- * @session_id: sme session id to be filled while forming the command
- * @module_id: module id given by user to be filled in the command
- * @arg_count: number of argument count
- * @arg: pointer to argument list
- *
- * This API exposed to HDD layer which takes the argument from user and sends
- * down to lower layer for further processing
- *
- * Return: QDF_STATUS based on overall success
- */
-QDF_STATUS sme_send_unit_test_cmd(uint32_t vdev_id, uint32_t module_id,
-				  uint32_t arg_count, uint32_t *arg);
-
 QDF_STATUS sme_update_dfs_scan_mode(tHalHandle hHal,
 		uint8_t sessionId,
 		uint8_t allowDFSChannelRoam);
@@ -1182,6 +1193,7 @@
 				       sme_ac_enum_type ac,
 				       uint32_t sessionId);
 
+#ifdef FEATURE_RSSI_MONITOR
 QDF_STATUS sme_set_rssi_monitoring(tHalHandle hal,
 					struct rssi_monitor_req *input);
 
@@ -1196,7 +1208,14 @@
  */
 QDF_STATUS sme_set_rssi_threshold_breached_cb(mac_handle_t mac_handle,
 					      rssi_threshold_breached_cb cb);
-
+#else /* FEATURE_RSSI_MONITOR */
+static inline
+QDF_STATUS sme_set_rssi_threshold_breached_cb(mac_handle_t mac_handle,
+					      rssi_threshold_breached_cb cb)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 /**
  * sme_reset_rssi_threshold_breached_cb() - Reset RSSI threshold breached
  *                                          callback
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 8d374a1..153e203 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -12995,35 +12995,6 @@
 	return status;
 }
 
-QDF_STATUS sme_set_rssi_threshold_breached_cb(mac_handle_t mac_handle,
-					      rssi_threshold_breached_cb cb)
-{
-	QDF_STATUS status;
-	tpAniSirGlobal mac;
-
-	mac = MAC_CONTEXT(mac_handle);
-	if (!mac) {
-		sme_err("Invalid mac context");
-		return QDF_STATUS_E_INVAL;
-	}
-
-	status = sme_acquire_global_lock(&mac->sme);
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
-		sme_err("sme_acquire_global_lock failed!(status=%d)",
-			status);
-		return status;
-	}
-
-	mac->sme.rssi_threshold_breached_cb = cb;
-	sme_release_global_lock(&mac->sme);
-	return status;
-}
-
-QDF_STATUS sme_reset_rssi_threshold_breached_cb(mac_handle_t mac_handle)
-{
-	return sme_set_rssi_threshold_breached_cb(mac_handle, NULL);
-}
-
 /**
  * sme_is_any_session_in_connected_state() - SME wrapper API to
  * check if any session is in connected state or not.
@@ -13066,6 +13037,7 @@
 	return status;
 }
 
+#ifdef FEATURE_RSSI_MONITOR
 /**
  * sme_set_rssi_monitoring() - set rssi monitoring
  * @hal: global hal handle
@@ -13113,6 +13085,36 @@
 	return status;
 }
 
+QDF_STATUS sme_set_rssi_threshold_breached_cb(mac_handle_t mac_handle,
+					      rssi_threshold_breached_cb cb)
+{
+	QDF_STATUS status;
+	tpAniSirGlobal mac;
+
+	mac = MAC_CONTEXT(mac_handle);
+	if (!mac) {
+		sme_err("Invalid mac context");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = sme_acquire_global_lock(&mac->sme);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		sme_err("sme_acquire_global_lock failed!(status=%d)",
+			status);
+		return status;
+	}
+
+	mac->sme.rssi_threshold_breached_cb = cb;
+	sme_release_global_lock(&mac->sme);
+	return status;
+}
+#endif /* FEATURE_RSSI_MONITOR */
+
+QDF_STATUS sme_reset_rssi_threshold_breached_cb(mac_handle_t mac_handle)
+{
+	return sme_set_rssi_threshold_breached_cb(mac_handle, NULL);
+}
+
 /*
  * sme_pdev_set_pcl() - Send WMI_PDEV_SET_PCL_CMDID to the WMA
  * @hal: Handle returned by macOpen
@@ -15708,6 +15710,16 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+uint32_t sme_unpack_rsn_ie(tHalHandle hal, uint8_t *buf,
+			   uint8_t buf_len, tDot11fIERSN *rsn_ie,
+			   bool append_ie)
+{
+	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+
+	return dot11f_unpack_ie_rsn(mac_ctx, buf, buf_len, rsn_ie, append_ie);
+}
+
+#ifdef FEATURE_BSS_TRANSITION
 /**
  * sme_get_status_for_candidate() - Get bss transition status for candidate
  * @hal: Handle for HAL
@@ -15806,15 +15818,6 @@
 	return false;
 }
 
-uint32_t sme_unpack_rsn_ie(tHalHandle hal, uint8_t *buf,
-				  uint8_t buf_len, tDot11fIERSN *rsn_ie,
-				  bool append_ie)
-{
-	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
-
-	return dot11f_unpack_ie_rsn(mac_ctx, buf, buf_len, rsn_ie, append_ie);
-}
-
 /**
  * wlan_hdd_get_bss_transition_status() - get bss transition status all cadidates
  * @adapter : Pointer to adapter
@@ -15896,6 +15899,7 @@
 
 	return status;
 }
+#endif /* FEATURE_BSS_TRANSITION */
 
 void sme_enable_roaming_on_connected_sta(tHalHandle hal)
 {
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index a0055b8..0dfa018 100644
--- a/core/wma/inc/wma.h
+++ b/core/wma/inc/wma.h
@@ -1729,8 +1729,17 @@
 void wma_send_flush_logs_to_fw(tp_wma_handle wma_handle);
 void wma_log_completion_timeout(void *data);
 
+#ifdef FEATURE_RSSI_MONITOR
 QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma,
-					struct rssi_monitor_req *req);
+				   struct rssi_monitor_req *req);
+#else /* FEATURE_RSSI_MONITOR */
+static inline
+QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma,
+				   struct rssi_monitor_req *req)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* FEATURE_RSSI_MONITOR */
 
 QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle,
 		struct wmi_pcl_chan_weights *msg);
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index 59124c2..bba583e 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -1094,8 +1094,17 @@
 void wma_set_vdev_mgmt_rate(tp_wma_handle wma, uint8_t vdev_id);
 void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id);
 
+#ifdef FEATURE_RSSI_MONITOR
 int wma_rssi_breached_event_handler(void *handle,
 				u_int8_t  *cmd_param_info, u_int32_t len);
+#else /* FEATURE_RSSI_MONITOR */
+static inline
+int wma_rssi_breached_event_handler(void *handle,
+				u_int8_t  *cmd_param_info, u_int32_t len)
+{
+	return 0;
+}
+#endif /* FEATURE_RSSI_MONITOR */
 
 QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
 				   struct vdev_ie_info *ie_info);
diff --git a/core/wma/src/wma_power.c b/core/wma/src/wma_power.c
index 35e3abe..96e04a8 100644
--- a/core/wma/src/wma_power.c
+++ b/core/wma/src/wma_power.c
@@ -1690,6 +1690,7 @@
 	return ret;
 }
 
+#ifdef FEATURE_TX_POWER
 /**
  * wma_set_tx_power_scale() - set tx power scale
  * @vdev_id: vdev id
@@ -1751,3 +1752,5 @@
 
 	return ret;
 }
+#endif /* FEATURE_TX_POWER */
+
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index f988230..f4d7ca7 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/core/wma/src/wma_scan_roam.c
@@ -2853,6 +2853,37 @@
 }
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
 
+#ifdef FEATURE_RSSI_MONITOR
+/**
+ * wma_set_rssi_monitoring() - set rssi monitoring
+ * @handle: WMA handle
+ * @req: rssi monitoring request structure
+ *
+ * This function reads the incoming @req and fill in the destination
+ * WMI structure and send down the rssi monitoring configs down to the firmware
+ *
+ * Return: 0 on success; error number otherwise
+ */
+QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma,
+				   struct rssi_monitor_req *req)
+{
+	struct rssi_monitor_param params = {0};
+
+	if (!wma) {
+		WMA_LOGE("%s: wma handle is NULL", __func__);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	params.request_id = req->request_id;
+	params.session_id = req->session_id;
+	params.min_rssi = req->min_rssi;
+	params.max_rssi = req->max_rssi;
+	params.control = req->control;
+
+	return wmi_unified_set_rssi_monitoring_cmd(wma->wmi_handle,
+						   &params);
+}
+
 /**
  * wma_rssi_breached_event_handler() - rssi breached event handler
  * @handle: wma handle
@@ -2890,13 +2921,14 @@
 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, rssi.curr_bssid.bytes);
 
 	WMA_LOGD("%s: req_id: %u vdev_id: %d curr_rssi: %d", __func__,
-		rssi.request_id, rssi.session_id, rssi.curr_rssi);
+		 rssi.request_id, rssi.session_id, rssi.curr_rssi);
 	WMA_LOGI("%s: curr_bssid: %pM", __func__, rssi.curr_bssid.bytes);
 
 	mac->sme.rssi_threshold_breached_cb(mac->hdd_handle, &rssi);
 	WMA_LOGD("%s: Invoke HDD rssi breached callback", __func__);
 	return 0;
 }
+#endif /* FEATURE_RSSI_MONITOR */
 
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 /**
@@ -5268,37 +5300,6 @@
 	return 0;
 }
 
-
-/**
- * wma_set_rssi_monitoring() - set rssi monitoring
- * @handle: WMA handle
- * @req: rssi monitoring request structure
- *
- * This function reads the incoming @req and fill in the destination
- * WMI structure and send down the rssi monitoring configs down to the firmware
- *
- * Return: 0 on success; error number otherwise
- */
-QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma,
-					struct rssi_monitor_req *req)
-{
-	struct rssi_monitor_param params = {0};
-
-	if (!wma) {
-		WMA_LOGE("%s: wma handle is NULL", __func__);
-		return QDF_STATUS_E_INVAL;
-	}
-
-	 params.request_id = req->request_id;
-	 params.session_id = req->session_id;
-	 params.min_rssi = req->min_rssi;
-	 params.max_rssi = req->max_rssi;
-	 params.control = req->control;
-
-	return wmi_unified_set_rssi_monitoring_cmd(wma->wmi_handle,
-						&params);
-}
-
 #ifdef FEATURE_LFR_SUBNET_DETECTION
 /**
  * wma_set_gateway_params() - set gateway parameters