qcacld-3.0: Add get antenna isolation command

Propagation from qcacld2.0 to qcacld3.0.
The WMI CMD and EVENT of "get antenna isolation" are already defined,
but not used before in qcacld3.0.
Now, The host driver uses vendor command to get this information
instead of iwpriv command in qcacld-2.0.
The attribution of this feature is already defined in file
"qca_vendor.h". The name is "QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION".
So host driver will use vendor command
"QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY" to get the information
from lower layer.

Change-Id: I915768f622ddc9a70a95ce4fe952f19917a8f901
CRs-Fixed: 2447360
diff --git a/Kbuild b/Kbuild
index ef00a96..f292fa7 100644
--- a/Kbuild
+++ b/Kbuild
@@ -245,6 +245,10 @@
 HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_bcn_recv.o
 endif
 
+ifeq ($(CONFIG_QCACLD_FEATURE_HW_CAPABILITY), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_hw_capability.o
+endif
+
 ###### OSIF_SYNC ########
 SYNC_DIR := os_if/sync
 SYNC_INC_DIR := $(SYNC_DIR)/inc
@@ -2607,6 +2611,9 @@
 #Flag to enable MPTA helper feature
 cppflags-$(CONFIG_QCACLD_FEATURE_MPTA_HELPER) += -DFEATURE_MPTA_HELPER
 
+#Flag to enable get hw capability
+cppflags-$(CONFIG_QCACLD_FEATURE_HW_CAPABILITY) += -DFEATURE_HW_CAPABILITY
+
 cppflags-$(CONFIG_DATA_CE_SW_INDEX_NO_INLINE_UPDATE) += -DDATA_CE_SW_INDEX_NO_INLINE_UPDATE
 
 #Flag to enable Multi page memory allocation for RX descriptor pool
diff --git a/configs/default_defconfig b/configs/default_defconfig
index 36b847b..a8cf808 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -129,6 +129,11 @@
 #Flag to enable set coex configuration
 CONFIG_QCACLD_FEATURE_COEX_CONFIG := n
 
+#Flag to enable get hw capability
+ifeq ($(CONFIG_ARCH_QCS405), y)
+CONFIG_QCACLD_FEATURE_HW_CAPABILITY := y
+endif
+
 ifeq ($(CONFIG_ARCH_MSM8998), y)
 CONFIG_QCACLD_FEATURE_METERING := y
 endif
diff --git a/configs/qcs40x.snoc.perf_defconfig b/configs/qcs40x.snoc.perf_defconfig
index d03795e..82b50fd 100644
--- a/configs/qcs40x.snoc.perf_defconfig
+++ b/configs/qcs40x.snoc.perf_defconfig
@@ -102,6 +102,7 @@
 CONFIG_WMI_INTERFACE_EVENT_LOGGING := y
 CONFIG_WLAN_FEATURE_LINK_LAYER_STATS := y
 CONFIG_DP_TRACE := n
+CONFIG_QCACLD_FEATURE_HW_CAPABILITY := y
 
 CONFIG_WLAN_LOG_FATAL := y
 CONFIG_WLAN_LOG_ERROR := y
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index b42417f..2447217 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -237,6 +237,8 @@
 
 #define WLAN_WAIT_TIME_FW_ROAM_STATS 1000
 
+#define WLAN_WAIT_TIME_ANTENNA_ISOLATION 8000
+
 /* Maximum time(ms) to wait for RSO CMD status event */
 #define WAIT_TIME_RSO_CMD_STATUS 2000
 
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 1258b3a..7c7bcbb 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -142,6 +142,7 @@
 #include "wlan_hdd_coex_config.h"
 #include "wlan_hdd_bcn_recv.h"
 #include "wlan_blm_ucfg_api.h"
+#include "wlan_hdd_hw_capability.h"
 
 #define g_mode_rates_size (12)
 #define a_mode_rates_size (8)
@@ -13139,6 +13140,7 @@
 	FEATURE_FW_STATE_COMMANDS
 	FEATURE_COEX_CONFIG_COMMANDS
 	FEATURE_MPTA_HELPER_COMMANDS
+	FEATURE_HW_CAPABILITY_COMMANDS
 };
 
 struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
diff --git a/core/hdd/src/wlan_hdd_hw_capability.c b/core/hdd/src/wlan_hdd_hw_capability.c
new file mode 100644
index 0000000..9898c6a
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_hw_capability.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2019 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_hw_capability.c
+ *
+ * The implementation of get hw capability
+ *
+ */
+
+#include "wlan_hdd_main.h"
+#include "wmi_unified_param.h"
+#include "wlan_hdd_hw_capability.h"
+#include "qca_vendor.h"
+#include "wlan_osif_request_manager.h"
+#include "osif_sync.h"
+
+/**
+ * hdd_get_isolation_cb - Callback function to get isolation information
+ * @context: opaque context originally passed to SME. HDD always passes
+ * a cookie for the request context
+ * @isolation: pointer of isolation information
+ *
+ * This function will fill isolation information to isolation priv adapter
+ *
+ * Return: None
+ */
+static void hdd_get_isolation_cb(struct sir_isolation_resp *isolation,
+				 void *context)
+{
+	struct osif_request *request;
+	struct sir_isolation_resp *priv;
+
+	if (!isolation) {
+		hdd_err("Bad param");
+		return;
+	}
+
+	request = osif_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
+		return;
+	}
+
+	priv = osif_request_priv(request);
+	priv->isolation_chain0 = isolation->isolation_chain0;
+	priv->isolation_chain1 = isolation->isolation_chain1;
+	priv->isolation_chain2 = isolation->isolation_chain2;
+	priv->isolation_chain3 = isolation->isolation_chain3;
+
+	osif_request_complete(request);
+	osif_request_put(request);
+}
+
+/**
+ * hdd_post_isolation - send rsp to user space
+ * @hdd_ctx: pointer to hdd context
+ * @isolation: antenna isolation information
+ *
+ * Return: 0 for success, non-zero for failure
+ */
+static int hdd_post_isolation(struct hdd_context *hdd_ctx,
+			      struct sir_isolation_resp *isolation)
+{
+	struct sk_buff *skb;
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
+						  (sizeof(u8) + NLA_HDRLEN) +
+						  (sizeof(u8) + NLA_HDRLEN) +
+						  (sizeof(u8) + NLA_HDRLEN) +
+						  (sizeof(u8) + NLA_HDRLEN) +
+						  NLMSG_HDRLEN);
+
+	if (!skb) {
+		hdd_err("cfg80211_vendor_event_alloc failed");
+		return -ENOMEM;
+	}
+
+	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION,
+		       isolation->isolation_chain0)) {
+		hdd_err("put fail");
+		goto nla_put_failure;
+	}
+
+	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION,
+		       isolation->isolation_chain1)) {
+		hdd_err("put fail");
+		goto nla_put_failure;
+	}
+
+	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION,
+		       isolation->isolation_chain2)) {
+		hdd_err("put fail");
+		goto nla_put_failure;
+	}
+
+	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION,
+		       isolation->isolation_chain3)) {
+		hdd_err("put fail");
+		goto nla_put_failure;
+	}
+
+	cfg80211_vendor_cmd_reply(skb);
+	return 0;
+
+nla_put_failure:
+	kfree_skb(skb);
+	return -EINVAL;
+}
+
+/**
+ * __wlan_hdd_cfg80211_get_hw_capability() - get hw capability
+ * @wiphy: wiphy device pointer
+ * @wdev: wireless device pointer
+ * @data: Vendor command data buffer
+ * @data_len: Buffer length
+ *
+ * Return: 0 on success; error number otherwise.
+ *
+ */
+static int __wlan_hdd_cfg80211_get_hw_capability(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 sir_isolation_resp *priv;
+	mac_handle_t mac_handle;
+	void *cookie;
+	QDF_STATUS status;
+	int ret;
+	static const struct osif_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_ANTENNA_ISOLATION,
+	};
+
+	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_isolation(mac_handle,
+				   cookie,
+				   hdd_get_isolation_cb);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Unable to retrieve isolation");
+		ret = -EFAULT;
+	} else {
+		ret = osif_request_wait_for_response(request);
+		if (ret) {
+			hdd_err("SME timed out while retrieving isolation");
+			ret = -ETIMEDOUT;
+		} else {
+			priv = osif_request_priv(request);
+			hdd_post_isolation(hdd_ctx, priv);
+			ret = 0;
+		}
+	}
+	osif_request_put(request);
+
+	return ret;
+}
+
+int wlan_hdd_cfg80211_get_hw_capability(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data,
+					int data_len)
+{
+	int errno;
+	struct osif_vdev_sync *vdev_sync;
+
+	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_cfg80211_get_hw_capability(wiphy, wdev,
+						      data, data_len);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+
+	return errno;
+}
diff --git a/core/hdd/src/wlan_hdd_hw_capability.h b/core/hdd/src/wlan_hdd_hw_capability.h
new file mode 100644
index 0000000..0cbdc07
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_hw_capability.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 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_hw_capability.h
+ *
+ * Add Vendor subcommand QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY
+ */
+
+#ifndef __WLAN_HDD_HW_CAPABILITY_H
+#define __WLAN_HDD_HW_CAPABILITY_H
+
+#ifdef FEATURE_HW_CAPABILITY
+#include <net/cfg80211.h>
+
+/**
+ * wlan_hdd_cfg80211_get_hw_capability() - get hardware capability
+ * @wiphy: wiphy device pointer
+ * @wdev: wireless device pointer
+ * @data: Vendor command data buffer
+ * @data_len: Buffer length
+ *
+ * Return: 0 on success; error number otherwise.
+ */
+int wlan_hdd_cfg80211_get_hw_capability(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data,
+					int data_len);
+
+#define FEATURE_HW_CAPABILITY_COMMANDS				\
+{								\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,		\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY,\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |			\
+		WIPHY_VENDOR_CMD_NEED_NETDEV |			\
+		WIPHY_VENDOR_CMD_NEED_RUNNING,			\
+	.doit = wlan_hdd_cfg80211_get_hw_capability			\
+},
+#else /* FEATURE_HW_CAPABILITY */
+#define FEATURE_HW_CAPABILITY_COMMANDS
+#endif /* FEATURE_HW_CAPABILITY */
+
+#endif /* __WLAN_HDD_HW_CAPABILITY_H */
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 34fc7e4..970440e 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -2712,6 +2712,20 @@
 	struct sir_peer_info_ext info[MAX_PEER_STA];
 };
 
+/**
+ * struct sir_isolation_resp - isolation info related structure
+ * @isolation_chain0: isolation value for chain 0
+ * @isolation_chain1: isolation value for chain 1
+ * @isolation_chain2: isolation value for chain 2
+ * @isolation_chain3: isolation value for chain 3
+ */
+struct sir_isolation_resp {
+	uint32_t isolation_chain0:8,
+		 isolation_chain1:8,
+		 isolation_chain2:8,
+		 isolation_chain3:8;
+};
+
 typedef struct sSirAddPeriodicTxPtrn {
 	/* MAC Address for the adapter */
 	struct qdf_mac_addr mac_address;
diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h
index a31ae81..2789f49 100644
--- a/core/mac/inc/wni_api.h
+++ b/core/mac/inc/wni_api.h
@@ -238,7 +238,8 @@
 	eWNI_SME_FW_STATUS_IND = SIR_SME_MSG_TYPES_BEGIN + 152,
 	eWNI_SME_STA_CSA_CONTINUE_REQ = SIR_SME_MSG_TYPES_BEGIN + 153,
 	WNI_SME_REGISTER_BCN_REPORT_SEND_CB = SIR_SME_MSG_TYPES_BEGIN + 154,
-	eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 155
+	eWNI_SME_ANTENNA_ISOLATION_RSP = SIR_SME_MSG_TYPES_BEGIN + 155,
+	eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 156
 };
 
 typedef struct sAniCfgTxRateCtrs {
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 07569e8..d5bdd1f 100644
--- a/core/mac/src/include/sir_params.h
+++ b/core/mac/src/include/sir_params.h
@@ -663,6 +663,8 @@
 
 #define SIR_HAL_SEND_PEER_UNMAP_CONF        (SIR_HAL_ITC_MSG_TYPES_BEGIN + 411)
 
+#define SIR_HAL_GET_ISOLATION              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 412)
+
 #define SIR_HAL_MSG_TYPES_END               (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
 /* LIM message types */
diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
index 71fe945..43b56d2 100644
--- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
+++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
@@ -370,6 +370,7 @@
 		CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END);
 		CASE_RETURN_STRING(eWNI_SME_HIDDEN_SSID_RESTART_RSP);
 		CASE_RETURN_STRING(eWNI_SME_STA_CSA_CONTINUE_REQ);
+		CASE_RETURN_STRING(eWNI_SME_ANTENNA_ISOLATION_RSP);
 	default:
 		return (uint8_t *) "UNKNOWN";
 		break;
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 8e2d860..25cade9 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -2271,6 +2271,20 @@
 			      get_chain_rssi_callback callback,
 			      void *context);
 
+/**
+ * sme_get_isolation() - sme api to get antenna isolation
+ * @mac_handle: hal handle for getting global mac struct
+ * @context: context of callback function
+ * @callbackfn: hdd callback function when receive response
+ *
+ * This function will send WMA_GET_ISOLATION to WMA
+ *
+ * Return: QDF_STATUS_SUCCESS or non-zero on failure
+ */
+QDF_STATUS sme_get_isolation(mac_handle_t mac_handle,
+			     void *context,
+			     sme_get_isolation_cb callbackfn);
+
 #ifdef FEATURE_FW_STATE
 /**
  * sme_get_fw_state() - Get fw state
diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h
index 59fbb1c..7f8f150 100644
--- a/core/sme/inc/sme_internal.h
+++ b/core/sme/inc/sme_internal.h
@@ -277,6 +277,15 @@
 				enum scan_event_type type,
 				bool is_disconnected);
 
+/**
+ * typedef sme_get_isolation_cb - get isolation callback fun
+ * @param: isolation result reported by firmware
+ * @pcontext: Opaque context that the client can use to associate the
+ *    callback with the request
+ */
+typedef void (*sme_get_isolation_cb)(struct sir_isolation_resp *param,
+				     void *pcontext);
+
 #ifdef WLAN_FEATURE_MOTION_DETECTION
 typedef QDF_STATUS (*md_host_evt_cb)(void *hdd_ctx, struct sir_md_evt *event);
 #endif /* WLAN_FEATURE_MOTION_DETECTION */
@@ -325,6 +334,8 @@
 	void (*pget_peer_info_ext_ind_cb)(struct sir_peer_info_ext_resp *param,
 		void *pcontext);
 	void *pget_peer_info_ext_cb_context;
+	sme_get_isolation_cb get_isolation_cb;
+	void *get_isolation_cb_context;
 #ifdef FEATURE_WLAN_EXTSCAN
 	ext_scan_ind_cb ext_scan_ind_cb;
 #endif /* FEATURE_WLAN_EXTSCAN */
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 8392012..8613c9f 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -2264,6 +2264,17 @@
 		else
 			sme_err("callback is NULL");
 		break;
+	case eWNI_SME_ANTENNA_ISOLATION_RSP:
+		if (pMsg->bodyptr) {
+			if (mac->sme.get_isolation_cb)
+				mac->sme.get_isolation_cb(
+				  (struct sir_isolation_resp *)pMsg->bodyptr,
+				  mac->sme.get_isolation_cb_context);
+			qdf_mem_free(pMsg->bodyptr);
+		} else {
+			sme_err("Empty message for: %d", pMsg->type);
+		}
+		break;
 	default:
 
 		if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN)
@@ -7567,6 +7578,36 @@
 	return status;
 }
 
+QDF_STATUS sme_get_isolation(mac_handle_t mac_handle, void *context,
+			     sme_get_isolation_cb callbackfn)
+{
+	QDF_STATUS status;
+	struct mac_context  *mac = MAC_CONTEXT(mac_handle);
+	struct scheduler_msg message = {0};
+
+	if (!callbackfn) {
+		sme_err("Indication Call back is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
+	mac->sme.get_isolation_cb = callbackfn;
+	mac->sme.get_isolation_cb_context = context;
+	message.bodyptr = NULL;
+	message.type    = WMA_GET_ISOLATION;
+	status = scheduler_post_message(QDF_MODULE_ID_SME,
+					QDF_MODULE_ID_WMA,
+					QDF_MODULE_ID_WMA,
+					&message);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		sme_err("failed to post WMA_GET_ISOLATION");
+		status = QDF_STATUS_E_FAILURE;
+	}
+	sme_release_global_lock(&mac->sme);
+	return status;
+}
+
 /*convert the ini value to the ENUM used in csr and MAC for CB state*/
 ePhyChanBondState sme_get_cb_phy_state_from_cb_ini_value(uint32_t cb_ini_value)
 {
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index 0e37064..bad0b95 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -1061,6 +1061,16 @@
 				struct sir_peer_info_ext_req *peer_info_req);
 
 /**
+ * wma_get_isolation() - get antenna isolation
+ * @handle: wma interface
+ *
+ * This function will send WMI_COEX_GET_ANTENNA_ISOLATION_CMDID to FW
+ *
+ * Return: 0 on success, otherwise error value
+ */
+QDF_STATUS wma_get_isolation(tp_wma_handle wma);
+
+/**
  * wma_peer_info_event_handler() - Handler for WMI_PEER_STATS_INFO_EVENTID
  * @handle: WMA global handle
  * @cmd_param_info: Command event data
diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h
index c8fc52e..7a620dd 100644
--- a/core/wma/inc/wma_types.h
+++ b/core/wma/inc/wma_types.h
@@ -336,6 +336,8 @@
 #define WMA_GET_PEER_INFO          SIR_HAL_GET_PEER_INFO
 #define WMA_GET_PEER_INFO_EXT      SIR_HAL_GET_PEER_INFO_EXT
 
+#define WMA_GET_ISOLATION          SIR_HAL_GET_ISOLATION
+
 #define WMA_MODEM_POWER_STATE_IND SIR_HAL_MODEM_POWER_STATE_IND
 
 #ifdef WLAN_FEATURE_STATS_EXT
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index ad0e6d6..79b45f6 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -901,6 +901,46 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS wma_get_isolation(tp_wma_handle wma)
+{
+	wmi_coex_get_antenna_isolation_cmd_fixed_param *cmd;
+	wmi_buf_t wmi_buf;
+	uint32_t  len;
+	uint8_t *buf_ptr;
+
+	WMA_LOGD("%s: get isolation", __func__);
+
+	if (!wma || !wma->wmi_handle) {
+		WMA_LOGE("%s: WMA is closed, can not issue get isolation",
+			 __func__);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	len  = sizeof(wmi_coex_get_antenna_isolation_cmd_fixed_param);
+	wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
+	if (!wmi_buf) {
+		WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
+		return QDF_STATUS_E_NOMEM;
+	}
+	buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf);
+
+	cmd = (wmi_coex_get_antenna_isolation_cmd_fixed_param *)buf_ptr;
+	WMITLV_SET_HDR(
+	&cmd->tlv_header,
+	WMITLV_TAG_STRUC_wmi_coex_get_antenna_isolation_cmd_fixed_param,
+	WMITLV_GET_STRUCT_TLVLEN(
+	wmi_coex_get_antenna_isolation_cmd_fixed_param));
+
+	if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
+				 WMI_COEX_GET_ANTENNA_ISOLATION_CMDID)) {
+		WMA_LOGE("Failed to get isolation request from fw");
+		wmi_buf_free(wmi_buf);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * wma_add_beacon_filter() - Issue WMI command to set beacon filter
  * @wma: wma handler
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 295a994..82a0bbb 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -1819,6 +1819,69 @@
 }
 
 /**
+ * wma_antenna_isolation_event_handler() - antenna isolation event handler
+ * @handle: wma handle
+ * @param: event data
+ * @len: length
+ *
+ * Return: 0 for success or error code
+ */
+static int wma_antenna_isolation_event_handler(void *handle,
+					       u8 *param,
+					       u32 len)
+{
+	struct scheduler_msg cds_msg = {0};
+	wmi_coex_report_isolation_event_fixed_param *event;
+	WMI_COEX_REPORT_ANTENNA_ISOLATION_EVENTID_param_tlvs *param_buf;
+	struct sir_isolation_resp *pisolation;
+	struct mac_context *mac = NULL;
+
+	WMA_LOGD("%s: handle %pK param %pK len %d", __func__,
+		 handle, param, len);
+
+	mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
+	if (!mac) {
+		WMA_LOGE("%s: Invalid mac context", __func__);
+		return -EINVAL;
+	}
+
+	pisolation = qdf_mem_malloc(sizeof(*pisolation));
+	if (!pisolation)
+		return 0;
+
+	param_buf =
+		(WMI_COEX_REPORT_ANTENNA_ISOLATION_EVENTID_param_tlvs *)param;
+	if (!param_buf) {
+		WMA_LOGE("%s: Invalid isolation event", __func__);
+		return -EINVAL;
+	}
+	event = param_buf->fixed_param;
+	pisolation->isolation_chain0 = event->isolation_chain0;
+	pisolation->isolation_chain1 = event->isolation_chain1;
+	pisolation->isolation_chain2 = event->isolation_chain2;
+	pisolation->isolation_chain3 = event->isolation_chain3;
+
+	WMA_LOGD("%s: chain1 %d chain2 %d chain3 %d chain4 %d", __func__,
+		 pisolation->isolation_chain0, pisolation->isolation_chain1,
+		 pisolation->isolation_chain2, pisolation->isolation_chain3);
+
+	cds_msg.type = eWNI_SME_ANTENNA_ISOLATION_RSP;
+	cds_msg.bodyptr = pisolation;
+	cds_msg.bodyval = 0;
+	if (QDF_STATUS_SUCCESS !=
+	    scheduler_post_message(QDF_MODULE_ID_WMA,
+				   QDF_MODULE_ID_SME,
+				   QDF_MODULE_ID_SME, &cds_msg)) {
+		WMA_LOGE("%s: could not post peer info rsp msg to SME",
+			 __func__);
+		/* free the mem and return */
+		qdf_mem_free(pisolation);
+	}
+
+	return 0;
+}
+
+/**
  * wma_init_max_no_of_peers - API to initialize wma configuration params
  * @wma_handle: WMA Handle
  * @max_peers: Max Peers supported
@@ -3632,6 +3695,12 @@
 				wma_rx_aggr_failure_event_handler,
 				WMA_RX_SERIALIZER_CTX);
 
+	wmi_unified_register_event_handler(
+				wma_handle->wmi_handle,
+				wmi_coex_report_antenna_isolation_event_id,
+				wma_antenna_isolation_event_handler,
+				WMA_RX_SERIALIZER_CTX);
+
 	wma_handle->ito_repeat_count = cds_cfg->ito_repeat_count;
 	wma_handle->bandcapability = cds_cfg->bandcapability;
 
@@ -8726,6 +8795,9 @@
 		wma_get_peer_info_ext(wma_handle, msg->bodyptr);
 		qdf_mem_free(msg->bodyptr);
 		break;
+	case WMA_GET_ISOLATION:
+		wma_get_isolation(wma_handle);
+		break;
 	case WMA_MODEM_POWER_STATE_IND:
 		wma_notify_modem_power_state(wma_handle,
 				(tSirModemPowerStateInd *) msg->bodyptr);