diff --git a/target_if/core/inc/target_if.h b/target_if/core/inc/target_if.h index 4a418082ec..e1e5a148b1 100644 --- a/target_if/core/inc/target_if.h +++ b/target_if/core/inc/target_if.h @@ -242,6 +242,7 @@ struct tgt_info { * @smart_log_enable: Enable Smart Logs feature * @cfr_support_enable: CFR support enable * @set_pktlog_checksum: Set the pktlog checksum from FW ready event to pl_dev + * @csa_switch_count_status: CSA event handler */ struct target_ops { QDF_STATUS (*ext_resource_config_enable) @@ -304,6 +305,9 @@ struct target_ops { struct target_psoc_info *tgt_info, uint8_t *event); void (*set_pktlog_checksum) (struct wlan_objmgr_pdev *pdev, uint32_t checksum); + int (*csa_switch_count_status)( + struct wlan_objmgr_psoc *psoc, + struct pdev_csa_switch_count_status csa_status); }; @@ -2115,6 +2119,26 @@ static inline void target_if_add_11ax_modes(struct wlan_objmgr_psoc *psoc, } #endif +/** + * target_if_csa_switch_count_status - Calls a function to process CSA event + * @psoc: psoc object + * @tgt_hdl: target_psoc_info pointer + * @csa_status: CSA switch count status event param + * + * Return: 0 on success, -1 on failure + */ +static inline int target_if_csa_switch_count_status( + struct wlan_objmgr_psoc *psoc, + struct target_psoc_info *tgt_hdl, + struct pdev_csa_switch_count_status csa_status) +{ + if (tgt_hdl->tif_ops && tgt_hdl->tif_ops->csa_switch_count_status) + return tgt_hdl->tif_ops->csa_switch_count_status( + psoc, csa_status); + + return -1; +} + /** * target_if_set_default_config - Set default config in init command * @psoc: psoc object diff --git a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c index 7839d7c9c9..c2b1d1390e 100644 --- a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c +++ b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c @@ -710,6 +710,59 @@ static int target_if_vdev_mgr_multi_vdev_restart_resp_handler( return qdf_status_to_os_return(status); } +/** + * target_if_pdev_csa_status_event_handler - CSA event handler + * @scn: Pointer to scn structure + * @data: pointer to event data + * @datalen: event data length + * + * Return: 0 on success + */ +static int target_if_pdev_csa_status_event_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + struct pdev_csa_switch_count_status csa_status; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct target_psoc_info *tgt_hdl; + QDF_STATUS status; + + if (!scn || !data) { + mlme_err("Invalid input"); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + mlme_err("PSOC is NULL"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_hdl) { + mlme_err("target_psoc_info is null"); + return -EINVAL; + } + + qdf_mem_zero(&csa_status, sizeof(csa_status)); + status = wmi_extract_pdev_csa_switch_count_status( + wmi_handle, data, &csa_status); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("Extracting CSA switch count status event failed"); + return -EINVAL; + } + + return target_if_csa_switch_count_status(psoc, tgt_hdl, csa_status); +} + QDF_STATUS target_if_vdev_mgr_wmi_event_register( struct wlan_objmgr_psoc *psoc) { @@ -767,6 +820,16 @@ QDF_STATUS target_if_vdev_mgr_wmi_event_register( if (QDF_IS_STATUS_ERROR(retval)) mlme_err("failed to register for multivdev restart response"); + if (wmi_service_enabled(wmi_handle, wmi_service_beacon_offload)) { + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_pdev_csa_switch_count_status_event_id, + target_if_pdev_csa_status_event_handler, + VDEV_RSP_RX_CTX); + if (QDF_IS_STATUS_ERROR(retval)) + mlme_err("failed to register for csa event handler"); + } + return retval; } diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 152f834c06..8ef440a39b 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -4235,4 +4235,18 @@ QDF_STATUS wmi_unified_send_vdev_tsf_tstamp_action_cmd(wmi_unified_t wmi_hdl, QDF_STATUS wmi_extract_vdev_tsf_report_event(wmi_unified_t wmi_hdl, uint8_t *evt_buf, struct wmi_host_tsf_event *param); + +/** + * wmi_extract_pdev_csa_switch_count_status() - extract CSA switch count status + * from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to CSA switch count status param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_pdev_csa_switch_count_status( + wmi_unified_t wmi_handle, + void *evt_buf, + struct pdev_csa_switch_count_status *param); #endif /* _WMI_UNIFIED_API_H_ */ diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 40aaecb342..805422d69f 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -3380,3 +3380,16 @@ QDF_STATUS wmi_extract_vdev_tsf_report_event(wmi_unified_t wmi_hdl, return QDF_STATUS_E_FAILURE; } +QDF_STATUS wmi_extract_pdev_csa_switch_count_status( + wmi_unified_t wmi_handle, + void *evt_buf, + struct pdev_csa_switch_count_status *param) +{ + if (wmi_handle->ops->extract_pdev_csa_switch_count_status) + return wmi_handle->ops->extract_pdev_csa_switch_count_status( + wmi_handle, + evt_buf, + param); + + return QDF_STATUS_E_FAILURE; +} diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 02b1e63975..bfa1ab4d9b 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -14112,6 +14112,42 @@ extract_vdev_tsf_report_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_SUCCESS; } +/** + * extract_pdev_csa_switch_count_status_tlv() - extract pdev csa switch count + * status tlv + * @wmi_handle: wmi handle + * @param evt_buf: pointer to event buffer + * @param param: Pointer to hold csa switch count status event param + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +static QDF_STATUS extract_pdev_csa_switch_count_status_tlv( + wmi_unified_t wmi_handle, + void *evt_buf, + struct pdev_csa_switch_count_status *param) +{ + WMI_PDEV_CSA_SWITCH_COUNT_STATUS_EVENTID_param_tlvs *param_buf; + wmi_pdev_csa_switch_count_status_event_fixed_param *csa_status; + + param_buf = (WMI_PDEV_CSA_SWITCH_COUNT_STATUS_EVENTID_param_tlvs *) + evt_buf; + if (!param_buf) { + wmi_err("Invalid CSA status event"); + return QDF_STATUS_E_INVAL; + } + + csa_status = param_buf->fixed_param; + + param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host( + wmi_handle, + csa_status->pdev_id); + param->current_switch_count = csa_status->current_switch_count; + param->num_vdevs = csa_status->num_vdevs; + param->vdev_ids = param_buf->vdev_ids; + + return QDF_STATUS_SUCCESS; +} + struct wmi_ops tlv_ops = { .send_vdev_create_cmd = send_vdev_create_cmd_tlv, .send_vdev_delete_cmd = send_vdev_delete_cmd_tlv, @@ -14468,6 +14504,8 @@ struct wmi_ops tlv_ops = { extract_cp_stats_more_pending_tlv, .send_vdev_tsf_tstamp_action_cmd = send_vdev_tsf_tstamp_action_cmd_tlv, .extract_vdev_tsf_report_event = extract_vdev_tsf_report_event_tlv, + .extract_pdev_csa_switch_count_status = + extract_pdev_csa_switch_count_status_tlv, }; /**