diff --git a/components/nan/core/inc/nan_public_structs.h b/components/nan/core/inc/nan_public_structs.h index 3a7dfc905679..5920e3975d15 100644 --- a/components/nan/core/inc/nan_public_structs.h +++ b/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 diff --git a/components/nan/core/src/nan_main.c b/components/nan/core/src/nan_main.c index d2f4d87bd0f2..b28c7f4c6871 100644 --- a/components/nan/core/src/nan_main.c +++ b/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; diff --git a/components/nan/core/src/nan_main_i.h b/components/nan/core/src/nan_main_i.h index 6ff4794ad594..1c41b1cba2e1 100644 --- a/components/nan/core/src/nan_main_i.h +++ b/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; }; /** diff --git a/components/nan/dispatcher/inc/nan_ucfg_api.h b/components/nan/dispatcher/inc/nan_ucfg_api.h index 6f8e731a702a..e9c2b2d13956 100644 --- a/components/nan/dispatcher/inc/nan_ucfg_api.h +++ b/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_ */ diff --git a/components/nan/dispatcher/src/nan_ucfg_api.c b/components/nan/dispatcher/src/nan_ucfg_api.c index 8b523000252c..92dc7ef43041 100644 --- a/components/nan/dispatcher/src/nan_ucfg_api.c +++ b/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(¶ms); + 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; +} diff --git a/components/target_if/nan/src/target_if_nan.c b/components/target_if/nan/src/target_if_nan.c index 8bb2599f6c69..3919315301f5 100644 --- a/components/target_if/nan/src/target_if_nan.c +++ b/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 diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 362359128a00..611a82aad698 100644 --- a/core/wma/src/wma_utils.c +++ b/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; } diff --git a/os_if/nan/src/os_if_nan.c b/os_if/nan/src/os_if_nan.c index 92830cc80e0e..88edbcbc1b9d 100644 --- a/os_if/nan/src/os_if_nan.c +++ b/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; }