qcacld-3.0: Add support for NDP data initiator request

qcacld-2.0 to qcacld-3.0 propagation

Add host side changes to handle INITIATOR_REQ, INITIATOR_RSP,
NEW_PEER_IND and NDP_CONFIRM_IND to support NDP data initiator
request.

Change-Id: I10bf88d3fff27e1f842b720a598c923983c06c90
CRs-Fixed: 962367
diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h
index 969cadf..9ecdf73 100644
--- a/core/hdd/inc/wlan_hdd_assoc.h
+++ b/core/hdd/inc/wlan_hdd_assoc.h
@@ -269,4 +269,12 @@
 }
 #endif
 
+QDF_STATUS hdd_roam_register_sta(struct hdd_adapter_s *adapter,
+					struct tagCsrRoamInfo *roam_info,
+					uint8_t sta_id,
+					struct qdf_mac_addr *peer_mac_addr,
+					struct sSirBssDescription *bss_desc);
+
+bool hdd_save_peer(hdd_station_ctx_t *sta_ctx, uint8_t sta_id,
+		   struct qdf_mac_addr *peer_mac_addr);
 #endif
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index 0d65b55..4db478d 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -1338,7 +1338,7 @@
  *
  * Return: QDF_STATUS enumeration
  */
-static QDF_STATUS hdd_roam_register_sta(hdd_adapter_t *pAdapter,
+QDF_STATUS hdd_roam_register_sta(hdd_adapter_t *pAdapter,
 					tCsrRoamInfo *pRoamInfo,
 					uint8_t staId,
 					struct qdf_mac_addr *pPeerMacAddress,
@@ -2551,37 +2551,31 @@
 }
 
 /**
- * roam_save_ibss_station() - Save the IBSS peer MAC address in the adapter
- * @pHddStaCtx: pointer to global HDD station context
- * @staId: station id
- * @peerMacAddress: pointer to peer MAC address
+ * hdd_save_peer() - Save peer MAC address in adapter peer table.
+ * @sta_ctx: pointer to hdd station context
+ * @sta_id: station ID
+ * @peer_mac_addr: mac address of new peer
  *
  * This information is passed to iwconfig later. The peer that joined
  * last is passed as information to iwconfig.
- *
- * Return:
- *	true if we add MAX_IBSS_PEERS or less STA
- *	false otherwise.
+
+ * Return: true if success, false otherwise
  */
-static bool roam_save_ibss_station(hdd_station_ctx_t *pHddStaCtx, uint8_t staId,
-				  struct qdf_mac_addr *peerMacAddress)
+bool hdd_save_peer(hdd_station_ctx_t *sta_ctx, uint8_t sta_id,
+		   struct qdf_mac_addr *peer_mac_addr)
 {
-	bool fSuccess = false;
-	int idx = 0;
+	int idx;
 
-	for (idx = 0; idx < MAX_IBSS_PEERS; idx++) {
-		if (0 == pHddStaCtx->conn_info.staId[idx]) {
-			pHddStaCtx->conn_info.staId[idx] = staId;
-
-			qdf_copy_macaddr(&pHddStaCtx->conn_info.
-					 peerMacAddress[idx], peerMacAddress);
-
-			fSuccess = true;
-			break;
+	for (idx = 0; idx < SIR_MAX_NUM_STA_IN_IBSS; idx++) {
+		if (0 == sta_ctx->conn_info.staId[idx]) {
+			sta_ctx->conn_info.staId[idx] = sta_id;
+			qdf_copy_macaddr(
+				&sta_ctx->conn_info.peerMacAddress[idx],
+				peer_mac_addr);
+			return true;
 		}
 	}
-
-	return fSuccess;
+	return false;
 }
 
 /**
@@ -2790,7 +2784,7 @@
 			MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId.bytes),
 			pRoamInfo->staId);
 
-		if (!roam_save_ibss_station
+		if (!hdd_save_peer
 			    (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
 			    pRoamInfo->staId,
 			    &pRoamInfo->peerMac)) {
diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c
index 8e4e08c..0278f19 100644
--- a/core/hdd/src/wlan_hdd_nan_datapath.c
+++ b/core/hdd/src/wlan_hdd_nan_datapath.c
@@ -31,6 +31,8 @@
 #include "wlan_hdd_includes.h"
 #include "wlan_hdd_p2p.h"
 #include "wma_api.h"
+#include "wlan_hdd_assoc.h"
+#include "sme_nan_datapath.h"
 
 /* NLA policy */
 static const struct nla_policy
@@ -39,8 +41,8 @@
 	[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID] = { .type = NLA_U16 },
 	[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR] = { .type = NLA_STRING,
 					.len = IFNAMSIZ },
-	[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID] = { .type = NLA_U32 },
-	[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 },
+	[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID] = { .type = NLA_U16 },
+	[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL] = { .type = NLA_U32 },
 	[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR] = {
 						.type = NLA_BINARY,
 						.len = QDF_MAC_ADDR_SIZE },
@@ -51,7 +53,7 @@
 	[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO] = { .type = NLA_BINARY,
 					.len = NDP_APP_INFO_LEN },
 	[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID] = { .type = NLA_U32 },
-	[QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_RESPONSE_CODE] = { .type = NLA_U16 },
+	[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE] = { .type = NLA_U16 },
 	[QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_STATUS_CODE] = { .type = NLA_U16 },
 	[QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR] = { .type = NLA_BINARY,
 					.len = QDF_MAC_ADDR_SIZE },
@@ -149,6 +151,52 @@
 }
 
 /**
+ * hdd_is_ndp_allowed() - Indicates if NDP is allowed
+ * @hdd_ctx: hdd context
+ *
+ * NDP is not allowed with any other role active except STA.
+ *
+ * Return:  true if allowed, false otherwise
+ */
+static bool hdd_is_ndp_allowed(hdd_context_t *hdd_ctx)
+{
+	hdd_adapter_t *adapter;
+	hdd_station_ctx_t *sta_ctx;
+	QDF_STATUS status;
+	hdd_adapter_list_node_t *curr = NULL, *next = NULL;
+
+	status = hdd_get_front_adapter(hdd_ctx, &curr);
+	while (QDF_STATUS_SUCCESS == status) {
+		adapter = curr->pAdapter;
+		if (!adapter)
+			goto next_adapter;
+
+		switch (adapter->device_mode) {
+		case QDF_P2P_GO_MODE:
+		case QDF_SAP_MODE:
+			if (test_bit(SOFTAP_BSS_STARTED,
+					&adapter->event_flags))
+				return false;
+			break;
+		case QDF_P2P_CLIENT_MODE:
+		case QDF_IBSS_MODE:
+			sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+			if (hdd_conn_is_connected(sta_ctx) ||
+					hdd_is_connecting(sta_ctx))
+				return false;
+			break;
+		default:
+			break;
+		}
+next_adapter:
+		status = hdd_get_next_adapter(hdd_ctx, curr, &next);
+		curr = next;
+	}
+
+	return true;
+}
+
+/**
  * hdd_ndi_start_bss() - Start BSS on NAN data interface
  * @adapter: adapter context
  * @operating_channel: channel on which the BSS to be started
@@ -383,7 +431,6 @@
 	return ret;
 }
 
-
 /**
  * hdd_ndp_initiator_req_handler() - NDP initiator request handler
  * @hdd_ctx: hdd context
@@ -394,6 +441,114 @@
 static int hdd_ndp_initiator_req_handler(hdd_context_t *hdd_ctx,
 						struct nlattr **tb)
 {
+	hdd_adapter_t *adapter;
+	char *iface_name;
+	struct ndp_initiator_req req;
+	QDF_STATUS status;
+	uint32_t ndp_qos_cfg;
+	tHalHandle hal = hdd_ctx->hHal;
+	struct nan_datapath_ctx *ndp_ctx;
+
+	ENTER();
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
+		hdd_err(FL("Interface name string is unavailable"));
+		return -EINVAL;
+	}
+
+	iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
+	/* Check for interface in NDI mode */
+	adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE);
+	if (!adapter) {
+		hdd_err(FL("NAN data interface %s not available"),
+			iface_name);
+		return -EINVAL;
+	}
+
+	/* NAN data path coexists only with STA interface */
+	if (false == hdd_is_ndp_allowed(hdd_ctx)) {
+		hdd_err(FL("Unsupported concurrency for NAN datapath"));
+		return -EPERM;
+	}
+
+	ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
+
+	if (ndp_ctx->state == NAN_DATA_NDI_DELETED_STATE ||
+	    ndp_ctx->state == NAN_DATA_NDI_DELETING_STATE ||
+	    ndp_ctx->state == NAN_DATA_NDI_CREATING_STATE) {
+		hdd_err(FL("Data request not allowed in NDI current state: %d"),
+			ndp_ctx->state);
+		return -EINVAL;
+	}
+
+	req.vdev_id = adapter->sessionId;
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
+		hdd_err(FL("Transaction ID is unavailable"));
+		return -EINVAL;
+	}
+	req.transaction_id =
+		nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL]) {
+		hdd_err(FL("NDP channel is unavailable"));
+		return -EINVAL;
+	}
+	req.channel =
+		nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL]);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID]) {
+		hdd_err(FL("NDP service instance ID is unavailable"));
+		return -EINVAL;
+	}
+	req.service_instance_id =
+		nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID]);
+
+	qdf_mem_copy(req.self_ndi_mac_addr.bytes,
+		     adapter->macAddressCurrent.bytes, QDF_MAC_ADDR_SIZE);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]) {
+		hdd_err(FL("NDI peer discovery mac addr is unavailable"));
+		return -EINVAL;
+	}
+	qdf_mem_copy(req.peer_discovery_mac_addr.bytes,
+		nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]),
+		QDF_MAC_ADDR_SIZE);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO_LEN]) {
+		hdd_err(FL("NDP app info len is unavailable"));
+		return -EINVAL;
+	}
+	req.ndp_info.ndp_app_info_len =
+		nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO_LEN]);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]) {
+		hdd_err(FL("NDP app info is unavailable"));
+		return -EINVAL;
+	}
+	req.ndp_info.ndp_app_info =
+		nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS]) {
+		/* at present ndp config stores 4 bytes QOS info only */
+		req.ndp_config.ndp_cfg_len = 4;
+		req.ndp_config.ndp_cfg = (uint8_t *)&ndp_qos_cfg;
+		ndp_qos_cfg =
+			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS]);
+	}
+
+	hddLog(LOG1,
+		FL("vdev_id: %d, transaction_id: %d, channel: %d, service_instance_id: %d, ndp_app_info_len: %d, peer_discovery_mac_addr: %pM"),
+		req.vdev_id, req.transaction_id, req.channel,
+		req.service_instance_id, req.ndp_info.ndp_app_info_len,
+		req.peer_discovery_mac_addr.bytes);
+	status = sme_ndp_initiator_req_handler(hal, &req);
+	if (status != QDF_STATUS_SUCCESS) {
+		hdd_err(FL("sme_ndp_initiator_req_handler failed, status: %d"),
+		       status);
+		return -ECOMM;
+	}
+	EXIT();
 	return 0;
 }
 
@@ -714,12 +869,74 @@
  * @adapter: pointer to adapter context
  * @rsp_params: response parameters
  *
+ * Following vendor event is sent to cfg80211:
+ * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD =
+ *         QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE (4 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID (4 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE (4 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE (4 bytes)
+ *
  * Return: none
  */
 static void hdd_ndp_initiator_rsp_handler(hdd_adapter_t *adapter,
 						void *rsp_params)
 {
+	struct sk_buff *vendor_event;
+	hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	struct ndp_initiator_rsp *rsp = rsp_params;
+	uint32_t data_len = (4 * sizeof(uint32_t)) + (1 * sizeof(uint16_t)) +
+				NLMSG_HDRLEN + (5 * NLA_HDRLEN);
+
+	ENTER();
+
+	if (!rsp) {
+		hdd_err(FL("Invalid NDP Initator response"));
+		return;
+	}
+
+	if (0 != wlan_hdd_validate_context(hdd_ctx))
+		return;
+
+	vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
+				data_len, QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
+				GFP_KERNEL);
+	if (!vendor_event) {
+		hdd_err(FL("cfg80211_vendor_event_alloc failed"));
+		return;
+	}
+
+	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+			QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE))
+		goto ndp_initiator_rsp_nla_failed;
+
+	if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+			rsp->transaction_id))
+		goto ndp_initiator_rsp_nla_failed;
+
+	if (nla_put_u32(vendor_event,
+			QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID,
+			rsp->ndp_instance_id))
+		goto ndp_initiator_rsp_nla_failed;
+
+	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE,
+		rsp->status))
+		goto ndp_initiator_rsp_nla_failed;
+
+	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE,
+		0))
+		goto ndp_initiator_rsp_nla_failed;
+
+	hddLog(LOG1,
+	       FL("NDP Initiator rsp sent, tid:%d, instance id:%d, status:%d"),
+	       rsp->transaction_id, rsp->ndp_instance_id, rsp->status);
+	cfg80211_vendor_event(vendor_event, GFP_KERNEL);
+	EXIT();
 	return;
+ndp_initiator_rsp_nla_failed:
+	hdd_err(FL("nla_put api failed"));
+	kfree_skb(vendor_event);
+	EXIT();
 }
 
 /**
@@ -732,7 +949,41 @@
 static void hdd_ndp_new_peer_ind_handler(hdd_adapter_t *adapter,
 						void *ind_params)
 {
-	return;
+	struct sme_ndp_peer_ind *new_peer_ind = ind_params;
+	hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	tSirBssDescription tmp_bss_descp = {0};
+	tCsrRoamInfo roam_info = {0};
+	struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
+	hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+	ENTER();
+
+	if (NULL == ind_params) {
+		hdd_err(FL("Invalid new NDP peer params"));
+		return;
+	}
+
+	/* save peer in ndp ctx */
+	if (false == hdd_save_peer(sta_ctx, new_peer_ind->sta_id,
+				   &new_peer_ind->peer_mac_addr)) {
+		hdd_err(FL("Ndp peer table full. cannot save new peer"));
+		return;
+	}
+
+	/* this function is called for each new peer */
+	ndp_ctx->active_ndp_peers++;
+	hdd_roam_register_sta(adapter, &roam_info, new_peer_ind->sta_id,
+			    &new_peer_ind->peer_mac_addr, &tmp_bss_descp);
+	hdd_ctx->sta_to_adapter[new_peer_ind->sta_id] = adapter;
+	/* perform following steps for first new peer ind */
+	if (ndp_ctx->active_ndp_peers == 1) {
+		hddLog(LOG1, FL("Set ctx connection state to connected"));
+		sta_ctx->conn_info.connState = eConnectionState_NdiConnected;
+		hdd_wmm_connect(adapter, &roam_info, eCSR_BSS_TYPE_NDI);
+		netif_carrier_on(adapter->dev);
+		netif_tx_start_all_queues(adapter->dev);
+	}
+	EXIT();
 }
 
 /**
@@ -753,12 +1004,109 @@
  * @adapter: pointer to adapter context
  * @ind_params: indication parameters
  *
+ * Following vendor event is sent to cfg80211:
+ * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD =
+ *         QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND (4 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID (4 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR (6 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR (IFNAMSIZ)
+ * QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO (ndp_app_info_len size)
+ * QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE (4 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_RETURN_VALUE (4 bytes)
+ *
  * Return: none
  */
 static void hdd_ndp_confirm_ind_handler(hdd_adapter_t *adapter,
 						void *ind_params)
 {
+	uint32_t ndp_qos_config = 0;
+	struct ndp_confirm_event *ndp_confirm = ind_params;
+	struct sk_buff *vendor_event;
+	hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
+	uint32_t data_len;
+
+	ENTER();
+	if (!ndp_confirm) {
+		hdd_err(FL("Invalid NDP Initator response"));
+		return;
+	}
+
+	if (0 != wlan_hdd_validate_context(hdd_ctx))
+		return;
+
+	/* ndp_confirm is called each time user generated npd req succeeds */
+	ndp_ctx->active_ndp_sessions++;
+
+	data_len = (4 * sizeof(uint32_t)) + QDF_MAC_ADDR_SIZE + IFNAMSIZ +
+			sizeof(uint16_t) + NLMSG_HDRLEN + (8 * NLA_HDRLEN) +
+			ndp_confirm->ndp_info.ndp_app_info_len;
+
+	vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
+				data_len, QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
+				GFP_KERNEL);
+	if (!vendor_event) {
+		hdd_err(FL("cfg80211_vendor_event_alloc failed"));
+		return;
+	}
+
+	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+			QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND))
+		goto ndp_confirm_nla_failed;
+
+	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID,
+			ndp_confirm->ndp_instance_id))
+		goto ndp_confirm_nla_failed;
+
+	if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR,
+		QDF_MAC_ADDR_SIZE, ndp_confirm->peer_ndi_mac_addr.bytes))
+		goto ndp_confirm_nla_failed;
+
+	if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR,
+		    IFNAMSIZ, adapter->dev->name))
+		goto ndp_confirm_nla_failed;
+
+	if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO_LEN,
+		    ndp_confirm->ndp_info.ndp_app_info_len))
+		goto ndp_confirm_nla_failed;
+
+	if (ndp_confirm->ndp_info.ndp_app_info_len && nla_put(vendor_event,
+				QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO,
+				ndp_confirm->ndp_info.ndp_app_info_len,
+				ndp_confirm->ndp_info.ndp_app_info))
+		goto ndp_confirm_nla_failed;
+
+	if (ndp_confirm->ndp_config.ndp_cfg_len) {
+		ndp_qos_config = *((uint32_t *)ndp_confirm->ndp_config.ndp_cfg);
+		/* at present ndp config stores 4 bytes QOS info only */
+		if (nla_put_u32(vendor_event,
+				QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS,
+				ndp_qos_config))
+			goto ndp_confirm_nla_failed;
+	}
+
+	if (nla_put_u32(vendor_event,
+			QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE,
+			ndp_confirm->rsp_code))
+		goto ndp_confirm_nla_failed;
+
+	cfg80211_vendor_event(vendor_event, GFP_KERNEL);
+	hddLog(LOG1,
+		FL("NDP confim sent, ndp instance id: %d, peer addr: %pM, ndp_cfg: %d, rsp_code: %d"),
+		ndp_confirm->ndp_instance_id,
+		ndp_confirm->peer_ndi_mac_addr.bytes,
+		ndp_qos_config, ndp_confirm->rsp_code);
+
+	hddLog(LOG1, FL("NDP confim, ndp app info dump"));
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
+			   ndp_confirm->ndp_info.ndp_app_info,
+			   ndp_confirm->ndp_info.ndp_app_info_len);
+	EXIT();
 	return;
+ndp_confirm_nla_failed:
+	hdd_err(FL("nla_put api failed"));
+	kfree_skb(vendor_event);
+	EXIT();
 }
 
 /**
diff --git a/core/hdd/src/wlan_hdd_nan_datapath.h b/core/hdd/src/wlan_hdd_nan_datapath.h
index 1480f66..93c6b7f 100644
--- a/core/hdd/src/wlan_hdd_nan_datapath.h
+++ b/core/hdd/src/wlan_hdd_nan_datapath.h
@@ -57,7 +57,7 @@
  * @QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID: Transaction id reference
  * @QCA_WLAN_VENDOR_ATTR_NDP_STATUS_ID: NDP status id
  * @QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID: Service instance id
- * @QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_SPEC_CHANNEL: Requested channel
+ * @QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL: Requested channel
  * @QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR: Peer discovery mac addr
  * @QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR: Iface name
  * @QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY: Security configuration
@@ -67,7 +67,7 @@
  * @QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID: NDP instance id
  * @QCA_WLAN_VENDOR_ATTR_NDP_NUM_INSTANCE_ID: Number of NDP instance ids
  * @QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY: NDP instance id array
- * @QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_RESPONSE_CODE: Schedule response
+ * @QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE: Schedule response
  * @QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_STATUS_CODE: schedule status
  * @QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR: NDI mac address
  * @QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE: Driver return status
@@ -78,7 +78,7 @@
 	QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
 	QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
 	QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID,
-	QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_SPEC_CHANNEL,
+	QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL,
 	QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR,
 	QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR,
 	QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY,
@@ -88,7 +88,7 @@
 	QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID,
 	QCA_WLAN_VENDOR_ATTR_NDP_NUM_INSTANCE_ID,
 	QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY,
-	QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_RESPONSE_CODE,
+	QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE,
 	QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_STATUS_CODE,
 	QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR,
 	QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE,
@@ -180,6 +180,7 @@
  * struct nan_datapath_ctx - context for nan data path
  * @state: Current state of NDP
  * @active_ndp_sessions: active ndp sessions per adapter
+ * @active_ndp_peers: number of active ndp peers
  * @ndp_create_transaction_id: transaction id for create req
  * @ndp_delete_transaction_id: transaction id for delete req
  * @ndp_key_installed: NDP security key installed
@@ -189,6 +190,7 @@
 struct nan_datapath_ctx {
 	enum nan_datapath_state state;
 	uint32_t active_ndp_sessions;
+	uint32_t active_ndp_peers;
 	uint16_t ndp_create_transaction_id;
 	uint16_t ndp_delete_transaction_id;
 	bool ndp_key_installed;
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 6cb946b..15e2c25 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -5927,7 +5927,7 @@
 struct ndp_cfg {
 	uint32_t tag;
 	uint32_t ndp_cfg_len;
-	uint8_t ndp_cfg[];
+	uint8_t *ndp_cfg;
 };
 
 /**
@@ -5953,7 +5953,7 @@
 struct ndp_app_info {
 	uint32_t tag;
 	uint32_t ndp_app_info_len;
-	uint8_t ndp_app_info[];
+	uint8_t *ndp_app_info;
 };
 
 /**
@@ -6028,7 +6028,7 @@
 };
 
 /**
- * struct ndp_initiator_rsp_event - response event from FW
+ * struct ndp_initiator_rsp - response event from FW
  * @transaction_id: unique identifier
  * @vdev_id: session id of the interface over which ndp is being created
  * @ndp_instance_id: locally created NDP instance ID
@@ -6036,12 +6036,11 @@
  * @reason: reason for failure if any
  *
  */
-struct ndp_initiator_rsp_event {
+struct ndp_initiator_rsp {
 	uint32_t transaction_id;
 	uint32_t vdev_id;
 	uint32_t ndp_instance_id;
 	uint32_t status;
-	uint32_t reason;
 };
 
 /**
@@ -6049,6 +6048,7 @@
  * @vdev_id: session id of the interface over which ndp is being created
  * @service_instance_id: Service identifier
  * @peer_discovery_mac_addr: Peer's discovery mac address
+ * @peer_mac_addr: Peer's NDI mac address
  * @ndp_initiator_mac_addr: NDI mac address of the peer initiating NDP
  * @ndp_instance_id: locally created NDP instance ID
  * @role: self role for NDP
@@ -6061,7 +6061,7 @@
 	uint32_t vdev_id;
 	uint32_t service_instance_id;
 	struct qdf_mac_addr peer_discovery_mac_addr;
-	struct qdf_mac_addr ndp_initiator_mac_addr;
+	struct qdf_mac_addr peer_mac_addr;
 	uint32_t ndp_instance_id;
 	enum ndp_self_role role;
 	enum ndp_accept_policy policy;
diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h
index 3d32c88..74d48f5 100644
--- a/core/mac/inc/wni_api.h
+++ b/core/mac/inc/wni_api.h
@@ -252,6 +252,7 @@
 	eWNI_SME_TSF_EVENT,
 	eWNI_SME_MON_INIT_SESSION,
 	eWNI_SME_PDEV_SET_HT_VHT_IE,
+	eWNI_SME_NDP_INITIATOR_REQ,
 	eWNI_SME_NDP_INITIATOR_RSP,
 	eWNI_SME_NDP_NEW_PEER_IND,
 	eWNI_SME_NDP_CONFIRM_IND,
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 5bc816b..746e065 100644
--- a/core/mac/src/include/sir_params.h
+++ b/core/mac/src/include/sir_params.h
@@ -606,7 +606,7 @@
 #define SIR_HAL_ADD_BCN_FILTER_CMDID        (SIR_HAL_ITC_MSG_TYPES_BEGIN + 339)
 #define SIR_HAL_REMOVE_BCN_FILTER_CMDID     (SIR_HAL_ITC_MSG_TYPES_BEGIN + 340)
 
-#define SIR_HAL_BPF_GET_CAPABILITIES_REQ     (SIR_HAL_ITC_MSG_TYPES_BEGIN + 341)
+#define SIR_HAL_BPF_GET_CAPABILITIES_REQ    (SIR_HAL_ITC_MSG_TYPES_BEGIN + 341)
 #define SIR_HAL_BPF_SET_INSTRUCTIONS_REQ    (SIR_HAL_ITC_MSG_TYPES_BEGIN + 342)
 
 #define SIR_HAL_SET_WISA_PARAMS             (SIR_HAL_ITC_MSG_TYPES_BEGIN + 343)
@@ -617,17 +617,17 @@
 #define SIR_HAL_TDLS_CONNECTION_TRACKER_NOTIFICATION (SIR_HAL_ITC_MSG_TYPES_BEGIN + 346)
 #endif
 
-#define SIR_HAL_NDP_GET_CAP_REQ             (SIR_HAL_ITC_MSG_TYPES_BEGIN + 344)
-#define SIR_HAL_NDP_INITIATOR_REQ           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 345)
-#define SIR_HAL_NDP_RESPONDER_REQ           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 346)
-#define SIR_HAL_NDP_END_REQ                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 347)
-#define SIR_HAL_NDI_CAP_RSP                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 348)
-#define SIR_HAL_NDP_INITIATOR_RSP           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 349)
-#define SIR_HAL_NDP_RESPONDER_RSP           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 350)
-#define SIR_HAL_NDP_END_RSP                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 351)
-#define SIR_HAL_NDP_INDICATION              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 352)
-#define SIR_HAL_NDP_CONFIRM                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 353)
-#define SIR_HAL_NDP_END_IND                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 354)
+#define SIR_HAL_NDP_GET_CAP_REQ             (SIR_HAL_ITC_MSG_TYPES_BEGIN + 347)
+#define SIR_HAL_NDP_INITIATOR_REQ           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 348)
+#define SIR_HAL_NDP_RESPONDER_REQ           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 349)
+#define SIR_HAL_NDP_END_REQ                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 350)
+#define SIR_HAL_NDI_CAP_RSP                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 351)
+#define SIR_HAL_NDP_INITIATOR_RSP           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 352)
+#define SIR_HAL_NDP_RESPONDER_RSP           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 353)
+#define SIR_HAL_NDP_END_RSP                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 354)
+#define SIR_HAL_NDP_INDICATION              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 355)
+#define SIR_HAL_NDP_CONFIRM                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 356)
+#define SIR_HAL_NDP_END_IND                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 357)
 
 #define SIR_HAL_MSG_TYPES_END                (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
index d8031c2..d1df825 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -63,6 +63,7 @@
 #include "cds_packet.h"
 #include "qdf_mem.h"
 #include "cds_concurrency.h"
+#include "nan_datapath.h"
 
 void lim_log_session_states(tpAniSirGlobal pMac);
 static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx,
@@ -1451,7 +1452,8 @@
 #endif  /* FEATURE_WLAN_ESE */
 	case eWNI_SME_REGISTER_MGMT_FRAME_CB:
 	case eWNI_SME_EXT_CHANGE_CHANNEL:
-	/* These messages are from HDD.No need to respond to HDD */
+	case eWNI_SME_NDP_INITIATOR_REQ:
+		/* These messages are from HDD.No need to respond to HDD */
 		lim_process_normal_hdd_msg(mac_ctx, msg, false);
 		break;
 
diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
index 1f7364e..9f53b3c 100644
--- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c
+++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
@@ -57,6 +57,7 @@
 #include "wmm_apsd.h"
 #include "sir_mac_prot_def.h"
 #include "rrm_api.h"
+#include "nan_datapath.h"
 
 #include "sap_api.h"
 
@@ -170,7 +171,7 @@
 	status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
 	if (!QDF_IS_STATUS_SUCCESS(status)) {
 		lim_log(mac, LOGE,
-			FL("vos_mq_post_message failed!(err=%d)"),
+			FL("cds_mq_post_message failed!(err=%d)"),
 			status);
 		qdf_mem_free(req_msg);
 		goto fail;
@@ -245,7 +246,7 @@
 	status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
 	if (!QDF_IS_STATUS_SUCCESS(status)) {
 		lim_log(mac, LOGE,
-				FL("vos_mq_post_message failed!(err=%d)"),
+				FL("cds_mq_post_message failed!(err=%d)"),
 				status);
 		qdf_mem_free(req_msg);
 		goto fail;
@@ -311,7 +312,7 @@
 	status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
 	if (!QDF_IS_STATUS_SUCCESS(status)) {
 		lim_log(mac, LOGE,
-				FL("vos_mq_post_message failed!(err=%d)"),
+				FL("cds_mq_post_message failed!(err=%d)"),
 				status);
 		qdf_mem_free(req_msg);
 		goto fail;
@@ -5169,6 +5170,8 @@
 		break;
 	case eWNI_SME_PDEV_SET_HT_VHT_IE:
 		lim_process_set_pdev_IEs(pMac, pMsgBuf);
+	case eWNI_SME_NDP_INITIATOR_REQ:
+		lim_handle_ndp_request_message(pMac, pMsg);
 		break;
 	default:
 		qdf_mem_free((void *)pMsg->bodyptr);
diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c
index 2efea04..49009b8 100644
--- a/core/mac/src/pe/lim/lim_utils.c
+++ b/core/mac/src/pe/lim/lim_utils.c
@@ -56,6 +56,7 @@
 #include "lim_ft_defs.h"
 #include "lim_session.h"
 #include "cds_reg_service.h"
+#include "nan_datapath.h"
 
 #ifdef WLAN_FEATURE_11W
 #include "wni_cfg.h"
@@ -5591,32 +5592,41 @@
 	return 0;
 }
 
-void lim_process_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ)
+/**
+ * lim_process_add_sta_rsp() - process WDA_ADD_STA_RSP from WMA
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: msg from WMA
+ *
+ * @Return: void
+ */
+void lim_process_add_sta_rsp(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
 {
-	tpPESession psessionEntry;
-	tpAddStaParams pAddStaParams;
+	tpPESession session;
+	tpAddStaParams add_sta_params;
 
-	pAddStaParams = (tpAddStaParams) limMsgQ->bodyptr;
+	add_sta_params = (tpAddStaParams) msg->bodyptr;
 
-	psessionEntry = pe_find_session_by_session_id(pMac,
-			pAddStaParams->sessionId);
-	if (psessionEntry == NULL) {
-		lim_log(pMac, LOGP,
+	session = pe_find_session_by_session_id(mac_ctx,
+			add_sta_params->sessionId);
+	if (session == NULL) {
+		lim_log(mac_ctx, LOGP,
 			FL("Session Does not exist for given sessionID"));
-		qdf_mem_free(pAddStaParams);
+		qdf_mem_free(add_sta_params);
 		return;
 	}
-	psessionEntry->csaOffloadEnable = pAddStaParams->csaOffloadEnable;
-	if (LIM_IS_IBSS_ROLE(psessionEntry))
-		(void)lim_ibss_add_sta_rsp(pMac, limMsgQ->bodyptr, psessionEntry);
+	session->csaOffloadEnable = add_sta_params->csaOffloadEnable;
+	if (LIM_IS_IBSS_ROLE(session))
+		(void)lim_ibss_add_sta_rsp(mac_ctx, msg->bodyptr, session);
+	else if (LIM_IS_NDI_ROLE(session))
+		lim_ndp_add_sta_rsp(mac_ctx, session, msg->bodyptr);
 #ifdef FEATURE_WLAN_TDLS
-	else if (pMac->lim.gLimAddStaTdls) {
-		lim_process_tdls_add_sta_rsp(pMac, limMsgQ->bodyptr, psessionEntry);
-		pMac->lim.gLimAddStaTdls = false;
+	else if (mac_ctx->lim.gLimAddStaTdls) {
+		lim_process_tdls_add_sta_rsp(mac_ctx, msg->bodyptr, session);
+		mac_ctx->lim.gLimAddStaTdls = false;
 	}
 #endif
 	else
-		lim_process_mlm_add_sta_rsp(pMac, limMsgQ, psessionEntry);
+		lim_process_mlm_add_sta_rsp(mac_ctx, msg, session);
 
 }
 
diff --git a/core/mac/src/pe/nan/nan_datapath.c b/core/mac/src/pe/nan/nan_datapath.c
index 3c7ec25..584adba 100644
--- a/core/mac/src/pe/nan/nan_datapath.c
+++ b/core/mac/src/pe/nan/nan_datapath.c
@@ -26,20 +26,117 @@
 
 #include "lim_utils.h"
 #include "lim_api.h"
+#include "lim_assoc_utils.h"
 #include "nan_datapath.h"
 #include "lim_types.h"
 #include "lim_send_messages.h"
+#include "wma_nan_datapath.h"
 
 /**
- * handle_ndp_request_message() - Function to handle NDP requests from SME
+ * lim_send_ndp_event_to_sme() - generic function to pepare and send NDP message
+ * to SME directly.
  * @mac_ctx: handle to mac structure
- * @msg: pointer to message
+ * @msg_type: sme message type to send
+ * @body_ptr: buffer
+ * @len: buffer length
+ * @body_val: value
+ *
+ * Return: Nothing
+ */
+static void lim_send_ndp_event_to_sme(tpAniSirGlobal mac_ctx, uint32_t msg_type,
+				void *body_ptr, uint32_t len, uint32_t body_val)
+{
+	tSirMsgQ mmh_msg = {0};
+
+	mmh_msg.type = msg_type;
+	if (len && body_ptr) {
+		mmh_msg.bodyptr = qdf_mem_malloc(len);
+		if (NULL == mmh_msg.bodyptr) {
+			lim_log(mac_ctx, LOGE, FL("Malloc failed"));
+			return;
+		}
+		qdf_mem_copy(mmh_msg.bodyptr, body_ptr, len);
+	} else {
+		mmh_msg.bodyval = body_val;
+	}
+	lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT);
+}
+
+/**
+ * lim_handle_ndp_indication_event() - Function to handle SIR_HAL_NDP_INDICATION
+ * event from WMA
+ * @mac_ctx: handle to mac structure
+ * @ndp_ind: ndp indication event params
  *
  * Return: QDF_STATUS_SUCCESS on success; error number otherwise
  */
-QDF_STATUS handle_ndp_request_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
+static QDF_STATUS lim_handle_ndp_indication_event(tpAniSirGlobal mac_ctx,
+					struct ndp_indication_event *ndp_ind)
 {
+	tpPESession session;
+	tpDphHashNode sta_ds;
+	uint16_t assoc_id, peer_idx;
+	tSirRetStatus status;
+
+	lim_log(mac_ctx, LOG1,
+		FL("role: %d, vdev: %d, peer_mac_addr "MAC_ADDRESS_STR),
+		ndp_ind->role, ndp_ind->vdev_id,
+		MAC_ADDR_ARRAY(ndp_ind->peer_mac_addr.bytes));
+
+	if (ndp_ind->role == NDP_ROLE_INITIATOR) {
+
+		session = pe_find_session_by_sme_session_id(mac_ctx,
+							    ndp_ind->vdev_id);
+		if (session == NULL) {
+			lim_log(mac_ctx, LOGE,
+				FL("Couldn't find session, vdev_id: %d, ndp_role: %d"),
+				ndp_ind->vdev_id, ndp_ind->role);
+			goto ndp_indication_failed;
+		}
+		sta_ds = dph_lookup_hash_entry(mac_ctx,
+					ndp_ind->peer_mac_addr.bytes,
+					&assoc_id, &session->dph.dphHashTable);
+		/* peer exists, don't do anything */
+		if (sta_ds != NULL) {
+			lim_log(mac_ctx, LOGE, FL("NDI Peer already exists!!"));
+			return QDF_STATUS_SUCCESS;
+		}
+
+		/* else create one */
+		lim_log(mac_ctx, LOG1, FL("Need to create NDI Peer!!"));
+		peer_idx = lim_assign_peer_idx(mac_ctx, session);
+		sta_ds = dph_add_hash_entry(mac_ctx,
+					ndp_ind->peer_mac_addr.bytes,
+					peer_idx, &session->dph.dphHashTable);
+		if (sta_ds == NULL) {
+			lim_log(mac_ctx, LOGE,
+				FL("Couldn't add dph entry, ndp_role: %d"),
+				ndp_ind->role);
+			goto ndp_indication_failed;
+		}
+		/* wma decides NDI mode from wma->inferface struct */
+		sta_ds->staType = STA_ENTRY_NDI_PEER;
+		status = lim_add_sta(mac_ctx, sta_ds, false, session);
+		if (eSIR_SUCCESS != status) {
+			lim_log(mac_ctx, LOGE,
+			       FL("limAddSta failed status: %d, ndp_role: %d"),
+				status, ndp_ind->role);
+			goto ndp_indication_failed;
+		}
+	} else {
+		/* Processing for NDP Data Reponder role */
+	}
+	/*
+	 * With NDP indication if peer does not exists already add_sta is
+	 * executed resulting in new peer else no action is taken. Note that
+	 * new_peer event is not necessary event and should not be sent if case
+	 * anything fails in this function. Rather eWNI_SME_NDP_CONFIRM_IND is
+	 * used to indicate success of final operation and abscence of it can be
+	 * used by service layer to identify failure.
+	 */
 	return QDF_STATUS_SUCCESS;
+ndp_indication_failed:
+	return QDF_STATUS_E_FAILURE;
 }
 
 /**
@@ -49,9 +146,115 @@
  *
  * Return: QDF_STATUS_SUCCESS on success; error number otherwise
  */
-QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
+QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, cds_msg_t *msg)
 {
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	switch (msg->type) {
+	case SIR_HAL_NDP_CONFIRM:
+		lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_CONFIRM_IND,
+				msg->bodyptr, sizeof(struct ndp_confirm_event),
+				msg->bodyval);
+		break;
+	case SIR_HAL_NDP_INITIATOR_RSP:
+		lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_INITIATOR_RSP,
+				msg->bodyptr, sizeof(struct ndp_initiator_rsp),
+				msg->bodyval);
+		break;
+	case SIR_HAL_NDP_INDICATION: {
+		struct ndp_indication_event *ndp_ind = msg->bodyptr;
+		status = lim_handle_ndp_indication_event(mac_ctx, ndp_ind);
+		qdf_mem_free(ndp_ind->ndp_config.ndp_cfg);
+		qdf_mem_free(ndp_ind->ndp_info.ndp_app_info);
+		break;
+	}
+	default:
+		lim_log(mac_ctx, LOGE,
+			FL("Unhandled NDP event: %d"), msg->type);
+		status = QDF_STATUS_E_NOSUPPORT;
+		break;
+	}
+	/*
+	 * No need to free body pointer, since the function is serving purpose
+	 * of callback and bodyptr if allocated is freed by caller itself
+	 */
+	return status;
+}
+
+/**
+ * lim_process_sme_ndp_initiator_req() - Handler for eWNI_SME_NDP_INITIATOR_REQ
+ * from SME.
+ * @mac_ctx: handle to mac structure
+ * @ndp_msg: ndp initiator request msg
+ *
+ * Return: Status of operation
+ */
+QDF_STATUS lim_process_sme_ndp_initiator_req(tpAniSirGlobal mac_ctx,
+					     void *ndp_msg)
+{
+	tSirMsgQ msg;
+	QDF_STATUS status;
+
+	struct sir_sme_ndp_initiator_req *sme_req =
+		(struct sir_sme_ndp_initiator_req *)ndp_msg;
+	struct ndp_initiator_req *wma_req;
+
+	if (NULL == ndp_msg) {
+		lim_log(mac_ctx, LOGE, FL("invalid ndp_req"));
+		status = QDF_STATUS_E_INVAL;
+		goto send_initiator_rsp;
+	}
+	wma_req = qdf_mem_malloc(sizeof(*wma_req));
+	if (wma_req == NULL) {
+		lim_log(mac_ctx, LOGE, FL("malloc failed"));
+		status = QDF_STATUS_E_NOMEM;
+		goto send_initiator_rsp;
+	}
+
+	qdf_mem_copy(wma_req, &sme_req->req, sizeof(*wma_req));
+	msg.type = SIR_HAL_NDP_INITIATOR_REQ;
+	msg.reserved = 0;
+	msg.bodyptr = wma_req;
+	msg.bodyval = 0;
+
+	lim_log(mac_ctx, LOG1, FL("sending WDA_NDP_INITIATOR_REQ to WMA"));
+	MTRACE(mac_trace_msg_tx(mac_ctx, NO_SESSION, msg.type));
+
+	if (eSIR_SUCCESS != wma_post_ctrl_msg(mac_ctx, &msg))
+		lim_log(mac_ctx, LOGP, FL("wma_post_ctrl_msg failed"));
+
 	return QDF_STATUS_SUCCESS;
+send_initiator_rsp:
+	/* msg to unblock SME, but not send rsp to HDD */
+	lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_INITIATOR_RSP,
+				  NULL, 0, true);
+	return status;
+}
+
+/**
+* lim_handle_ndp_request_message() - Handler for NDP req from SME
+* @mac_ctx: handle to mac structure
+* @msg: pointer to message
+*
+* Return: QDF_STATUS_SUCCESS on success; error number otherwise
+*/
+QDF_STATUS lim_handle_ndp_request_message(tpAniSirGlobal mac_ctx,
+					  tpSirMsgQ msg)
+{
+	QDF_STATUS status;
+
+	switch (msg->type) {
+	case eWNI_SME_NDP_INITIATOR_REQ:
+		status = lim_process_sme_ndp_initiator_req(mac_ctx,
+							   msg->bodyptr);
+		break;
+	default:
+		lim_log(mac_ctx, LOGE, FL("Unhandled NDP request: %d"),
+		       msg->type);
+		status = QDF_STATUS_E_NOSUPPORT;
+		break;
+	}
+	return status;
 }
 
 /**
@@ -160,3 +363,98 @@
 		session_entry = NULL;
 	}
 }
+
+
+/**
+ * lim_send_sme_ndp_add_sta_rsp() - prepares and send new peer ind to SME
+ * @mac_ctx: handle to mac structure
+ * @session: session pointer
+ * @add_sta_rsp: add sta response struct
+ *
+ * Return: status of operation
+ */
+static QDF_STATUS lim_send_sme_ndp_add_sta_rsp(tpAniSirGlobal mac_ctx,
+					       tpPESession session,
+					       tAddStaParams *add_sta_rsp)
+{
+	tSirMsgQ  mmh_msg = {0};
+	struct sme_ndp_peer_ind *new_peer_ind;
+
+	mmh_msg.type = eWNI_SME_NDP_NEW_PEER_IND;
+
+	if (NULL == add_sta_rsp) {
+		lim_log(mac_ctx, LOGE, FL("Invalid add_sta_rsp"));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	new_peer_ind = qdf_mem_malloc(sizeof(*new_peer_ind));
+	if (NULL == new_peer_ind) {
+		lim_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	/* this message is going to HDD, fill in sme session id */
+	new_peer_ind->session_id = add_sta_rsp->smesessionId;
+	new_peer_ind->msg_len = sizeof(struct sme_ndp_peer_ind);
+	new_peer_ind->msg_type = eWNI_SME_NDP_NEW_PEER_IND;
+	qdf_mem_copy(new_peer_ind->peer_mac_addr.bytes, add_sta_rsp->staMac,
+		     sizeof(tSirMacAddr));
+	new_peer_ind->sta_id = add_sta_rsp->staIdx;
+
+	mmh_msg.bodyptr = new_peer_ind;
+	mmh_msg.bodyval = 0;
+	lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT);
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * lim_ndp_add_sta_rsp() - handles add sta rsp for NDP from WMA
+ * @mac_ctx: handle to mac structure
+ * @session: session pointer
+ * @add_sta_rsp: add sta response struct
+ *
+ * Return: None
+ */
+void lim_ndp_add_sta_rsp(tpAniSirGlobal mac_ctx, tpPESession session,
+			 tAddStaParams *add_sta_rsp)
+{
+	tpDphHashNode sta_ds;
+	uint16_t peer_idx;
+
+	if (NULL == add_sta_rsp) {
+		lim_log(mac_ctx, LOGE, FL("Invalid add_sta_rsp"));
+		qdf_mem_free(add_sta_rsp);
+		return;
+	}
+
+	SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true);
+	sta_ds = dph_lookup_hash_entry(mac_ctx, add_sta_rsp->staMac, &peer_idx,
+				    &session->dph.dphHashTable);
+	if (sta_ds == NULL) {
+		lim_log(mac_ctx, LOGE,
+			FL("NAN: ADD_STA_RSP for unknown MAC addr "
+			MAC_ADDRESS_STR),
+			MAC_ADDR_ARRAY(add_sta_rsp->staMac));
+		qdf_mem_free(add_sta_rsp);
+		return;
+	}
+
+	if (add_sta_rsp->status != QDF_STATUS_SUCCESS) {
+		lim_log(mac_ctx, LOGE,
+			FL("NAN: ADD_STA_RSP error %x for MAC addr: %pM"),
+			add_sta_rsp->status, add_sta_rsp->staMac);
+		/* delete the sta_ds allocated during ADD STA */
+		lim_delete_dph_hash_entry(mac_ctx, add_sta_rsp->staMac,
+				      peer_idx, session);
+		qdf_mem_free(add_sta_rsp);
+		return;
+	}
+	sta_ds->bssId = add_sta_rsp->bssIdx;
+	sta_ds->staIndex = add_sta_rsp->staIdx;
+	sta_ds->ucUcastSig = add_sta_rsp->ucUcastSig;
+	sta_ds->ucBcastSig = add_sta_rsp->ucBcastSig;
+	sta_ds->valid = 1;
+	sta_ds->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
+	lim_send_sme_ndp_add_sta_rsp(mac_ctx, session, add_sta_rsp);
+	qdf_mem_free(add_sta_rsp);
+}
diff --git a/core/mac/src/pe/nan/nan_datapath.h b/core/mac/src/pe/nan/nan_datapath.h
index 62115f1..556de8d 100644
--- a/core/mac/src/pe/nan/nan_datapath.h
+++ b/core/mac/src/pe/nan/nan_datapath.h
@@ -104,23 +104,29 @@
 QDF_STATUS lim_handle_ndp_request_message(tpAniSirGlobal mac_ctx,
 					tpSirMsgQ msg);
 /* Function to process NDP events */
-QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg);
+QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, cds_msg_t *msg);
 void lim_process_ndi_mlm_add_bss_rsp(tpAniSirGlobal mac_ctx,
 				     tpSirMsgQ lim_msg_q,
 				     tpPESession session_entry);
 /* Handler for DEL BSS resp for NDI interface */
 void lim_ndi_del_bss_rsp(tpAniSirGlobal  mac_ctx,
 			void *msg, tpPESession session_entry);
+
+void lim_ndp_add_sta_rsp(tpAniSirGlobal mac_ctx, tpPESession session_entry,
+			 tAddStaParams *add_sta_rsp);
+
 #else
+
 /* Function to process NDP requests */
 static inline QDF_STATUS lim_handle_ndp_request_message(tpAniSirGlobal mac_ctx,
 					tpSirMsgQ msg)
 {
 	return QDF_STATUS_SUCCESS;
 }
+
 /* Function to process NDP events */
 static inline QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx,
-						      tpSirMsgQ msg)
+						      cds_msg_t *msg)
 {
 	return QDF_STATUS_SUCCESS;
 }
@@ -136,6 +142,12 @@
 {
 }
 
+static inline void lim_ndp_add_sta_rsp(tpAniSirGlobal mac_ctx,
+					tpPESession session_entry,
+					tAddStaParams *add_sta_rsp)
+{
+}
+
 #endif /* WLAN_FEATURE_NAN_DATAPATH */
 
 #endif /* __MAC_NAN_DATAPATH_H */
diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h
index 5bd8301..084d85e 100644
--- a/core/sme/inc/csr_api.h
+++ b/core/sme/inc/csr_api.h
@@ -1388,7 +1388,7 @@
 		struct ndp_confirm_event ndp_confirm_params;
 		struct ndp_responder_rsp_event ndp_responder_rsp_params;
 		struct ndp_indication_event ndp_indication_params;
-		struct ndp_initiator_rsp_event ndp_init_rsp_params;
+		struct ndp_initiator_rsp ndp_init_rsp_params;
 		struct ndi_create_rsp ndi_create_params;
 		struct ndi_delete_rsp ndi_delete_params;
 	} ndp;
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 804dc1e..2990912 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -914,7 +914,7 @@
     \param  hHal - The handle returned by macOpen.
     \param  sessionId - Session Identifier
     \param  pRequest -  Pointer to the offload request.
-    \return eHalStatus
+    \return QDF_STATUS
   ---------------------------------------------------------------------------*/
 QDF_STATUS sme_ipa_offload_enable_disable(tHalHandle hal,
 				uint8_t session_id,
diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h
index 5a6600a..68a26a6 100644
--- a/core/sme/inc/sme_inside.h
+++ b/core/sme/inc/sme_inside.h
@@ -192,6 +192,9 @@
 		struct s_nss_update_cmd nss_update_cmd;
 		struct sir_dual_mac_config set_dual_mac_cmd;
 		struct sir_antenna_mode_param set_antenna_mode_cmd;
+#ifdef WLAN_FEATURE_NAN_DATAPATH
+		struct ndp_initiator_req initiator_req;
+#endif
 	} u;
 } tSmeCmd;
 
diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h
index d6d0e50..cdd1922 100644
--- a/core/sme/inc/sme_internal.h
+++ b/core/sme/inc/sme_internal.h
@@ -93,6 +93,7 @@
 	e_sme_command_nss_update,
 	e_sme_command_set_dual_mac_config,
 	e_sme_command_set_antenna_mode,
+	eSmeCommandNdpInitiatorRequest,
 } eSmeCommandType;
 
 typedef enum eSmeState {
diff --git a/core/sme/inc/sme_nan_datapath.h b/core/sme/inc/sme_nan_datapath.h
index a57f1fb..74102e6 100644
--- a/core/sme/inc/sme_nan_datapath.h
+++ b/core/sme/inc/sme_nan_datapath.h
@@ -31,9 +31,23 @@
 #include "qdf_types.h"
 #include "sir_api.h"
 #include "ani_global.h"
+#include "sme_inside.h"
+
+/**
+ * struct sir_sme_ndp_initiator_req - sme request struct for ndp initiator req
+ * @mesgType: SME msg type(eWNI_SME_NDP_INITIATOR_REQ)
+ * @mesgLen: lenght of message
+ * @req: actual ndp initiator request
+ *
+ */
+struct sir_sme_ndp_initiator_req {
+	uint16_t msg_type;
+	uint16_t msg_len;
+	struct ndp_initiator_req req;
+};
 
 /* NAN initiator request handler */
-QDF_STATUS sme_ndp_initiator_req_handler(uint32_t session_id,
+QDF_STATUS sme_ndp_initiator_req_handler(tHalHandle hal,
 					struct ndp_initiator_req *req_params);
 
 /* NAN responder request handler */
@@ -73,6 +87,11 @@
 					uint32_t *roam_status,
 					uint32_t *roam_result,
 					struct tagCsrRoamInfo *roam_info);
+QDF_STATUS csr_process_ndp_initiator_request(tpAniSirGlobal mac_ctx,
+					     tSmeCmd *cmd);
+
+void sme_ndp_msg_processor(tpAniSirGlobal mac_ctx, cds_msg_t *msg);
+
 #else
 
 /* Start NDI BSS */
@@ -107,5 +126,24 @@
 					struct tagCsrRoamInfo *roam_info)
 {
 }
+
+/* NaN indication response handler */
+QDF_STATUS sme_ndp_end_req_handler(uint32_t session_id,
+					struct ndp_end_req *req_params);
+
+/* NaN schedule update request handler */
+QDF_STATUS sme_ndp_sched_req_handler(uint32_t session_id,
+				struct ndp_schedule_update_req *req_params);
+
+static inline eHalStatus csr_process_ndp_initiator_request(
+				tpAniSirGlobal mac_ctx, tSmeCmd *cmd)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline void sme_ndp_msg_processor(tpAniSirGlobal mac_ctx, cds_msg_t *msg)
+{
+}
+
 #endif /* WLAN_FEATURE_NAN_DATAPATH */
 #endif /* __SME_NAN_DATAPATH_H */
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 6c7766e..1601666 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -59,6 +59,7 @@
 #include "sme_power_save_api.h"
 #include "wma.h"
 #include "sch_api.h"
+#include "sme_nan_datapath.h"
 
 extern tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, tSirMbMsg *pMb);
 
@@ -956,6 +957,15 @@
 		csr_ll_unlock(&pMac->sme.smeCmdActiveList);
 		csr_process_add_sta_session_command(pMac, pCommand);
 		break;
+	case eSmeCommandNdpInitiatorRequest:
+		csr_ll_unlock(&pMac->sme.smeCmdActiveList);
+		if (csr_process_ndp_initiator_request(pMac, pCommand) !=
+			QDF_STATUS_SUCCESS)
+			if (csr_ll_remove_entry(
+				&pMac->sme.smeCmdActiveList,
+				&pCommand->Link, LL_ACCESS_LOCK))
+				csr_release_command(pMac, pCommand);
+	    break;
 	case eSmeCommandDelStaSession:
 		csr_ll_unlock(&pMac->sme.smeCmdActiveList);
 		csr_process_del_sta_session_command(pMac, pCommand);
@@ -2985,6 +2995,11 @@
 					pMsg->type);
 		}
 		break;
+	case eWNI_SME_NDP_CONFIRM_IND:
+	case eWNI_SME_NDP_NEW_PEER_IND:
+	case eWNI_SME_NDP_INITIATOR_RSP:
+		sme_ndp_msg_processor(pMac, pMsg);
+		break;
 	default:
 
 		if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN)
@@ -13178,13 +13193,13 @@
 
 /**
  * sme_set_epno_list() - set epno network list
- * @hHal: global hal handle
+ * @hal: global hal handle
  * @input: request message
  *
  * This function constructs the cds message and fill in message type,
  * bodyptr with %input and posts it to WDA queue.
  *
- * Return: eHalStatus enumeration
+ * Return: QDF_STATUS enumeration
  */
 QDF_STATUS sme_set_epno_list(tHalHandle hal,
 				struct wifi_epno_params *input)
@@ -13253,7 +13268,7 @@
  * This function constructs the cds message and fill in message type,
  * bodyptr with @input and posts it to WDA queue.
  *
- * Return: eHalStatus enumeration
+ * Return: QDF_STATUS enumeration
  */
 QDF_STATUS sme_set_passpoint_list(tHalHandle hal,
 				struct wifi_passpoint_req *input)
@@ -13320,7 +13335,7 @@
  * @hHal: global hal handle
  * @input: request message
  *
- * Return: eHalStatus enumeration
+ * Return: QDF_STATUS enumeration
  */
 QDF_STATUS sme_reset_passpoint_list(tHalHandle hal,
 				    struct wifi_passpoint_req *input)
@@ -13370,7 +13385,7 @@
  * @hal: SME handle
  * @request: set ssid hotlist request
  *
- * Return: eHalStatus
+ * Return: QDF_STATUS
  */
 QDF_STATUS
 sme_set_ssid_hotlist(tHalHandle hal,
@@ -14262,7 +14277,7 @@
  * This function is used to send the command that will
  * be used to flush the logs in the firmware
  *
- * Return: eHalStatus
+ * Return: QDF_STATUS
  */
 QDF_STATUS sme_send_flush_logs_cmd_to_fw(tpAniSirGlobal mac)
 {
@@ -14691,8 +14706,8 @@
 	status = sme_acquire_global_lock(&mac->sme);
 	if (status != QDF_STATUS_SUCCESS) {
 		sms_log(mac, LOGE,
-				FL("sme_AcquireGlobalLock failed!(status=%d)"),
-				status);
+			FL("sme_acquire_global_lock failed!(status=%d)"),
+			status);
 		qdf_mem_free(req_msg);
 		return status;
 	}
@@ -14703,7 +14718,7 @@
 	status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
 	if (!QDF_IS_STATUS_SUCCESS(status)) {
 		sms_log(mac, LOGE,
-				FL("vos_mq_post_message failed!(err=%d)"),
+				FL("cds_mq_post_message failed!(err=%d)"),
 				status);
 		qdf_mem_free(req_msg);
 		status = QDF_STATUS_E_FAILURE;
diff --git a/core/sme/src/nan/nan_datapath_api.c b/core/sme/src/nan/nan_datapath_api.c
index 3efd69b..a36a644 100644
--- a/core/sme/src/nan/nan_datapath_api.c
+++ b/core/sme/src/nan/nan_datapath_api.c
@@ -32,17 +32,83 @@
 
 /**
  * sme_ndp_initiator_req_handler() - ndp initiator req handler
- * @session_id: session id over which the ndp is being created
+ * @hal: hal handle
  * @req_params: request parameters
  *
  * Return: QDF_STATUS_SUCCESS on success; error number otherwise
  */
-QDF_STATUS sme_ndp_initiator_req_handler(uint32_t session_id,
-	struct ndp_initiator_req *req_params)
+QDF_STATUS sme_ndp_initiator_req_handler(tHalHandle hal,
+			struct ndp_initiator_req *req_params)
 {
-	return QDF_STATUS_SUCCESS;
-}
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	tSmeCmd *cmd;
+	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
 
+	if (NULL == req_params) {
+		sms_log(mac_ctx, LOGE, FL("Invalid req_params"));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = sme_acquire_global_lock(&mac_ctx->sme);
+	if (QDF_STATUS_SUCCESS != status) {
+		sms_log(mac_ctx, LOGE,
+		       FL("SME lock failed, status:%d"), status);
+		return status;
+	}
+	cmd = csr_get_command_buffer(mac_ctx);
+	if (NULL == cmd) {
+		sme_release_global_lock(&mac_ctx->sme);
+		return QDF_STATUS_E_RESOURCES;
+	}
+
+	cmd->command = eSmeCommandNdpInitiatorRequest;
+	cmd->sessionId = (uint8_t)req_params->vdev_id;
+	qdf_mem_copy(&cmd->u.initiator_req, req_params,
+		     sizeof(struct ndp_initiator_req));
+	/* pointers copied as part of above operation are to be overwritten */
+	cmd->u.initiator_req.ndp_info.ndp_app_info = NULL;
+	cmd->u.initiator_req.ndp_config.ndp_cfg = NULL;
+
+	if (req_params->ndp_info.ndp_app_info_len) {
+		cmd->u.initiator_req.ndp_info.ndp_app_info =
+			qdf_mem_malloc(req_params->ndp_info.ndp_app_info_len);
+		if (NULL == cmd->u.initiator_req.ndp_info.ndp_app_info) {
+			sme_release_global_lock(&mac_ctx->sme);
+			return QDF_STATUS_E_NOMEM;
+		}
+		qdf_mem_copy(cmd->u.initiator_req.ndp_info.ndp_app_info,
+			req_params->ndp_info.ndp_app_info,
+			req_params->ndp_info.ndp_app_info_len);
+	}
+
+	if (req_params->ndp_config.ndp_cfg_len) {
+		cmd->u.initiator_req.ndp_config.ndp_cfg =
+			qdf_mem_malloc(req_params->ndp_config.ndp_cfg_len);
+		if (NULL == cmd->u.initiator_req.ndp_config.ndp_cfg) {
+			sme_release_global_lock(&mac_ctx->sme);
+			qdf_mem_free(
+				cmd->u.initiator_req.ndp_info.ndp_app_info);
+			cmd->u.initiator_req.ndp_info.ndp_app_info_len = 0;
+			return QDF_STATUS_E_NOMEM;
+		}
+		qdf_mem_copy(cmd->u.initiator_req.ndp_config.ndp_cfg,
+			req_params->ndp_config.ndp_cfg,
+			req_params->ndp_config.ndp_cfg_len);
+	}
+
+	status = csr_queue_sme_command(mac_ctx, cmd, true);
+	if (QDF_STATUS_SUCCESS != status) {
+		sms_log(mac_ctx, LOGE, FL("SME enqueue failed, status:%d"),
+			status);
+		qdf_mem_free(cmd->u.initiator_req.ndp_info.ndp_app_info);
+		qdf_mem_free(cmd->u.initiator_req.ndp_config.ndp_cfg);
+		cmd->u.initiator_req.ndp_info.ndp_app_info_len = 0;
+		cmd->u.initiator_req.ndp_config.ndp_cfg_len = 0;
+	}
+
+	sme_release_global_lock(&mac_ctx->sme);
+	return status;
+}
 /**
  * sme_ndp_responder_req_handler() - ndp responder request handler
  * @session_id: session id over which the ndp is being created
@@ -245,3 +311,143 @@
 		break;
 	}
 }
+
+
+/**
+ * csr_process_ndp_initiator_request() - process ndp initiator request
+ * @mac_ctx: Global MAC context
+ * @cmd: ndp initiator sme cmd
+ *
+ * Return: status of operation
+ */
+QDF_STATUS csr_process_ndp_initiator_request(tpAniSirGlobal mac_ctx,
+					     tSmeCmd *cmd)
+{
+	struct sir_sme_ndp_initiator_req *lim_msg;
+	uint16_t msg_len;
+	uint8_t *self_mac_addr = NULL;
+	struct ndp_initiator_req *req;
+
+	if (NULL == cmd) {
+		sms_log(mac_ctx, LOGE, FL("Invalid req_params"));
+		return QDF_STATUS_E_INVAL;
+	}
+	req = &cmd->u.initiator_req;
+
+	msg_len = sizeof(*lim_msg);
+	lim_msg = qdf_mem_malloc(msg_len);
+	if (NULL == lim_msg)
+		return QDF_STATUS_E_NOMEM;
+
+	qdf_mem_set(lim_msg, msg_len, 0);
+	lim_msg->msg_type = eWNI_SME_NDP_INITIATOR_REQ;
+	lim_msg->msg_len = msg_len;
+	/*
+	 * following is being copied from p_cmd->u.initiator_req,
+	 * no need to perform deep copy, as we are going to use memory
+	 * allocated at SME in p_cmd->u.initiator_req and pass it all the way
+	 * to WMA.
+	 */
+	qdf_mem_copy(&lim_msg->req, req, sizeof(struct ndp_initiator_req));
+
+	self_mac_addr = lim_msg->req.self_ndi_mac_addr.bytes;
+	sms_log(mac_ctx, LOG1, FL("selfMac = "MAC_ADDRESS_STR),
+		MAC_ADDR_ARRAY(self_mac_addr));
+
+	return cds_send_mb_message_to_mac(lim_msg);
+}
+
+/**
+ * sme_ndp_msg_processor() - message processor for ndp/ndi north-bound SME msg.
+ * @mac_ctx: Global MAC context
+ * @msg: ndp/ndi SME message
+ *
+ * This function will further call csrRoamCallCallback with appropriate
+ * roam_status and roam_result thus allowing hdd to correctly identify NDP/NDI
+ * response.
+ *
+ * Return: nothing
+ */
+void sme_ndp_msg_processor(tpAniSirGlobal mac_ctx, cds_msg_t *msg)
+{
+	tCsrRoamInfo roam_info = {0};
+	eCsrRoamResult result;
+	uint32_t session_id;
+	tListElem *entry = NULL;
+	tSmeCmd *cmd = NULL;
+	bool release_active_cmd = false;
+	eSmeCommandType cmd_to_rel = eSmeNoCommand;
+	bool send_to_user = true;
+
+	switch (msg->type) {
+	case eWNI_SME_NDP_CONFIRM_IND: {
+		result = eCSR_ROAM_RESULT_NDP_CONFIRM_IND;
+		/* copy msg from msg body to roam info passed to callback */
+		qdf_mem_copy(&roam_info.ndp.ndp_confirm_params, msg->bodyptr,
+			sizeof(roam_info.ndp.ndp_confirm_params));
+		session_id = roam_info.ndp.ndp_confirm_params.vdev_id;
+		break;
+	}
+	case eWNI_SME_NDP_INITIATOR_RSP: {
+		if (true == msg->bodyval) {
+			/* rsp was locally generated, do not send to HDD */
+			send_to_user = false;
+		} else {
+			result = eCSR_ROAM_RESULT_NDP_INITIATOR_RSP;
+			qdf_mem_copy(&roam_info.ndp.ndp_init_rsp_params,
+				     msg->bodyptr,
+				     sizeof(roam_info.ndp.ndp_init_rsp_params));
+			session_id = roam_info.ndp.ndp_init_rsp_params.vdev_id;
+		}
+		release_active_cmd = true;
+		cmd_to_rel = eSmeCommandNdpInitiatorRequest;
+		entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList,
+				      LL_ACCESS_LOCK);
+		if (entry != NULL) {
+			cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
+			if (cmd_to_rel == cmd->command) {
+				qdf_mem_free(
+				    cmd->u.initiator_req.ndp_config.ndp_cfg);
+				qdf_mem_free(
+				    cmd->u.initiator_req.ndp_info.ndp_app_info);
+			}
+		}
+		break;
+	}
+	case eWNI_SME_NDP_NEW_PEER_IND: {
+		result = eCSR_ROAM_RESULT_NDP_NEW_PEER_IND;
+		/* copy msg from msg body to roam info passed to callback */
+		qdf_mem_copy(&roam_info.ndp.ndp_peer_ind_params,
+			     msg->bodyptr,
+			     sizeof(roam_info.ndp.ndp_peer_ind_params));
+		session_id = roam_info.ndp.ndp_peer_ind_params.session_id;
+		break;
+	}
+	default:
+		sms_log(mac_ctx, LOGE, FL("Unhandled NDP rsp"));
+		qdf_mem_free(msg->bodyptr);
+		return;
+	}
+
+	if (true == send_to_user) {
+		csr_roam_call_callback(mac_ctx, session_id, &roam_info, 0,
+				    eCSR_ROAM_NDP_STATUS_UPDATE, result);
+	}
+	qdf_mem_free(msg->bodyptr);
+	if (release_active_cmd == false)
+		return;
+
+	entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList,
+			LL_ACCESS_LOCK);
+	if (entry == NULL)
+		return;
+
+	cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
+	if (cmd_to_rel == cmd->command) {
+		/* Now put this cmd back on the avilable command list */
+		if (csr_ll_remove_entry(&mac_ctx->sme.smeCmdActiveList,
+				     entry, LL_ACCESS_LOCK))
+			sme_release_command(mac_ctx, cmd);
+		sme_process_pending_queue(mac_ctx);
+	}
+}
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index e374df2..957af80 100644
--- a/core/wma/inc/wma.h
+++ b/core/wma/inc/wma.h
@@ -1434,7 +1434,7 @@
 	/* NAN datapath support enabled in firmware */
 	bool nan_datapath_enabled;
 	QDF_STATUS (*pe_ndp_event_handler)(tpAniSirGlobal mac_ctx,
-					   tpSirMsgQ msg);
+					   cds_msg_t *msg);
 } t_wma_handle, *tp_wma_handle;
 
 /**
@@ -2133,6 +2133,10 @@
 					uint32_t vdev_id,
 					uint32_t bitmap,
 					bool enable);
+QDF_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev,
+			   ol_txrx_vdev_handle vdev, u8 peer_addr[6],
+			   u_int32_t peer_type, u_int8_t vdev_id,
+			   bool roam_synch_in_progress);
 
 #endif
 struct wma_ini_config *wma_get_ini_handle(tp_wma_handle wma_handle);
diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h
index 9e3e6ab..c690f55 100644
--- a/core/wma/inc/wma_api.h
+++ b/core/wma/inc/wma_api.h
@@ -254,11 +254,11 @@
 #ifdef WLAN_FEATURE_NAN_DATAPATH
 QDF_STATUS wma_register_ndp_cb(QDF_STATUS (*pe_ndp_event_handler)
 					  (tpAniSirGlobal mac_ctx,
-					  tpSirMsgQ msg));
+					  cds_msg_t *msg));
 #else
 static inline QDF_STATUS wma_register_ndp_cb(QDF_STATUS (*pe_ndp_event_handler)
 							(tpAniSirGlobal mac_ctx,
-							tpSirMsgQ msg))
+							cds_msg_t *msg))
 {
 	return QDF_STATUS_SUCCESS;
 }
diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h
index 39aab20..58b0dac 100644
--- a/core/wma/inc/wma_if.h
+++ b/core/wma/inc/wma_if.h
@@ -84,6 +84,7 @@
 #ifdef FEATURE_WLAN_TDLS
 #define STA_ENTRY_TDLS_PEER         4
 #endif /* FEATURE_WLAN_TDLS */
+#define STA_ENTRY_NDI_PEER          5
 
 #define STA_INVALID_IDX 0xFF
 
diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c
index 8b46b64..e785e2b 100644
--- a/core/wma/src/wma_dev_if.c
+++ b/core/wma/src/wma_dev_if.c
@@ -4067,6 +4067,8 @@
 	else if (wma_is_vdev_in_ibss_mode(wma, add_sta->smesessionId))
 		oper_mode = BSS_OPERATIONAL_MODE_IBSS;
 
+	if (WMA_IS_VDEV_IN_NDI_MODE(wma->interfaces, add_sta->smesessionId))
+		oper_mode = BSS_OPERATIONAL_MODE_NDI;
 	switch (oper_mode) {
 	case BSS_OPERATIONAL_MODE_STA:
 		wma_add_sta_req_sta_mode(wma, add_sta);
@@ -4078,6 +4080,9 @@
 		htc_vote_link_down(wma->htc_handle);
 		wma_add_sta_req_ap_mode(wma, add_sta);
 		break;
+	case BSS_OPERATIONAL_MODE_NDI:
+		wma_add_sta_ndi_mode(wma, add_sta);
+		break;
 	}
 
 #ifdef QCA_IBSS_SUPPORT
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index f38b2e3..85463a1 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -5946,6 +5946,10 @@
 		wma_set_bpf_instructions(wma_handle, msg->bodyptr);
 		qdf_mem_free(msg->bodyptr);
 		break;
+	case SIR_HAL_NDP_INITIATOR_REQ:
+		wma_handle_ndp_initiator_req(wma_handle, msg->bodyptr);
+		qdf_mem_free(msg->bodyptr);
+		break;
 
 	default:
 		WMA_LOGD("unknow msg type %x", msg->type);
diff --git a/core/wma/src/wma_nan_datapath.c b/core/wma/src/wma_nan_datapath.c
index e77f93c..83deb25 100644
--- a/core/wma/src/wma_nan_datapath.c
+++ b/core/wma/src/wma_nan_datapath.c
@@ -30,18 +30,138 @@
 #include "wmi_unified.h"
 #include "wma_nan_datapath.h"
 #include "wma_internal.h"
+#include "cds_utils.h"
 
 /**
  * wma_handle_ndp_initiator_req() - NDP initiator request handler
  * @wma_handle: wma handle
- * @req_params: request parameters
+ * @req: request parameters
  *
  * Return: QDF_STATUS_SUCCESS on success; error number otherwise
  */
-QDF_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle,
-					struct ndp_initiator_req *req_params)
+QDF_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle, void *req)
 {
+	QDF_STATUS status;
+	int ret;
+	uint16_t len;
+	uint32_t vdev_id, ndp_cfg_len, ndp_app_info_len;
+	struct ndp_initiator_rsp ndp_rsp = {0};
+	uint8_t *cfg_info, *app_info;
+	ol_txrx_vdev_handle vdev;
+	wmi_buf_t buf;
+	wmi_ndp_initiator_req_fixed_param *cmd;
+	cds_msg_t pe_msg = {0};
+	struct ndp_initiator_req *ndp_req = req;
+	wmi_channel *ch_tlv;
+
+	if (NULL == ndp_req) {
+		WMA_LOGE(FL("Invalid ndp_req."));
+		goto send_ndi_initiator_fail;
+	}
+	vdev_id = ndp_req->vdev_id;
+	vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
+	if (!vdev) {
+		WMA_LOGE(FL("vdev not found for vdev id %d."), vdev_id);
+		goto send_ndi_initiator_fail;
+	}
+
+	if (!WMA_IS_VDEV_IN_NDI_MODE(wma_handle->interfaces, vdev_id)) {
+		WMA_LOGE(FL("vdev :%d, not in NDI mode"), vdev_id);
+		goto send_ndi_initiator_fail;
+	}
+
+	/*
+	 * WMI command expects 4 byte alligned len:
+	 * round up ndp_cfg_len and ndp_app_info_len to 4 bytes
+	 */
+	ndp_cfg_len = roundup(ndp_req->ndp_config.ndp_cfg_len, 4);
+	ndp_app_info_len = roundup(ndp_req->ndp_info.ndp_app_info_len, 4);
+	/* allocated memory for fixed params as well as variable size data */
+	len = sizeof(*cmd) + ndp_cfg_len + ndp_app_info_len +
+		(2 * WMI_TLV_HDR_SIZE) + sizeof(*ch_tlv);
+	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
+	if (!buf) {
+		WMA_LOGE(FL("wmi_buf_alloc failed"));
+		goto send_ndi_initiator_fail;
+	}
+	cmd = (wmi_ndp_initiator_req_fixed_param *) wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_ndp_initiator_req_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN(
+				wmi_ndp_initiator_req_fixed_param));
+	cmd->vdev_id = ndp_req->vdev_id;
+	cmd->transaction_id = ndp_req->transaction_id;
+	cmd->service_instance_id = ndp_req->service_instance_id;
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(ndp_req->peer_discovery_mac_addr.bytes,
+				   &cmd->peer_discovery_mac_addr);
+
+	cmd->ndp_cfg_len = ndp_req->ndp_config.ndp_cfg_len;
+	cmd->ndp_app_info_len = ndp_req->ndp_info.ndp_app_info_len;
+
+	ch_tlv = (wmi_channel *)&cmd[1];
+	WMITLV_SET_HDR(ch_tlv, WMITLV_TAG_STRUC_wmi_channel,
+			WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
+	ch_tlv->mhz = ndp_req->channel;
+	ch_tlv->band_center_freq1 =
+		cds_chan_to_freq(cds_freq_to_chan(ndp_req->channel));
+
+	cfg_info = (uint8_t *)&ch_tlv[1];
+	WMITLV_SET_HDR(cfg_info, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len);
+	qdf_mem_copy(&cfg_info[WMI_TLV_HDR_SIZE], ndp_req->ndp_config.ndp_cfg,
+		     cmd->ndp_cfg_len);
+
+	app_info = &cfg_info[WMI_TLV_HDR_SIZE + ndp_cfg_len];
+	WMITLV_SET_HDR(app_info, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len);
+	qdf_mem_copy(&app_info[WMI_TLV_HDR_SIZE],
+		     ndp_req->ndp_info.ndp_app_info,
+		     cmd->ndp_app_info_len);
+
+	WMA_LOGE(FL("vdev_id = %d, transaction_id: %d, service_instance_id, %d channel: %d"),
+		cmd->vdev_id, cmd->transaction_id, cmd->service_instance_id,
+		ch_tlv->mhz);
+	WMA_LOGE(FL("peer mac addr: mac_addr31to0: 0x%x, mac_addr47to32: 0x%x"),
+		cmd->peer_discovery_mac_addr.mac_addr31to0,
+		cmd->peer_discovery_mac_addr.mac_addr47to32);
+
+	WMA_LOGE(FL("ndp_config len: %d"), cmd->ndp_cfg_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+			   ndp_req->ndp_config.ndp_cfg,
+			   ndp_req->ndp_config.ndp_cfg_len);
+
+	WMA_LOGE(FL("ndp_app_info len: %d"), cmd->ndp_app_info_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+			   ndp_req->ndp_info.ndp_app_info,
+			   ndp_req->ndp_info.ndp_app_info_len);
+
+	WMA_LOGE(FL("sending WMI_NDP_INITIATOR_REQ_CMDID(0x%X)"),
+		WMI_NDP_INITIATOR_REQ_CMDID);
+	ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
+				   WMI_NDP_INITIATOR_REQ_CMDID);
+	if (ret < 0) {
+		WMA_LOGE(FL("WMI_NDP_INITIATOR_REQ_CMDID failed, ret: %d"),
+			ret);
+		wmi_buf_free(buf);
+		goto send_ndi_initiator_fail;
+	}
+
 	return QDF_STATUS_SUCCESS;
+
+send_ndi_initiator_fail:
+	status = QDF_STATUS_E_FAILURE;
+	if (ndp_req) {
+		ndp_rsp.vdev_id = ndp_req->vdev_id;
+		ndp_rsp.transaction_id = ndp_req->transaction_id;
+		ndp_rsp.ndp_instance_id = ndp_req->service_instance_id;
+		ndp_rsp.status = NDP_CMD_RSP_STATUS_ERROR;
+	} else {
+		/* unblock SME queue, but do not send rsp to HDD */
+		pe_msg.bodyval = true;
+	}
+
+	pe_msg.type = SIR_HAL_NDP_INITIATOR_RSP;
+	pe_msg.bodyptr = &ndp_rsp;
+	return wma_handle->pe_ndp_event_handler(wma_handle->mac_context,
+						&pe_msg);
 }
 
 /**
@@ -92,12 +212,78 @@
  * Handler for WMI_NDP_INDICATION_EVENTID
  * Return: 0 on success, negative errno on failure
  */
-static int wma_ndp_indication_event_handler(void *handle,
-					uint8_t *event_info, uint32_t len)
+static int wma_ndp_indication_event_handler(void *handle, uint8_t *event_info,
+					    uint32_t len)
 {
-	return 0;
+	WMI_NDP_INDICATION_EVENTID_param_tlvs *event;
+	wmi_ndp_indication_event_fixed_param *fixed_params;
+	cds_msg_t pe_msg = {0};
+	struct ndp_indication_event ind_event = {0};
+	tp_wma_handle wma_handle = handle;
+
+	event = (WMI_NDP_INDICATION_EVENTID_param_tlvs *)event_info;
+	fixed_params =
+		(wmi_ndp_indication_event_fixed_param *)event->fixed_param;
+
+	WMA_LOGD(FL("WMI_NDP_INDICATION_EVENTID(0x%X) received. vdev %d, service_instance %d, ndp_instance %d, role %d, policy %d"),
+		 WMI_NDP_INDICATION_EVENTID, fixed_params->vdev_id,
+		 fixed_params->service_instance_id,
+		 fixed_params->ndp_instance_id, fixed_params->self_ndp_role,
+		 fixed_params->accept_policy);
+
+	WMA_LOGD(FL("ndp_cfg - %d bytes"), fixed_params->ndp_cfg_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+			   &event->ndp_cfg, fixed_params->ndp_cfg_len);
+
+	WMA_LOGD(FL("ndp_app_info - %d bytes"), fixed_params->ndp_app_info_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+			&event->ndp_app_info, fixed_params->ndp_app_info_len);
+
+	ind_event.vdev_id = fixed_params->vdev_id;
+	ind_event.service_instance_id = fixed_params->service_instance_id;
+	ind_event.ndp_instance_id = fixed_params->ndp_instance_id;
+	ind_event.role = fixed_params->self_ndp_role;
+	ind_event.policy = fixed_params->accept_policy;
+
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
+				ind_event.peer_mac_addr.bytes);
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_discovery_mac_addr,
+				ind_event.peer_discovery_mac_addr.bytes);
+
+	ind_event.ndp_config.ndp_cfg_len = fixed_params->ndp_cfg_len;
+	ind_event.ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len;
+
+	if (ind_event.ndp_config.ndp_cfg_len) {
+		ind_event.ndp_config.ndp_cfg =
+			qdf_mem_malloc(fixed_params->ndp_cfg_len);
+		if (NULL == ind_event.ndp_config.ndp_cfg) {
+			WMA_LOGE(FL("malloc failed"));
+			return QDF_STATUS_E_NOMEM;
+		}
+		qdf_mem_copy(ind_event.ndp_config.ndp_cfg, event->ndp_cfg,
+			     ind_event.ndp_config.ndp_cfg_len);
+	}
+
+	if (ind_event.ndp_info.ndp_app_info_len) {
+		ind_event.ndp_info.ndp_app_info =
+			qdf_mem_malloc(ind_event.ndp_info.ndp_app_info_len);
+		if (NULL == ind_event.ndp_info.ndp_app_info) {
+			WMA_LOGE(FL("malloc failed"));
+			qdf_mem_free(ind_event.ndp_config.ndp_cfg);
+			return QDF_STATUS_E_NOMEM;
+		}
+		qdf_mem_copy(ind_event.ndp_info.ndp_app_info,
+			     event->ndp_app_info,
+			     ind_event.ndp_info.ndp_app_info_len);
+	}
+	pe_msg.type = SIR_HAL_NDP_INDICATION;
+	pe_msg.bodyptr = &ind_event;
+	pe_msg.bodyval = 0;
+	return wma_handle->pe_ndp_event_handler(wma_handle->mac_context,
+						&pe_msg);
 }
 
+
 /**
  * wma_ndp_responder_rsp_event_handler() - NDP responder response event handler
  * @handle: wma handle
@@ -122,10 +308,70 @@
  * Handler for WMI_NDP_CONFIRM_EVENTID
  * Return: 0 on success, negative errno on failure
  */
-static int wma_ndp_confirm_event_handler(void *handle,
-					uint8_t *event_info, uint32_t len)
+static int wma_ndp_confirm_event_handler(void *handle, uint8_t *event_info,
+					 uint32_t len)
 {
-	return 0;
+	struct ndp_confirm_event ndp_confirm = {0};
+	cds_msg_t msg = {0};
+	WMI_NDP_CONFIRM_EVENTID_param_tlvs *event;
+	wmi_ndp_confirm_event_fixed_param *fixed_params;
+	tp_wma_handle wma_handle = handle;
+
+	event = (WMI_NDP_CONFIRM_EVENTID_param_tlvs *) event_info;
+	fixed_params = (wmi_ndp_confirm_event_fixed_param *)event->fixed_param;
+	WMA_LOGE(FL("WMI_NDP_CONFIRM_EVENTID(0x%X) recieved. vdev %d, ndp_instance %d, rsp_code %d"),
+		 WMI_NDP_CONFIRM_EVENTID, fixed_params->vdev_id,
+		 fixed_params->ndp_instance_id, fixed_params->rsp_code);
+
+	WMA_LOGE(FL("ndp_cfg - %d bytes"), fixed_params->ndp_cfg_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+		&event->ndp_cfg, fixed_params->ndp_cfg_len);
+
+	WMA_LOGE(FL("ndp_app_info - %d bytes"), fixed_params->ndp_app_info_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+		&event->ndp_app_info, fixed_params->ndp_app_info_len);
+
+	ndp_confirm.vdev_id = fixed_params->vdev_id;
+	ndp_confirm.ndp_instance_id = fixed_params->ndp_instance_id;
+	ndp_confirm.rsp_code = fixed_params->rsp_code;
+
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
+				   ndp_confirm.peer_ndi_mac_addr.bytes);
+
+	qdf_mem_copy(&ndp_confirm.ndp_config, event->ndp_cfg,
+		     fixed_params->ndp_cfg_len);
+
+	ndp_confirm.ndp_config.ndp_cfg_len = fixed_params->ndp_cfg_len;
+	ndp_confirm.ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len;
+
+	if (ndp_confirm.ndp_config.ndp_cfg_len) {
+		ndp_confirm.ndp_config.ndp_cfg =
+			qdf_mem_malloc(ndp_confirm.ndp_config.ndp_cfg_len);
+		if (NULL == ndp_confirm.ndp_config.ndp_cfg) {
+			WMA_LOGE(FL("malloc failed"));
+			return QDF_STATUS_E_NOMEM;
+		}
+		qdf_mem_copy(ndp_confirm.ndp_config.ndp_cfg,
+			     event->ndp_cfg,
+			     ndp_confirm.ndp_config.ndp_cfg_len);
+	}
+
+	if (ndp_confirm.ndp_info.ndp_app_info_len) {
+		ndp_confirm.ndp_info.ndp_app_info =
+				qdf_mem_malloc(fixed_params->ndp_app_info_len);
+		if (NULL == ndp_confirm.ndp_info.ndp_app_info) {
+			WMA_LOGE(FL("malloc failed"));
+			qdf_mem_free(ndp_confirm.ndp_config.ndp_cfg);
+			return QDF_STATUS_E_NOMEM;
+		}
+		qdf_mem_copy(&ndp_confirm.ndp_info.ndp_app_info,
+			     event->ndp_app_info,
+			     ndp_confirm.ndp_info.ndp_app_info_len);
+	}
+	msg.type = SIR_HAL_NDP_CONFIRM;
+	msg.bodyptr = &ndp_confirm;
+	msg.bodyval = 0;
+	return wma_handle->pe_ndp_event_handler(wma_handle->mac_context, &msg);
 }
 
 /**
@@ -170,7 +416,24 @@
 static int wma_ndp_initiator_rsp_event_handler(void *handle,
 					uint8_t *event_info, uint32_t len)
 {
-	return 0;
+	cds_msg_t pe_msg = {0};
+	WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *event;
+	wmi_ndp_initiator_rsp_event_fixed_param  *fixed_params;
+	struct ndp_initiator_rsp ndp_rsp = {0};
+	tp_wma_handle wma_handle = handle;
+
+	event = (WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *)event_info;
+	fixed_params = event->fixed_param;
+
+	ndp_rsp.vdev_id = fixed_params->vdev_id;
+	ndp_rsp.transaction_id = fixed_params->transaction_id;
+	ndp_rsp.ndp_instance_id = fixed_params->ndp_instance_id;
+	ndp_rsp.status = fixed_params->rsp_status;
+
+	pe_msg.type = SIR_HAL_NDP_INITIATOR_RSP;
+	pe_msg.bodyptr = &ndp_rsp;
+	return wma_handle->pe_ndp_event_handler(wma_handle->mac_context,
+						&pe_msg);
 }
 
 /**
@@ -551,7 +814,7 @@
  * Return: Success or Failure Status
  */
 QDF_STATUS wma_register_ndp_cb(QDF_STATUS (*pe_ndp_event_handler)
-				(tpAniSirGlobal mac_ctx, tpSirMsgQ msg))
+				(tpAniSirGlobal mac_ctx, cds_msg_t *msg))
 {
 
 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
@@ -565,3 +828,95 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * wma_add_sta_ndi_mode() - Process ADD_STA for NaN Data path
+ * @wma: wma handle
+ * @add_sta: Parameters of ADD_STA command
+ *
+ * Sends CREATE_PEER command to firmware
+ * Return: void
+ */
+void wma_add_sta_ndi_mode(tp_wma_handle wma, tpAddStaParams add_sta)
+{
+	enum ol_txrx_peer_state state = OL_TXRX_PEER_STATE_CONN;
+	ol_txrx_pdev_handle pdev;
+	ol_txrx_vdev_handle vdev;
+	ol_txrx_peer_handle peer;
+	u_int8_t peer_id;
+	QDF_STATUS status;
+	struct wma_txrx_node *iface;
+
+	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+
+	if (NULL == pdev) {
+		WMA_LOGE(FL("Failed to find pdev"));
+		add_sta->status = QDF_STATUS_E_FAILURE;
+		goto send_rsp;
+	}
+
+	vdev = wma_find_vdev_by_id(wma, add_sta->smesessionId);
+	if (!vdev) {
+		WMA_LOGE(FL("Failed to find vdev"));
+		add_sta->status = QDF_STATUS_E_FAILURE;
+		goto send_rsp;
+	}
+
+	iface = &wma->interfaces[vdev->vdev_id];
+	WMA_LOGD(FL("vdev: %d, peer_mac_addr: "MAC_ADDRESS_STR),
+		add_sta->smesessionId, MAC_ADDR_ARRAY(add_sta->staMac));
+
+	peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, add_sta->staMac,
+						  &peer_id);
+	if (peer) {
+		WMA_LOGE(FL("NDI peer already exists, peer_addr %pM"),
+			 add_sta->staMac);
+		add_sta->status = QDF_STATUS_E_EXISTS;
+		goto send_rsp;
+	}
+
+	/*
+	 * The code above only checks the peer existence on its own vdev.
+	 * Need to check whether the peer exists on other vDevs because firmware
+	 * can't create the peer if the peer with same MAC address already
+	 * exists on the pDev. As this peer belongs to other vDevs, just return
+	 * here.
+	 */
+	peer = ol_txrx_find_peer_by_addr(pdev, add_sta->staMac, &peer_id);
+	if (peer) {
+		WMA_LOGE(FL("vdev:%d, peer exists on other vdev with peer_addr %pM and peer_id %d"),
+			 vdev->vdev_id, add_sta->staMac, peer_id);
+		add_sta->status = QDF_STATUS_E_EXISTS;
+		goto send_rsp;
+	}
+
+	status = wma_create_peer(wma, pdev, vdev, add_sta->staMac,
+				 WMI_PEER_TYPE_NAN_DATA, add_sta->smesessionId,
+				 false);
+	if (status != QDF_STATUS_SUCCESS) {
+		WMA_LOGE(FL("Failed to create peer for %pM"), add_sta->staMac);
+		add_sta->status = status;
+		goto send_rsp;
+	}
+
+	peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, add_sta->staMac,
+						  &peer_id);
+	if (!peer) {
+		WMA_LOGE(FL("Failed to find peer handle using peer mac %pM"),
+			 add_sta->staMac);
+		add_sta->status = QDF_STATUS_E_FAILURE;
+		wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId,
+				peer, false);
+		goto send_rsp;
+	}
+
+	WMA_LOGD(FL("Moving peer %pM to state %d"), add_sta->staMac, state);
+	ol_txrx_peer_state_update(pdev, add_sta->staMac, state);
+
+	add_sta->staIdx = ol_txrx_local_peer_id(peer);
+	add_sta->nss    = iface->nss;
+	add_sta->status = QDF_STATUS_SUCCESS;
+send_rsp:
+	WMA_LOGD(FL("Sending add sta rsp to umac (mac:%pM, status:%d)"),
+		 add_sta->staMac, add_sta->status);
+	wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)add_sta, 0);
+}
diff --git a/core/wma/src/wma_nan_datapath.h b/core/wma/src/wma_nan_datapath.h
index b230a10..f498a7f 100644
--- a/core/wma/src/wma_nan_datapath.h
+++ b/core/wma/src/wma_nan_datapath.h
@@ -29,13 +29,11 @@
 
 #include "wma.h"
 #include "sir_api.h"
+#include "sme_nan_datapath.h"
 
 #ifdef WLAN_FEATURE_NAN_DATAPATH
 #define WMA_IS_VDEV_IN_NDI_MODE(intf, vdev_id) \
 				(WMI_VDEV_TYPE_NDI == intf[vdev_id].type)
-
-void wma_add_bss_ndi_mode(tp_wma_handle wma, tpAddBssParams add_bss);
-
 /**
  * wma_update_hdd_cfg_ndp() - Update target device NAN datapath capability
  * @wma_handle: pointer to WMA context
@@ -56,6 +54,9 @@
 void wma_ndp_add_wow_wakeup_event(tp_wma_handle wma_handle,
 						uint8_t vdev_id);
 void wma_ndp_wow_event_callback(void *handle, void *event, uint32_t len);
+void wma_add_bss_ndi_mode(tp_wma_handle wma, tpAddBssParams add_bss);
+void wma_add_sta_ndi_mode(tp_wma_handle wma, tpAddStaParams add_sta);
+QDF_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle, void *req);
 #else
 #define WMA_IS_VDEV_IN_NDI_MODE(intf, vdev_id) (false)
 static inline void wma_update_hdd_cfg_ndp(tp_wma_handle wma_handle,
@@ -80,5 +81,13 @@
 						uint8_t vdev_id) {}
 static inline void wma_ndp_wow_event_callback(void *handle, void *event,
 						uint32_t len) {}
+static inline void wma_add_sta_ndi_mode(tp_wma_handle wma,
+					tpAddStaParams add_sta) {}
+static inline QDF_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle,
+						      void *req)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
 #endif /* WLAN_FEATURE_NAN_DATAPATH */
 #endif /* __WMA_NAN_DATAPATH_H */