Browse Source

qcacld-3.0: Add support for disabling an NDI concurrency

NAN Datapath implementation allows more than one concurrent
NDI's to be active at the same time. But this isn't supported
if there is a higher priority incoming connection such as
STA. Add modules that check for unsupported NDI concurrency
and initiates termination of all NDP's on it.

Add modules that check and disable unsupported NDI concurrency.

Change-Id: I6ad9afbfc41beda1d1c8f31bf58a8ea70027f5ca
CRs-Fixed: 2407215
Nachiket Kukade 6 years ago
parent
commit
9ea5f13a28

+ 28 - 2
components/nan/core/inc/nan_public_structs.h

@@ -80,6 +80,8 @@ enum nan_discovery_msg_type {
  * @NDP_NEW_PEER: ndp new peer created
  * @NDP_PEER_DEPARTED: ndp peer departed/deleted
  * @NDP_SCHEDULE_UPDATE: ndp schedule update
+ * @NDP_END_ALL: end all NDPs request
+ * @NDP_HOST_UPDATE: update host about ndp status
  */
 enum nan_datapath_msg_type {
 	NAN_DATAPATH_INF_CREATE_REQ  = 0,
@@ -98,6 +100,8 @@ enum nan_datapath_msg_type {
 	NDP_NEW_PEER                 = 13,
 	NDP_PEER_DEPARTED            = 14,
 	NDP_SCHEDULE_UPDATE          = 15,
+	NDP_END_ALL                  = 16,
+	NDP_HOST_UPDATE              = 17,
 };
 
 /**
@@ -313,14 +317,16 @@ struct peer_nan_datapath_map {
 
 /**
  * struct nan_datapath_channel_info - ndp channel and channel bandwidth
- * @channel: channel freq in mhz of the ndp connection
+ * @freq: channel freq in mhz of the ndp connection
  * @ch_width: channel width (wmi_channel_width) of the ndp connection
  * @nss: nss used for ndp connection
+ * @mac_id: MAC ID associated with the NDP channel
  */
 struct nan_datapath_channel_info {
-	uint32_t channel;
+	uint32_t freq;
 	uint32_t ch_width;
 	uint32_t nss;
+	uint8_t mac_id;
 };
 
 #define NAN_CH_INFO_MAX_LEN \
@@ -480,6 +486,15 @@ struct nan_datapath_end_req {
 	uint32_t ndp_ids[NDP_NUM_INSTANCE_ID];
 };
 
+/**
+ * struct nan_datapath_end_all_ndps - Datapath termination request to end all
+ * NDPs on the given vdev
+ * @vdev: pointer to vdev object
+ */
+struct nan_datapath_end_all_ndps {
+	struct wlan_objmgr_vdev *vdev;
+};
+
 /**
  * enum nan_event_id_types - NAN event ID types
  * @nan_event_id_error_rsp: NAN event indicating error
@@ -692,6 +707,17 @@ struct nan_datapath_sch_update_event {
 	uint32_t ndp_instances[NDP_NUM_INSTANCE_ID];
 };
 
+/**
+ * struct nan_datapath_host_event - ndp host event parameters
+ * @vdev: vdev obj associated with the ndp
+ * @ndp_termination_in_progress: flag that indicates whether NDPs associated
+ * with the given vdev are being terminated
+ */
+struct nan_datapath_host_event {
+	struct wlan_objmgr_vdev *vdev;
+	bool ndp_termination_in_progress;
+};
+
 /**
  * struct nan_callbacks - struct containing callback to non-converged driver
  * @os_if_nan_event_handler: OS IF Callback for handling NAN Discovery events

+ 52 - 0
components/nan/core/src/nan_main.c

@@ -124,6 +124,12 @@ void nan_release_cmd(void *in_req, uint32_t cmdtype)
 		vdev = req->vdev;
 		break;
 	}
+	case WLAN_SER_CMD_NDP_END_ALL_REQ: {
+		struct nan_datapath_end_all_ndps *req = in_req;
+
+		vdev = req->vdev;
+		break;
+	}
 	default:
 		nan_err("invalid req type: %d", cmdtype);
 		break;
@@ -172,6 +178,13 @@ static void nan_req_activated(void *in_req, uint32_t cmdtype)
 		req_type = NDP_END_REQ;
 		break;
 	}
+	case WLAN_SER_CMD_NDP_END_ALL_REQ: {
+		struct nan_datapath_end_all_ndps *req = in_req;
+
+		vdev = req->vdev;
+		req_type = NDP_END_ALL;
+		break;
+	}
 	default:
 		nan_alert("in correct cmdtype: %d", cmdtype);
 		return;
@@ -266,6 +279,13 @@ QDF_STATUS nan_scheduled_msg_handler(struct scheduler_msg *msg)
 		cmd.vdev = req->vdev;
 		break;
 	}
+	case NDP_END_ALL: {
+		struct nan_datapath_end_all_ndps *req = msg->bodyptr;
+
+		cmd.cmd_type = WLAN_SER_CMD_NDP_END_ALL_REQ;
+		cmd.vdev = req->vdev;
+		break;
+	}
 	default:
 		nan_err("wrong request type: %d", msg->type);
 		return QDF_STATUS_E_INVAL;
@@ -846,6 +866,35 @@ static QDF_STATUS nan_handle_schedule_update(
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * nan_handle_host_update: Updates Host about NAN Datapath status, called by
+ * NAN modules's Datapath event handler.
+ *
+ * Return: status of operation
+ */
+static QDF_STATUS nan_handle_host_update(struct nan_datapath_host_event *evt)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct nan_psoc_priv_obj *psoc_nan_obj;
+
+	psoc = wlan_vdev_get_psoc(evt->vdev);
+	if (!psoc) {
+		nan_err("psoc is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	psoc_nan_obj = nan_get_psoc_priv_obj(psoc);
+	if (!psoc_nan_obj) {
+		nan_err("psoc_nan_obj is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	psoc_nan_obj->cb_obj.os_if_ndp_event_handler(psoc, evt->vdev,
+						     NDP_HOST_UPDATE, evt);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS nan_discovery_event_handler(struct scheduler_msg *msg)
 {
 	struct nan_event_params *nan_event;
@@ -934,6 +983,9 @@ QDF_STATUS nan_datapath_event_handler(struct scheduler_msg *pe_msg)
 	case NDP_SCHEDULE_UPDATE:
 		nan_handle_schedule_update(pe_msg->bodyptr);
 		break;
+	case NDP_HOST_UPDATE:
+		nan_handle_host_update(pe_msg->bodyptr);
+		break;
 	default:
 		nan_alert("Unhandled NDP event: %d", pe_msg->type);
 		status = QDF_STATUS_E_NOSUPPORT;

+ 2 - 0
components/nan/core/src/nan_main_i.h

@@ -126,6 +126,7 @@ struct nan_psoc_priv_obj {
  * @ndi_delete_rsp_reason: reason code for ndi_delete rsp
  * @ndi_delete_rsp_status: status for ndi_delete rsp
  * @primary_peer_mac: Primary NDP Peer mac address for the vdev
+ * @disable_context: Disable all NDP's operation context
  */
 struct nan_vdev_priv_obj {
 	qdf_spinlock_t lock;
@@ -136,6 +137,7 @@ struct nan_vdev_priv_obj {
 	uint32_t ndi_delete_rsp_reason;
 	uint32_t ndi_delete_rsp_status;
 	struct qdf_mac_addr primary_peer_mac;
+	void *disable_context;
 };
 
 /**

+ 26 - 0
components/nan/dispatcher/inc/nan_ucfg_api.h

@@ -236,6 +236,16 @@ bool ucfg_is_nan_disable_supported(struct wlan_objmgr_psoc *psoc);
  */
 bool ucfg_is_nan_dbs_supported(struct wlan_objmgr_psoc *psoc);
 
+/**
+ * ucfg_is_ndi_dbs_supported() - ucfg API to query NAN Datapath DBS support
+ * @psoc: pointer to psoc object
+ *
+ * This function returns NDI DBS support status
+ *
+ * Return: True if NDI DBS is supported, False otherwise
+ */
+bool ucfg_is_ndi_dbs_supported(struct wlan_objmgr_psoc *psoc);
+
 /**
  * ucfg_is_nan_enable_allowed() - ucfg API to query if NAN Discovery is
  * allowed
@@ -274,6 +284,16 @@ void ucfg_nan_disable_concurrency(struct wlan_objmgr_psoc *psoc);
  */
 int ucfg_nan_register_wma_callbacks(struct wlan_objmgr_psoc *psoc,
 				    struct nan_callbacks *cb_obj);
+/**
+ * ucfg_nan_check_and_disable_unsupported_ndi: ucfg API to check if NAN Datapath
+ * is active on multiple NDI's and disable the unsupported concurrencies.
+ * @psoc: pointer to psoc object
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+ucfg_nan_check_and_disable_unsupported_ndi(struct wlan_objmgr_psoc *psoc);
+
 #else /* WLAN_FEATURE_NAN */
 
 static inline
@@ -285,5 +305,11 @@ void ucfg_nan_set_tgt_caps(struct wlan_objmgr_psoc *psoc,
 static inline void ucfg_nan_disable_concurrency(struct wlan_objmgr_psoc *psoc)
 {
 }
+
+static inline QDF_STATUS
+ucfg_nan_check_and_disable_unsupported_ndi(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif /* WLAN_FEATURE_NAN */
 #endif /* _NAN_UCFG_API_H_ */

+ 131 - 2
components/nan/dispatcher/src/nan_ucfg_api.c

@@ -29,6 +29,7 @@
 #include "wlan_objmgr_pdev_obj.h"
 #include "wlan_objmgr_vdev_obj.h"
 #include "wlan_osif_request_manager.h"
+#include "wlan_policy_mgr_api.h"
 
 struct wlan_objmgr_psoc;
 struct wlan_objmgr_vdev;
@@ -275,6 +276,9 @@ static QDF_STATUS ucfg_nan_sch_msg_flush_cb(struct scheduler_msg *msg)
 	case NDP_END_REQ:
 		vdev = ((struct nan_datapath_end_req *)msg->bodyptr)->vdev;
 		break;
+	case NDP_END_ALL:
+		vdev = ((struct nan_datapath_end_all_ndps *)msg->bodyptr)->vdev;
+		break;
 	default:
 		nan_err("Invalid NAN msg type during sch flush");
 		return QDF_STATUS_E_INVAL;
@@ -310,6 +314,9 @@ QDF_STATUS ucfg_nan_req_processor(struct wlan_objmgr_vdev *vdev,
 	case NDP_END_REQ:
 		len = sizeof(struct nan_datapath_end_req);
 		break;
+	case NDP_END_ALL:
+		len = sizeof(struct nan_datapath_end_all_ndps);
+		break;
 	default:
 		nan_err("in correct message req type: %d", req_type);
 		return QDF_STATUS_E_INVAL;
@@ -463,6 +470,19 @@ bool ucfg_is_nan_dbs_supported(struct wlan_objmgr_psoc *psoc)
 	return (psoc_priv->nan_caps.nan_dbs_supported == 1);
 }
 
+bool ucfg_is_ndi_dbs_supported(struct wlan_objmgr_psoc *psoc)
+{
+	struct nan_psoc_priv_obj *psoc_priv;
+
+	psoc_priv = nan_get_psoc_priv_obj(psoc);
+	if (!psoc_priv) {
+		nan_err("nan psoc priv object is NULL");
+		return false;
+	}
+
+	return (psoc_priv->nan_caps.ndi_dbs_supported == 1);
+}
+
 bool ucfg_is_nan_enable_allowed(struct wlan_objmgr_psoc *psoc, uint8_t nan_chan)
 {
 	return nan_is_enable_allowed(psoc, nan_chan);
@@ -619,16 +639,15 @@ void ucfg_nan_disable_concurrency(struct wlan_objmgr_psoc *psoc)
 	nan_req.psoc = psoc;
 	nan_req.disable_2g_discovery = true;
 	nan_req.disable_5g_discovery = true;
+	psoc_priv->disable_context = osif_request_cookie(request);
 
 	status = ucfg_nan_discovery_req(&nan_req, NAN_DISABLE_REQ);
-
 	if (QDF_IS_STATUS_ERROR(status)) {
 		nan_err("Unable to disable NAN Discovery");
 		osif_request_put(request);
 		return;
 	}
 
-	psoc_priv->disable_context = osif_request_cookie(request);
 	psoc_priv->is_explicit_disable = true;
 	nan_debug("Successfully sent NAN Disable request");
 
@@ -641,3 +660,113 @@ void ucfg_nan_disable_concurrency(struct wlan_objmgr_psoc *psoc)
 	psoc_priv->is_explicit_disable = false;
 	osif_request_put(request);
 }
+
+QDF_STATUS
+ucfg_nan_check_and_disable_unsupported_ndi(struct wlan_objmgr_psoc *psoc)
+{
+	enum nan_datapath_state curr_ndi_state;
+	struct nan_datapath_host_event *event;
+	uint32_t ndi_count, first_ndi_vdev_id;
+	struct nan_vdev_priv_obj *ndi_vdev_priv;
+	struct nan_datapath_end_all_ndps req = {0};
+	struct wlan_objmgr_vdev *ndi_vdev;
+	struct osif_request *request;
+	QDF_STATUS status;
+	int err;
+	static const struct osif_request_params params = {
+		.priv_size = sizeof(struct nan_datapath_host_event),
+		.timeout_ms = 1000,
+	};
+
+	if (!psoc) {
+		nan_err("psoc object is NULL, no action will be taken");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (!ucfg_is_ndi_dbs_supported(psoc))
+		return QDF_STATUS_SUCCESS;
+
+	ndi_count = policy_mgr_mode_specific_connection_count(psoc, PM_NDI_MODE,
+							      NULL);
+	if (ndi_count < 2) {
+		nan_debug("No more than one NDI is active, nothing to do...");
+		return QDF_STATUS_SUCCESS;
+	}
+
+	/*
+	 * At least 2 NDI active concurrencies exist. Disable all NDP's on the
+	 * first NDI to support an incoming connection.
+	 */
+	first_ndi_vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_NDI_MODE);
+	ndi_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, first_ndi_vdev_id,
+							WLAN_NAN_ID);
+	if (!ndi_vdev) {
+		nan_err("Cannot obtain NDI vdev object!");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	ndi_vdev_priv = nan_get_vdev_priv_obj(ndi_vdev);
+	if (!ndi_vdev_priv) {
+		nan_err("ndi vdev priv object is NULL");
+		wlan_objmgr_vdev_release_ref(ndi_vdev, WLAN_NAN_ID);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	qdf_spin_lock_bh(&ndi_vdev_priv->lock);
+	curr_ndi_state = ndi_vdev_priv->state;
+	/* Nothing to do if NDI is in DELETING or DATA_END state */
+	if (curr_ndi_state == NAN_DATA_NDI_DELETING_STATE ||
+	    curr_ndi_state == NAN_DATA_END_STATE) {
+		qdf_spin_unlock_bh(&ndi_vdev_priv->lock);
+		wlan_objmgr_vdev_release_ref(ndi_vdev, WLAN_NAN_ID);
+		return QDF_STATUS_SUCCESS;
+	}
+	ndi_vdev_priv->state = NAN_DATA_END_STATE;
+	qdf_spin_unlock_bh(&ndi_vdev_priv->lock);
+
+	request = osif_request_alloc(&params);
+	if (!request) {
+		nan_err("Request allocation failure");
+		status = QDF_STATUS_E_NOMEM;
+		goto cleanup;
+	}
+	ndi_vdev_priv->disable_context = osif_request_cookie(request);
+
+	req.vdev = ndi_vdev;
+	status = ucfg_nan_req_processor(NULL, &req, NDP_END_ALL);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		nan_err("Unable to disable NDP's on NDI");
+		wlan_objmgr_vdev_release_ref(ndi_vdev, WLAN_NAN_ID);
+		goto cleanup;
+	}
+
+	nan_debug("Disabling all NDP's on NDI vdev id - %d", first_ndi_vdev_id);
+
+	err = osif_request_wait_for_response(request);
+	if (err) {
+		nan_err("Disabling NDP's timed out waiting for confirmation");
+		status = QDF_STATUS_E_TIMEOUT;
+		goto cleanup;
+	}
+
+	event = osif_request_priv(request);
+	if (!event->ndp_termination_in_progress) {
+		nan_err("Failed to terminate NDP's on NDI");
+		status = QDF_STATUS_E_FAILURE;
+	}
+
+cleanup:
+	/* Restore original NDI state in case of failure */
+	qdf_spin_lock_bh(&ndi_vdev_priv->lock);
+	if (QDF_IS_STATUS_SUCCESS(status))
+		ndi_vdev_priv->state = NAN_DATA_DISCONNECTED_STATE;
+	else
+		ndi_vdev_priv->state = curr_ndi_state;
+	qdf_spin_unlock_bh(&ndi_vdev_priv->lock);
+
+	if (request)
+		osif_request_put(request);
+
+	return status;
+}

+ 110 - 0
components/target_if/nan/src/target_if_nan.c

@@ -92,6 +92,9 @@ static QDF_STATUS target_if_ndp_event_flush_cb(struct scheduler_msg *msg)
 	case NDP_SCHEDULE_UPDATE:
 		vdev = ((struct nan_datapath_sch_update_event *)ptr)->vdev;
 		break;
+	case NDP_HOST_UPDATE:
+		vdev = ((struct nan_datapath_host_event *)ptr)->vdev;
+		break;
 	default:
 		break;
 	}
@@ -134,6 +137,9 @@ static QDF_STATUS target_if_ndp_event_dispatcher(struct scheduler_msg *msg)
 	case NDP_SCHEDULE_UPDATE:
 		vdev = ((struct nan_datapath_sch_update_event *)ptr)->vdev;
 		break;
+	case NDP_HOST_UPDATE:
+		vdev = ((struct nan_datapath_host_event *)ptr)->vdev;
+		break;
 	default:
 		target_if_err("invalid msg type %d", msg->type);
 		status = QDF_STATUS_E_INVAL;
@@ -667,6 +673,92 @@ static int target_if_ndp_sch_update_handler(ol_scn_t scn, uint8_t *data,
 	return 0;
 }
 
+static QDF_STATUS target_if_nan_end_all_ndps_req(void *req)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_psoc *psoc;
+	struct wmi_unified *wmi_handle;
+	uint8_t vdev_id;
+
+	vdev = ((struct nan_datapath_end_all_ndps *)req)->vdev;
+	if (!vdev) {
+		target_if_err("vdev object is NULL!");
+		return QDF_STATUS_E_INVAL;
+	}
+	vdev_id = wlan_vdev_get_id(vdev);
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		target_if_err("psoc is null.");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("wmi_handle is null.");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return wmi_unified_terminate_all_ndps_req_cmd(wmi_handle, vdev_id);
+}
+
+static int target_if_ndp_host_event_handler(ol_scn_t scn, uint8_t *data,
+					    uint32_t data_len)
+{
+	QDF_STATUS status;
+	struct wlan_objmgr_psoc *psoc;
+	struct wmi_unified *wmi_handle;
+	struct scheduler_msg msg = {0};
+	struct nan_datapath_host_event *host_evt = NULL;
+
+	psoc = target_if_get_psoc_from_scn_hdl(scn);
+	if (!psoc) {
+		target_if_err("psoc is null");
+		return -EINVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("wmi_handle is null.");
+		return -EINVAL;
+	}
+
+	host_evt = qdf_mem_malloc(sizeof(*host_evt));
+	if (!host_evt) {
+		target_if_err("malloc failed");
+		return -ENOMEM;
+	}
+
+	status = wmi_extract_ndp_host_event(wmi_handle, data, host_evt);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		target_if_err("parsing of event failed, %d", status);
+		qdf_mem_free(host_evt);
+		return -EINVAL;
+	}
+
+	if (!host_evt->vdev) {
+		target_if_err("vdev is null");
+		qdf_mem_free(host_evt);
+		return -EINVAL;
+	}
+
+	msg.bodyptr = host_evt;
+	msg.type = NDP_HOST_UPDATE;
+	msg.callback = target_if_ndp_event_dispatcher;
+	msg.flush_callback = target_if_ndp_event_flush_cb;
+	target_if_debug("NDP_HOST_UPDATE sent: %d", msg.type);
+	status = scheduler_post_message(QDF_MODULE_ID_TARGET_IF,
+					QDF_MODULE_ID_TARGET_IF,
+					QDF_MODULE_ID_TARGET_IF, &msg);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		target_if_err("failed to post msg, status: %d", status);
+		target_if_ndp_event_flush_cb(&msg);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static QDF_STATUS target_if_nan_datapath_req(void *req, uint32_t req_type)
 {
 	/* send cmd to fw */
@@ -680,6 +772,9 @@ static QDF_STATUS target_if_nan_datapath_req(void *req, uint32_t req_type)
 	case NDP_END_REQ:
 		target_if_nan_ndp_end_req(req);
 		break;
+	case NDP_END_ALL:
+		target_if_nan_end_all_ndps_req(req);
+		break;
 	default:
 		target_if_err("invalid req type");
 		break;
@@ -933,6 +1028,15 @@ QDF_STATUS target_if_nan_register_events(struct wlan_objmgr_psoc *psoc)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	ret = wmi_unified_register_event_handler(handle, wmi_ndp_event_id,
+					       target_if_ndp_host_event_handler,
+					       WMI_RX_UMAC_CTX);
+	if (ret) {
+		target_if_err("wmi event registration failed, ret: %d", ret);
+		target_if_nan_deregister_events(psoc);
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -994,6 +1098,12 @@ QDF_STATUS target_if_nan_deregister_events(struct wlan_objmgr_psoc *psoc)
 		status = ret;
 	}
 
+	ret = wmi_unified_unregister_event_handler(handle, wmi_ndp_event_id);
+	if (ret) {
+		target_if_err("wmi event deregistration failed, ret: %d", ret);
+		status = ret;
+	}
+
 	if (status)
 		return QDF_STATUS_E_FAILURE;
 	else

+ 2 - 1
core/wma/src/wma_utils.c

@@ -4039,8 +4039,9 @@ QDF_STATUS wma_ndi_update_connection_info(uint8_t vdev_id,
 	}
 
 	wma_iface_entry->chan_width = ndp_chan_info->ch_width;
-	wma_iface_entry->mhz = ndp_chan_info->channel;
+	wma_iface_entry->mhz = ndp_chan_info->freq;
 	wma_iface_entry->nss = ndp_chan_info->nss;
+	wma_iface_entry->mac_id = ndp_chan_info->mac_id;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 41 - 5
os_if/nan/src/os_if_nan.c

@@ -1400,8 +1400,8 @@ static QDF_STATUS os_if_ndp_confirm_pack_ch_info(struct sk_buff *event,
 		return QDF_STATUS_E_FAULT;
 
 	for (idx = 0; idx < ndp_confirm->num_channels; idx++) {
-		cfg80211_debug("ch[%d]: freq: %d, width: %d, nss: %d",
-			       idx, ndp_confirm->ch[idx].channel,
+		cfg80211_debug("Freq[%d]: freq: %d, width: %d, nss: %d",
+			       idx, ndp_confirm->ch[idx].freq,
 			       ndp_confirm->ch[idx].ch_width,
 			       ndp_confirm->ch[idx].nss);
 		ch_element = nla_nest_start(event, idx);
@@ -1409,7 +1409,7 @@ static QDF_STATUS os_if_ndp_confirm_pack_ch_info(struct sk_buff *event,
 			return QDF_STATUS_E_FAULT;
 
 		if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL,
-				ndp_confirm->ch[idx].channel))
+				ndp_confirm->ch[idx].freq))
 			return QDF_STATUS_E_FAULT;
 
 		if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH,
@@ -2027,7 +2027,7 @@ static QDF_STATUS os_if_ndp_sch_update_pack_ch_info(struct sk_buff *event,
 
 	for (idx = 0; idx < sch_update->num_channels; idx++) {
 		cfg80211_debug("ch[%d]: freq: %d, width: %d, nss: %d",
-			       idx, sch_update->ch[idx].channel,
+			       idx, sch_update->ch[idx].freq,
 			       sch_update->ch[idx].ch_width,
 			       sch_update->ch[idx].nss);
 		ch_element = nla_nest_start(event, idx);
@@ -2035,7 +2035,7 @@ static QDF_STATUS os_if_ndp_sch_update_pack_ch_info(struct sk_buff *event,
 			return QDF_STATUS_E_FAULT;
 
 		if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL,
-				sch_update->ch[idx].channel))
+				sch_update->ch[idx].freq))
 			return QDF_STATUS_E_FAULT;
 
 		if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH,
@@ -2141,6 +2141,39 @@ ndp_sch_ind_nla_failed:
 	kfree_skb(vendor_event);
 }
 
+/**
+ * os_if_ndp_host_update_handler() - NDP Host update handler
+ * @vdev: vdev object pointer
+ * @evt: pointer to host update event
+ *
+ * Return: none
+ */
+static void os_if_ndp_host_update_handler(struct wlan_objmgr_vdev *vdev,
+					  void *evt)
+{
+	struct nan_vdev_priv_obj *vdev_nan_obj;
+	struct nan_datapath_host_event *event;
+	struct osif_request *request;
+
+	vdev_nan_obj = nan_get_vdev_priv_obj(vdev);
+	if (!vdev_nan_obj) {
+		cfg80211_err("vdev_nan_obj is NULL");
+		return;
+	}
+
+	request = osif_request_get(vdev_nan_obj->disable_context);
+	if (!request) {
+		cfg80211_debug("Obsolete request");
+		return;
+	}
+
+	event = osif_request_priv(request);
+	qdf_mem_copy(event, evt, sizeof(*event));
+
+	osif_request_complete(request);
+	osif_request_put(request);
+}
+
 static void os_if_nan_datapath_event_handler(struct wlan_objmgr_psoc *psoc,
 					     struct wlan_objmgr_vdev *vdev,
 					     uint32_t type, void *msg)
@@ -2179,6 +2212,9 @@ static void os_if_nan_datapath_event_handler(struct wlan_objmgr_psoc *psoc,
 	case NDP_SCHEDULE_UPDATE:
 		os_if_ndp_sch_update_ind_handler(vdev, msg);
 		break;
+	case NDP_HOST_UPDATE:
+		os_if_ndp_host_update_handler(vdev, msg);
+		break;
 	default:
 		break;
 	}