diff --git a/target_if/cp_stats/inc/target_if_cp_stats.h b/target_if/cp_stats/inc/target_if_cp_stats.h index caae7252ac..0a7d45c40b 100644 --- a/target_if/cp_stats/inc/target_if_cp_stats.h +++ b/target_if/cp_stats/inc/target_if_cp_stats.h @@ -120,6 +120,27 @@ target_if_cp_stats_unregister_legacy_event_handler( } #endif /* WLAN_SUPPORT_LEGACY_CP_STATS_HANDLERS */ +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +/** + * get_infra_cp_stats_id() - convert from to wmi_ctrl_path_stats_id + * @type: type from enum infra_cp_stats_id + * + * Return: wmi_ctrl_path_stats_id code for success or -EINVAL + * for failure + */ +uint32_t get_infra_cp_stats_id(enum infra_cp_stats_id type); + +/** + * get_infra_cp_stats_action() - convert action codes from + * enum infra_cp_stats_action to wmi_ctrl_path_stats_action + * @action: action code from enum infra_cp_stats_action + * + * Return: wmi_ctrl_path_stats_action code for success or -EINVAL + * for failure + */ +uint32_t get_infra_cp_stats_action(enum infra_cp_stats_action action); +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + #else static inline QDF_STATUS target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) diff --git a/target_if/cp_stats/src/target_if_cp_stats.c b/target_if/cp_stats/src/target_if_cp_stats.c index 80c2566d62..2ebdfbf2e2 100644 --- a/target_if/cp_stats/src/target_if_cp_stats.c +++ b/target_if/cp_stats/src/target_if_cp_stats.c @@ -33,28 +33,276 @@ #include #include +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS + +uint32_t get_infra_cp_stats_id(enum infra_cp_stats_id type) +{ + switch (type) { + case TYPE_REQ_CTRL_PATH_PDEV_TX_STAT: + return WMI_REQUEST_CTRL_PATH_PDEV_TX_STAT; + case TYPE_REQ_CTRL_PATH_VDEV_EXTD_STAT: + return WMI_REQUEST_CTRL_PATH_VDEV_EXTD_STAT; + case TYPE_REQ_CTRL_PATH_MEM_STAT: + return WMI_REQUEST_CTRL_PATH_MEM_STAT; + case TYPE_REQ_CTRL_PATH_TWT_STAT: + return WMI_REQUEST_CTRL_PATH_TWT_STAT; + default: + return -EINVAL; + } +} + +uint32_t get_infra_cp_stats_action(enum infra_cp_stats_action action) +{ + switch (action) { + case ACTION_REQ_CTRL_PATH_STAT_GET: + return WMI_REQUEST_CTRL_PATH_STAT_GET; + case ACTION_REQ_CTRL_PATH_STAT_RESET: + return WMI_REQUEST_CTRL_PATH_STAT_RESET; + case ACTION_REQ_CTRL_PATH_STAT_START: + return WMI_REQUEST_CTRL_PATH_STAT_START; + case ACTION_REQ_CTRL_PATH_STAT_STOP: + return WMI_REQUEST_CTRL_PATH_STAT_STOP; + default: + return -EINVAL; + } +} + +#ifdef WLAN_SUPPORT_TWT +/** + * target_if_infra_cp_stats_twt_event_free() - Free event buffer + * @ev: pointer to infra cp stats event structure + * + * Return: None + */ +static +void target_if_infra_cp_stats_twt_event_free(struct infra_cp_stats_event *ev) +{ + qdf_mem_free(ev->twt_infra_cp_stats); + ev->twt_infra_cp_stats = NULL; +} + +/** + * target_if_infra_cp_stats_twt_event_alloc() - Allocate event buffer for TWT + * parameters + * @ev: pointer to infra cp stats event structure + * + * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes on + * failure + */ +static QDF_STATUS +target_if_infra_cp_stats_twt_event_alloc(struct infra_cp_stats_event *ev) +{ + ev->twt_infra_cp_stats = + qdf_mem_malloc(sizeof(*ev->twt_infra_cp_stats) * + INFRA_CP_STATS_MAX_RESP_TWT_DIALOG_ID); + if (!ev->twt_infra_cp_stats) { + cp_stats_err("mem alloc failed for ev.twt_infra_cp_stats"); + return QDF_STATUS_E_NOMEM; + } + + return QDF_STATUS_SUCCESS; +} +#else +static inline +void target_if_infra_cp_stats_twt_event_free(struct infra_cp_stats_event *ev) +{ +} + +static inline QDF_STATUS +target_if_infra_cp_stats_twt_event_alloc(struct infra_cp_stats_event *ev) +{ + return QDF_STATUS_SUCCESS; +} + +static inline +void target_if_infra_cp_stats_free_stats_event(struct infra_cp_stats_event *ev) +{ +} +#endif /* WLAN_SUPPORT_TWT */ + +/** + * target_if_extract_infra_cp_stats_event() - Extract data from stats event + * @wmi_hdl: WMI Handle + * @data: pointer to event data buffer from firmware + * @data_len: length of the data buffer + * @ev: pointer of output structure to be filled with extracted values + * + * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes + * on failure + */ +static QDF_STATUS +target_if_extract_infra_cp_stats_event(struct wmi_unified *wmi_hdl, + uint8_t *data, uint32_t data_len, + struct infra_cp_stats_event *ev) +{ + QDF_STATUS status; + uint32_t more_flag = 0; + + status = wmi_unified_extract_cp_stats_more_pending(wmi_hdl, data, + &more_flag); + + status = wmi_unified_extract_infra_cp_stats(wmi_hdl, data, + data_len, ev); + + cp_stats_debug("request_id %d", ev->request_id); + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_infra_cp_stats_event_handler() - Handle + * wmi_pdev_cp_fwstats_eventid + * @scn: opaque scn handle + * @data: event buffer received from fw + * @datalen: length of event buffer + * + * Return: 0 for success or non zero error codes for failure + */ +static +int target_if_infra_cp_stats_event_handler(ol_scn_t scn, uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct infra_cp_stats_event ev = {0}; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_cp_stats_rx_ops *rx_ops; + + if (!scn || !data) { + cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + cp_stats_err("null psoc"); + return -EINVAL; + } + + rx_ops = target_if_cp_stats_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->process_stats_event) { + cp_stats_err("callback not registered"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + cp_stats_err("wmi_handle is null"); + return -EINVAL; + } + status = target_if_infra_cp_stats_twt_event_alloc(&ev); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("Alloc TWT event mem failed"); + goto end; + } + + status = target_if_extract_infra_cp_stats_event(wmi_handle, data, + datalen, &ev); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("extract event failed"); + goto end; + } + + status = rx_ops->process_infra_stats_event(psoc, &ev); + +end: + target_if_infra_cp_stats_twt_event_free(&ev); + + return qdf_status_to_os_return(status); +} +#else +static +int target_if_infra_cp_stats_event_handler(ol_scn_t scn, uint8_t *data, + uint32_t datalen) +{ + return 0; +} +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + static QDF_STATUS target_if_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc) { + struct wmi_unified *wmi_handle; + QDF_STATUS ret_val; + if (!psoc) { cp_stats_err("PSOC is NULL!"); return QDF_STATUS_E_INVAL; } + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + cp_stats_err("wmi_handle is null"); + return QDF_STATUS_E_INVAL; + } + + ret_val = wmi_unified_register_event_handler(wmi_handle, + wmi_pdev_cp_fwstats_eventid, + target_if_infra_cp_stats_event_handler, + WMI_RX_WORK_CTX); + if (QDF_IS_STATUS_ERROR(ret_val)) + cp_stats_err("Failed to register for pdev_cp_fwstats_event"); + return QDF_STATUS_SUCCESS; } static QDF_STATUS target_if_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc) { + struct wmi_unified *wmi_handle; + if (!psoc) { cp_stats_err("PSOC is NULL!"); return QDF_STATUS_E_INVAL; } + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + cp_stats_err("wmi_handle is null"); + return QDF_STATUS_E_INVAL; + } + + wmi_unified_unregister_event_handler(wmi_handle, + wmi_pdev_cp_fwstats_eventid); return QDF_STATUS_SUCCESS; } +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +/** + * target_if_infra_cp_stats_req() - API to send stats request to wmi + * @psoc: pointer to psoc object + * @req: pointer to object containing stats request parameters + * + * Return: QDF_STATUS_SUCCESS on success, else other qdf error values + */ +static +QDF_STATUS target_if_infra_cp_stats_req(struct wlan_objmgr_psoc *psoc, + struct infra_cp_stats_cmd_info *req) + +{ + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + cp_stats_err("wmi_handle is null."); + return QDF_STATUS_E_NULL_VALUE; + } + + return wmi_unified_infra_cp_stats_request_send(wmi_handle, req); +} + +static void target_if_register_infra_cp_stats_txops( + struct wlan_lmac_if_cp_stats_tx_ops *tx_ops) +{ + tx_ops->send_req_infra_cp_stats = target_if_infra_cp_stats_req; +} +#else +static void target_if_register_infra_cp_stats_txops( + struct wlan_lmac_if_cp_stats_tx_ops *tx_ops) +{ +} +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + QDF_STATUS target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { @@ -70,6 +318,7 @@ target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) cp_stats_err("lmac tx ops is NULL!"); return QDF_STATUS_E_FAILURE; } + target_if_register_infra_cp_stats_txops(cp_stats_tx_ops); cp_stats_tx_ops->cp_stats_attach = target_if_cp_stats_register_event_handler;