From 0d4a8a67813c3c877a04cfe3ad66ed6c065e0270 Mon Sep 17 00:00:00 2001 From: Rajasekaran Kalidoss Date: Sat, 16 Jan 2021 05:57:48 +0530 Subject: [PATCH] qcacmn: Add wmi support for REQUEST_CTRL_PATH_STATS Firmware has added support for control path stats infrastructure. Add wmi support to prepare wmi tlv buffer and send WMI_REQUEST_CTRL_PATH_STATS_CMDID. In the response path, add support to handle WMI_CTRL_PATH_STATS_EVENTID and extract the tlv. Change-Id: I930a44187af29adfda8acd90d0e41cff5fc94603 CRs-Fixed: 2856370 --- wmi/inc/wmi_unified_api.h | 18 +++ wmi/inc/wmi_unified_cp_stats_api.h | 18 ++- wmi/inc/wmi_unified_priv.h | 10 ++ wmi/src/wmi_unified_api.c | 16 +++ wmi/src/wmi_unified_cp_stats_api.c | 16 ++- wmi/src/wmi_unified_cp_stats_tlv.c | 179 ++++++++++++++++++++++++++- wmi/src/wmi_unified_tlv.c | 186 ++++++++++++++++++++++++++++- 7 files changed, 438 insertions(+), 5 deletions(-) diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 604a8c01bc..3e726454e9 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -4217,6 +4217,24 @@ wmi_unified_send_injector_frame_config_cmd(wmi_unified_t wmi_handle, QDF_STATUS wmi_unified_send_cp_stats_cmd(wmi_unified_t wmi_handle, void *buf_ptr, uint32_t buf_len); +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +/** + * wmi_unified_extract_infra_cp_stats() - extract various infra cp statistics + * @wmi_handle: wmi handle + * @evt_buf: event buffer + * @evt_buf_len: length of event buffer + * @params: pointer to store the extracted event info + * + * This function extracts the infra cp statistics from the event + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_extract_infra_cp_stats(wmi_unified_t wmi_handle, + void *evt_buf, uint32_t evt_buf_len, + struct infra_cp_stats_event *params); +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + /** * wmi_unified_extract_cp_stats_more_pending() - extract more flag * @wmi_handle: wmi handle diff --git a/wmi/inc/wmi_unified_cp_stats_api.h b/wmi/inc/wmi_unified_cp_stats_api.h index a5532298f0..cbd4f00080 100644 --- a/wmi/inc/wmi_unified_cp_stats_api.h +++ b/wmi/inc/wmi_unified_cp_stats_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,6 +24,22 @@ #include #endif +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +/** + * wmi_unified_infra_cp_stats_request_send() - WMI request infra_cp_stats + * function + * @wmi_handle: wmi handle + * @param: pointer to hold infra_cp_stats request parameters + * + * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error + * codes on failure + */ +QDF_STATUS +wmi_unified_infra_cp_stats_request_send( + wmi_unified_t wmi_handle, + struct infra_cp_stats_cmd_info *param); +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + /** * wmi_unified_stats_request_send() - WMI request stats function * @wmi_handle: handle to WMI diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 54d8665263..cd7273f590 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -2474,6 +2474,16 @@ QDF_STATUS (*send_cp_stats_cmd)(wmi_unified_t wmi_handle, QDF_STATUS (*extract_cp_stats_more_pending)(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *more_flag); +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +QDF_STATUS +(*extract_infra_cp_stats)(wmi_unified_t wmi_handle, + void *evt_buf, uint32_t evt_buf_len, + struct infra_cp_stats_event *params); + +QDF_STATUS +(*send_infra_cp_stats_request_cmd)(wmi_unified_t wmi_handle, + struct infra_cp_stats_cmd_info *param); +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ QDF_STATUS (*send_vdev_tsf_tstamp_action_cmd)(wmi_unified_t wmi, uint8_t vdev_id); diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 44e776ea9f..41d5cd4ac5 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -3327,6 +3327,22 @@ QDF_STATUS wmi_unified_send_cp_stats_cmd(wmi_unified_t wmi_handle, return QDF_STATUS_E_FAILURE; } +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +QDF_STATUS +wmi_unified_extract_infra_cp_stats(wmi_unified_t wmi_handle, + void *evt_buf, uint32_t evt_buf_len, + struct infra_cp_stats_event *params) +{ + if (wmi_handle->ops->extract_infra_cp_stats) + return wmi_handle->ops->extract_infra_cp_stats(wmi_handle, + evt_buf, + evt_buf_len, + params); + + return QDF_STATUS_E_FAILURE; +} +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + QDF_STATUS wmi_unified_extract_cp_stats_more_pending(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *more_flag) diff --git a/wmi/src/wmi_unified_cp_stats_api.c b/wmi/src/wmi_unified_cp_stats_api.c index 27d42b51c4..42633c6922 100644 --- a/wmi/src/wmi_unified_cp_stats_api.c +++ b/wmi/src/wmi_unified_cp_stats_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,6 +21,20 @@ #include "wmi_unified_param.h" #include "wmi_unified_cp_stats_api.h" +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +QDF_STATUS +wmi_unified_infra_cp_stats_request_send(wmi_unified_t wmi_handle, + struct infra_cp_stats_cmd_info *param) +{ + if (wmi_handle->ops->send_infra_cp_stats_request_cmd) + return wmi_handle->ops->send_infra_cp_stats_request_cmd( + wmi_handle, + param); + + return QDF_STATUS_E_FAILURE; +} +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + QDF_STATUS wmi_unified_stats_request_send(wmi_unified_t wmi_handle, uint8_t macaddr[QDF_MAC_ADDR_SIZE], struct stats_request_params *param) diff --git a/wmi/src/wmi_unified_cp_stats_tlv.c b/wmi/src/wmi_unified_cp_stats_tlv.c index 5afff91ad8..bdd8e225d5 100644 --- a/wmi/src/wmi_unified_cp_stats_tlv.c +++ b/wmi/src/wmi_unified_cp_stats_tlv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,6 +18,170 @@ #include "wmi.h" #include "wmi_unified_priv.h" #include "wmi_unified_param.h" +#include "target_if_cp_stats.h" +#include + +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +#ifdef WLAN_SUPPORT_TWT +static uint32_t +get_stats_req_twt_dialog_id(struct infra_cp_stats_cmd_info *req) +{ + return req->dialog_id; +} +#else +static inline +uint32_t get_stats_req_twt_dialog_id(struct infra_cp_stats_cmd_info *req) +{ + return 0; +} +#endif +/** + * prepare_infra_cp_stats_buf() - Allocate and prepate wmi cmd request buffer + * @wmi_handle: wmi handle + * @stats_req: Request parameters to be filled in wmi cmd request buffer + * @req_buf_len: length of the output wmi cmd buffer allocated + * + * Return: Valid wmi buffer pointer on success and NULL pointer for failure + */ +static wmi_buf_t +prepare_infra_cp_stats_buf(wmi_unified_t wmi_handle, + struct infra_cp_stats_cmd_info *stats_req, + uint32_t *req_buf_len) +{ + wmi_request_ctrl_path_stats_cmd_fixed_param *cmd_fixed_param; + uint32_t index; + wmi_buf_t req_buf; + uint8_t *buf_ptr; + uint32_t *pdev_id_array; + uint32_t *vdev_id_array; + uint8_t *mac_addr_array; + uint32_t *dialog_id_array; + uint32_t num_pdev_ids = stats_req->num_pdev_ids; + uint32_t num_vdev_ids = stats_req->num_vdev_ids; + uint32_t num_mac_addr_list = stats_req->num_mac_addr_list; + uint32_t num_dialog_ids = INFRA_CP_STATS_MAX_REQ_TWT_DIALOG_ID; + + /* Calculate total buffer length */ + *req_buf_len = (sizeof(wmi_request_ctrl_path_stats_cmd_fixed_param) + + WMI_TLV_HDR_SIZE + (sizeof(A_UINT32) * (num_pdev_ids)) + + WMI_TLV_HDR_SIZE + sizeof(A_UINT32) * (num_vdev_ids) + + WMI_TLV_HDR_SIZE + + sizeof(wmi_mac_addr) * (num_mac_addr_list) + + WMI_TLV_HDR_SIZE + + (sizeof(A_UINT32) * (num_dialog_ids))); + req_buf = wmi_buf_alloc(wmi_handle, *req_buf_len); + if (!req_buf) + return NULL; + + cmd_fixed_param = (wmi_request_ctrl_path_stats_cmd_fixed_param *) + wmi_buf_data(req_buf); + + /*Set TLV header*/ + WMITLV_SET_HDR(&cmd_fixed_param->tlv_header, + WMITLV_TAG_STRUC_wmi_request_ctrl_path_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_request_ctrl_path_stats_cmd_fixed_param)); + + index = get_infra_cp_stats_id(stats_req->stats_id); + cmd_fixed_param->stats_id_mask = (1 << index); + + cmd_fixed_param->request_id = stats_req->action; + cmd_fixed_param->action = get_infra_cp_stats_action(stats_req->action); + + buf_ptr = (uint8_t *)cmd_fixed_param; + /* Setting tlv header for pdev id arrays*/ + buf_ptr = buf_ptr + sizeof(*cmd_fixed_param); + pdev_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + sizeof(A_UINT32) * num_pdev_ids); + + /* Setting tlv header for vdev id arrays*/ + buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE + + (sizeof(A_UINT32) * num_pdev_ids); + vdev_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + sizeof(A_UINT32) * num_vdev_ids); + + /* Setting tlv header for mac addr arrays*/ + buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE + + (sizeof(A_UINT32) * num_vdev_ids); + mac_addr_array = buf_ptr + WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, + sizeof(wmi_mac_addr) * num_mac_addr_list); + + /* Setting tlv header for dialog id arrays*/ + buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE + + sizeof(wmi_mac_addr) * num_mac_addr_list; + dialog_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + sizeof(A_UINT32) * num_dialog_ids); + + for (index = 0; index < num_pdev_ids; index++) + pdev_id_array[index] = stats_req->pdev_id[index]; + + for (index = 0; index < num_vdev_ids; index++) + vdev_id_array[index] = stats_req->vdev_id[index]; + + for (index = 0; index < num_mac_addr_list; index++) { + qdf_mem_copy(mac_addr_array, stats_req->peer_mac_addr[index], + QDF_MAC_ADDR_SIZE); + mac_addr_array += QDF_MAC_ADDR_SIZE; + } + + dialog_id_array[0] = get_stats_req_twt_dialog_id(stats_req); + + wmi_debug("stats_id_mask 0x%x action 0x%x dialog_id %d", + cmd_fixed_param->stats_id_mask, cmd_fixed_param->action, + dialog_id_array[0]); + wmi_debug("num_pdev_ids %d num_vdev_ids %d num_dialog_ids %d \ + num_mac_addr %d", num_pdev_ids, num_vdev_ids, + num_dialog_ids, num_mac_addr_list); + + return req_buf; +} + +/** + * send_infra_cp_stats_request_cmd_tlv() - Prepare and send infra_cp_stats + * wmi cmd to firmware + * @wmi_handle: wmi handle + * @param: Pointer to request structure + * + * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes + * on failure + */ +static QDF_STATUS +send_infra_cp_stats_request_cmd_tlv(wmi_unified_t wmi_handle, + struct infra_cp_stats_cmd_info *param) +{ + uint32_t len; + wmi_buf_t buf; + QDF_STATUS status; + + buf = prepare_infra_cp_stats_buf(wmi_handle, param, &len); + if (!buf) + return QDF_STATUS_E_NOMEM; + + wmi_debug("buf_len %d", len); + + wmi_mtrace(WMI_REQUEST_CTRL_PATH_STATS_CMDID, NO_SESSION, 0); + status = wmi_unified_cmd_send(wmi_handle, buf, + len, WMI_REQUEST_CTRL_PATH_STATS_CMDID); + + if (QDF_IS_STATUS_ERROR(status)) { + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} +#else +static inline QDF_STATUS +send_infra_cp_stats_request_cmd_tlv(wmi_unified_t wmi_handle, + struct infra_cp_stats_cmd_info *param) +{ + return QDF_STATUS_SUCCESS; +} +#endif /** * send_stats_request_cmd_tlv() - WMI request stats function @@ -501,6 +665,18 @@ extract_pmf_bcn_protect_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_SUCCESS; } +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +static void wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops *ops) +{ + ops->send_infra_cp_stats_request_cmd = + send_infra_cp_stats_request_cmd_tlv; +} +#else +static void wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops *ops) +{ +} +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + void wmi_cp_stats_attach_tlv(wmi_unified_t wmi_handle) { struct wmi_ops *ops = wmi_handle->ops; @@ -511,6 +687,7 @@ void wmi_cp_stats_attach_tlv(wmi_unified_t wmi_handle) ops->extract_vdev_stats = extract_vdev_stats_tlv; ops->extract_peer_stats = extract_peer_stats_tlv; ops->extract_peer_extd_stats = extract_peer_extd_stats_tlv; + wmi_infra_cp_stats_ops_attach_tlv(ops); ops->extract_pmf_bcn_protect_stats = extract_pmf_bcn_protect_stats_tlv, wmi_mc_cp_stats_attach_tlv(wmi_handle); diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 8217c376a9..98962ed551 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -4780,8 +4780,9 @@ static void wmi_set_pno_channel_prediction(uint8_t *buf_ptr, /** * send_cp_stats_cmd_tlv() - Send cp stats wmi command - * @buf_ptr: Buffer passed by upper layers - * @buf_len: Length of passed buffer by upper layer + * @wmi_handle: wmi handle + * @buf_ptr: Buffer passed by upper layers + * @buf_len: Length of passed buffer by upper layer * * Copy the buffer passed by the upper layers and send it * down to the firmware. @@ -4815,6 +4816,184 @@ static QDF_STATUS send_cp_stats_cmd_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS +#ifdef WLAN_SUPPORT_TWT +static inline +void wmi_extract_ctrl_path_twt_stats_tlv(void *tag_buf, + struct twt_infra_cp_stats_event *param) +{ + wmi_ctrl_path_twt_stats_struct *wmi_stats_buf = + (wmi_ctrl_path_twt_stats_struct *)tag_buf; + + param->dialog_id = wmi_stats_buf->dialog_id; + param->status = wmi_stats_buf->status; + param->num_sp_cycles = wmi_stats_buf->num_sp_cycles; + param->avg_sp_dur_us = wmi_stats_buf->avg_sp_dur_us; + param->min_sp_dur_us = wmi_stats_buf->min_sp_dur_us; + param->max_sp_dur_us = wmi_stats_buf->max_sp_dur_us; + param->tx_mpdu_per_sp = wmi_stats_buf->tx_mpdu_per_sp; + param->rx_mpdu_per_sp = wmi_stats_buf->rx_mpdu_per_sp; + param->tx_bytes_per_sp = wmi_stats_buf->tx_bytes_per_sp; + param->rx_bytes_per_sp = wmi_stats_buf->rx_bytes_per_sp; + + wmi_debug("dialog_id = %u status = %u", wmi_stats_buf->dialog_id, + wmi_stats_buf->status); + wmi_debug("num_sp_cycles = %u avg_sp_dur_us = 0x%x, \ + min_sp_dur_us = 0x%x, max_sp_dur_us = 0x%x", + wmi_stats_buf->num_sp_cycles, wmi_stats_buf->avg_sp_dur_us, + wmi_stats_buf->min_sp_dur_us, wmi_stats_buf->max_sp_dur_us); + wmi_debug("tx_mpdu_per_sp 0x%x, rx_mpdu_per_sp = 0x%x, \ + tx_bytes_per_sp = 0x%x, rx_bytes_per_sp = 0x%x", + wmi_stats_buf->tx_mpdu_per_sp, wmi_stats_buf->rx_mpdu_per_sp, + wmi_stats_buf->tx_bytes_per_sp, + wmi_stats_buf->rx_bytes_per_sp); +} + +static void wmi_twt_extract_stats_struct(void *tag_buf, + struct infra_cp_stats_event *params) +{ + struct twt_infra_cp_stats_event *twt_params; + + twt_params = params->twt_infra_cp_stats + + params->num_twt_infra_cp_stats; + + wmi_debug("TWT stats struct found - num_twt_cp_stats %d", + params->num_twt_infra_cp_stats); + + params->num_twt_infra_cp_stats++; + wmi_extract_ctrl_path_twt_stats_tlv(tag_buf, twt_params); +} +#else +static void wmi_twt_extract_stats_struct(void *tag_buf, + struct infra_cp_stats_event *params) +{ +} +#endif + +/* + * wmi_stats_extract_tag_struct: function to extract tag structs + * @tag_type: tag type that is to be printed + * @tag_buf: pointer to the tag structure + * @params: buffer to hold parameters extracted from response event + * + * Return: None + */ +static void wmi_stats_extract_tag_struct(uint32_t tag_type, void *tag_buf, + struct infra_cp_stats_event *params) +{ + wmi_debug("tag_type %d", tag_type); + + switch (tag_type) { + case WMITLV_TAG_STRUC_wmi_ctrl_path_pdev_stats_struct: + break; + + case WMITLV_TAG_STRUC_wmi_ctrl_path_mem_stats_struct: + break; + + case WMITLV_TAG_STRUC_wmi_ctrl_path_twt_stats_struct: + wmi_twt_extract_stats_struct(tag_buf, params); + break; + + default: + break; + } +} + +/* + * wmi_stats_handler: parse the wmi event and fill the stats values + * @buff: Buffer containing wmi event + * @len: length of event buffer + * @params: buffer to hold parameters extracted from response event + * + * Return: QDF_STATUS_SUCCESS on success, else other qdf error values + */ +static QDF_STATUS wmi_stats_handler(void *buff, int32_t len, + struct infra_cp_stats_event *params) +{ + WMI_CTRL_PATH_STATS_EVENTID_param_tlvs *param_buf; + wmi_ctrl_path_stats_event_fixed_param *ev; + uint8_t *buf_ptr = (uint8_t *)buff; + uint32_t curr_tlv_tag; + uint32_t curr_tlv_len; + uint8_t *tag_start_ptr; + + param_buf = (WMI_CTRL_PATH_STATS_EVENTID_param_tlvs *)buff; + if (!param_buf) + return QDF_STATUS_E_FAILURE; + ev = (wmi_ctrl_path_stats_event_fixed_param *)param_buf->fixed_param; + + curr_tlv_tag = WMITLV_GET_TLVTAG(ev->tlv_header); + curr_tlv_len = WMITLV_GET_TLVLEN(ev->tlv_header); + buf_ptr = (uint8_t *)param_buf->fixed_param; + wmi_debug("Fixed param more %d req_id %d status %d", ev->more, + ev->request_id, ev->status); + params->request_id = ev->request_id; + params->status = ev->status; + + /* buffer should point to next TLV in event */ + buf_ptr += (curr_tlv_len + WMI_TLV_HDR_SIZE); + len -= (curr_tlv_len + WMI_TLV_HDR_SIZE); + + curr_tlv_tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(buf_ptr)); + curr_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr)); + + wmi_debug("curr_tlv_len %d curr_tlv_tag %d rem_len %d", len, + curr_tlv_len, curr_tlv_tag); + + while ((len >= curr_tlv_len) && + (curr_tlv_tag >= WMITLV_TAG_FIRST_ARRAY_ENUM)) { + if (curr_tlv_tag == WMITLV_TAG_ARRAY_STRUC) { + /* Move to next WMITLV_TAG_ARRAY_STRUC */ + buf_ptr += WMI_TLV_HDR_SIZE; + len -= WMI_TLV_HDR_SIZE; + if (len <= 0) + break; + } + curr_tlv_tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(buf_ptr)); + curr_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr)); + + wmi_debug("curr_tlv_len %d curr_tlv_tag %d rem_len %d", + len, curr_tlv_len, curr_tlv_tag); + if (curr_tlv_len) { + /* point to the tag inside WMITLV_TAG_ARRAY_STRUC */ + tag_start_ptr = buf_ptr + WMI_TLV_HDR_SIZE; + curr_tlv_tag = WMITLV_GET_TLVTAG( + WMITLV_GET_HDR(tag_start_ptr)); + wmi_stats_extract_tag_struct(curr_tlv_tag, + (void *)tag_start_ptr, + params); + } + /* Move to next tag */ + buf_ptr += curr_tlv_len + WMI_TLV_HDR_SIZE; + len -= (curr_tlv_len + WMI_TLV_HDR_SIZE); + + if (len <= 0) + break; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * extract_infra_cp_stats_tlv - api to extract stats information from + * event buffer + * @wmi_handle: wmi handle + * @evt_buf: event buffer + * @evt_buf_len: length of the event buffer + * @params: buffer to populate more flag + * + * Return: QDF_STATUS_SUCCESS on success, else other qdf error values + */ +static QDF_STATUS +extract_infra_cp_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t evt_buf_len, + struct infra_cp_stats_event *params) +{ + wmi_stats_handler(evt_buf, evt_buf_len, params); + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ + /** * extract_cp_stats_more_pending_tlv - api to extract more flag from event data * @wmi_handle: wmi handle @@ -14943,6 +15122,9 @@ struct wmi_ops tlv_ops = { .send_roam_scan_ch_list_req_cmd = send_roam_scan_ch_list_req_cmd_tlv, .send_injector_config_cmd = send_injector_config_cmd_tlv, .send_cp_stats_cmd = send_cp_stats_cmd_tlv, +#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS + .extract_infra_cp_stats = extract_infra_cp_stats_tlv, +#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ .extract_cp_stats_more_pending = extract_cp_stats_more_pending_tlv, .send_vdev_tsf_tstamp_action_cmd = send_vdev_tsf_tstamp_action_cmd_tlv,