1 /* 2 * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "osdep.h" 19 #include "wmi.h" 20 #include "wmi_unified_priv.h" 21 #include "wmi_unified_param.h" 22 #include "target_if_cp_stats.h" 23 #include <wlan_cp_stats_public_structs.h> 24 25 #if defined(WLAN_SUPPORT_INFRA_CTRL_PATH_STATS) || \ 26 defined(WLAN_TELEMETRY_STATS_SUPPORT) 27 /** 28 * get_infra_cp_stats_id() - convert from to wmi_ctrl_path_stats_id 29 * @type: type from enum infra_cp_stats_id 30 * 31 * Return: wmi_ctrl_path_stats_id code for success or -EINVAL 32 * for failure 33 */ 34 static uint32_t get_infra_cp_stats_id(enum infra_cp_stats_id type) 35 { 36 switch (type) { 37 case TYPE_REQ_CTRL_PATH_PDEV_TX_STAT: 38 return WMI_REQUEST_CTRL_PATH_PDEV_TX_STAT; 39 case TYPE_REQ_CTRL_PATH_VDEV_EXTD_STAT: 40 return WMI_REQUEST_CTRL_PATH_VDEV_EXTD_STAT; 41 case TYPE_REQ_CTRL_PATH_MEM_STAT: 42 return WMI_REQUEST_CTRL_PATH_MEM_STAT; 43 case TYPE_REQ_CTRL_PATH_TWT_STAT: 44 return WMI_REQUEST_CTRL_PATH_TWT_STAT; 45 case TYPE_REQ_CTRL_PATH_BMISS_STAT: 46 return WMI_REQUEST_CTRL_PATH_BMISS_STAT; 47 case TYPE_REQ_CTRL_PATH_PMLO_STAT: 48 return WMI_REQUEST_CTRL_PATH_PMLO_STAT; 49 default: 50 return -EINVAL; 51 } 52 } 53 54 /** 55 * get_infra_cp_stats_action() - convert action codes from 56 * enum infra_cp_stats_action to wmi_ctrl_path_stats_action 57 * @action: action code from enum infra_cp_stats_action 58 * 59 * Return: wmi_ctrl_path_stats_action code for success or -EINVAL 60 * for failure 61 */ 62 static uint32_t get_infra_cp_stats_action(enum infra_cp_stats_action action) 63 { 64 switch (action) { 65 case ACTION_REQ_CTRL_PATH_STAT_GET: 66 return WMI_REQUEST_CTRL_PATH_STAT_GET; 67 case ACTION_REQ_CTRL_PATH_STAT_RESET: 68 return WMI_REQUEST_CTRL_PATH_STAT_RESET; 69 case ACTION_REQ_CTRL_PATH_STAT_START: 70 return WMI_REQUEST_CTRL_PATH_STAT_START; 71 case ACTION_REQ_CTRL_PATH_STAT_STOP: 72 return WMI_REQUEST_CTRL_PATH_STAT_STOP; 73 case ACTION_REQ_CTRL_PATH_STAT_PERIODIC_PUBLISH: 74 return WMI_REQUEST_CTRL_PATH_STAT_PERIODIC_PUBLISH; 75 default: 76 return -EINVAL; 77 } 78 } 79 80 #ifdef WLAN_SUPPORT_TWT 81 static uint32_t 82 get_stats_req_twt_dialog_id(struct infra_cp_stats_cmd_info *req) 83 { 84 return req->dialog_id; 85 } 86 87 static enum WMI_HOST_GET_STATS_TWT_STATUS 88 wmi_get_converted_twt_get_stats_status(WMI_GET_STATS_TWT_STATUS_T tgt_status) 89 { 90 switch (tgt_status) { 91 case WMI_GET_STATS_TWT_STATUS_OK: 92 return WMI_HOST_GET_STATS_TWT_STATUS_OK; 93 case WMI_GET_STATS_TWT_STATUS_DIALOG_ID_NOT_EXIST: 94 return WMI_HOST_GET_STATS_TWT_STATUS_DIALOG_ID_NOT_EXIST; 95 case WMI_GET_STATS_TWT_STATUS_INVALID_PARAM: 96 return WMI_HOST_GET_STATS_TWT_STATUS_INVALID_PARAM; 97 default: 98 return WMI_HOST_GET_STATS_TWT_STATUS_UNKNOWN_ERROR; 99 } 100 } 101 102 static inline 103 void wmi_extract_ctrl_path_twt_stats_tlv(void *tag_buf, 104 struct twt_infra_cp_stats_event *param) 105 { 106 wmi_ctrl_path_twt_stats_struct *wmi_stats_buf = 107 (wmi_ctrl_path_twt_stats_struct *)tag_buf; 108 109 param->dialog_id = wmi_stats_buf->dialog_id; 110 param->status = wmi_get_converted_twt_get_stats_status(wmi_stats_buf->status); 111 param->num_sp_cycles = wmi_stats_buf->num_sp_cycles; 112 param->avg_sp_dur_us = wmi_stats_buf->avg_sp_dur_us; 113 param->min_sp_dur_us = wmi_stats_buf->min_sp_dur_us; 114 param->max_sp_dur_us = wmi_stats_buf->max_sp_dur_us; 115 param->tx_mpdu_per_sp = wmi_stats_buf->tx_mpdu_per_sp; 116 param->rx_mpdu_per_sp = wmi_stats_buf->rx_mpdu_per_sp; 117 param->tx_bytes_per_sp = wmi_stats_buf->tx_bytes_per_sp; 118 param->rx_bytes_per_sp = wmi_stats_buf->rx_bytes_per_sp; 119 120 wmi_debug("dialog_id = %u status = %u", wmi_stats_buf->dialog_id, 121 wmi_stats_buf->status); 122 wmi_debug("num_sp_cycles = %u avg_sp_dur_us = 0x%x, \ 123 min_sp_dur_us = 0x%x, max_sp_dur_us = 0x%x", 124 wmi_stats_buf->num_sp_cycles, wmi_stats_buf->avg_sp_dur_us, 125 wmi_stats_buf->min_sp_dur_us, wmi_stats_buf->max_sp_dur_us); 126 wmi_debug("tx_mpdu_per_sp 0x%x, rx_mpdu_per_sp = 0x%x, \ 127 tx_bytes_per_sp = 0x%x, rx_bytes_per_sp = 0x%x", 128 wmi_stats_buf->tx_mpdu_per_sp, wmi_stats_buf->rx_mpdu_per_sp, 129 wmi_stats_buf->tx_bytes_per_sp, 130 wmi_stats_buf->rx_bytes_per_sp); 131 } 132 133 static void wmi_twt_extract_stats_struct(void *tag_buf, 134 struct infra_cp_stats_event *params) 135 { 136 struct twt_infra_cp_stats_event *twt_params; 137 138 twt_params = params->twt_infra_cp_stats + 139 params->num_twt_infra_cp_stats; 140 141 wmi_debug("TWT stats struct found - num_twt_cp_stats %d", 142 params->num_twt_infra_cp_stats); 143 144 params->num_twt_infra_cp_stats++; 145 wmi_extract_ctrl_path_twt_stats_tlv(tag_buf, twt_params); 146 } 147 #else 148 static inline 149 uint32_t get_stats_req_twt_dialog_id(struct infra_cp_stats_cmd_info *req) 150 { 151 return 0; 152 } 153 154 static void wmi_twt_extract_stats_struct(void *tag_buf, 155 struct infra_cp_stats_event *params) 156 { 157 } 158 #endif /* WLAN_SUPPORT_TWT */ 159 160 #ifdef CONFIG_WLAN_BMISS 161 static void 162 wmi_extract_ctrl_path_bmiss_stats_tlv(void *tag_buf, 163 struct bmiss_infra_cp_stats_event *param) 164 { 165 int idx = 0; 166 167 wmi_ctrl_path_bmiss_stats_struct *wmi_stats_buf = 168 (wmi_ctrl_path_bmiss_stats_struct *)tag_buf; 169 param->num_pre_bmiss = wmi_stats_buf->num_pre_bmiss; 170 for (idx = 0; idx < BMISS_STATS_RSSI_SAMPLES_MAX; idx++) { 171 param->rssi_samples[idx].rssi = 172 wmi_stats_buf->rssi_samples[idx].rssi; 173 param->rssi_samples[idx].sample_time = 174 wmi_stats_buf->rssi_samples[idx].sample_time; 175 } 176 param->rssi_sample_curr_index = wmi_stats_buf->rssi_sample_curr_index; 177 param->num_first_bmiss = wmi_stats_buf->num_first_bmiss; 178 param->num_final_bmiss = wmi_stats_buf->num_final_bmiss; 179 param->num_null_sent_in_first_bmiss = 180 wmi_stats_buf->num_null_sent_in_first_bmiss; 181 param->num_null_failed_in_first_bmiss = 182 wmi_stats_buf->num_null_failed_in_first_bmiss; 183 param->num_null_failed_in_final_bmiss = 184 wmi_stats_buf->num_null_failed_in_final_bmiss; 185 param->cons_bmiss_stats.num_of_bmiss_sequences = 186 wmi_stats_buf->cons_bmiss_stats.num_of_bmiss_sequences; 187 param->cons_bmiss_stats.num_bitmask_wraparound = 188 wmi_stats_buf->cons_bmiss_stats.num_bitmask_wraparound; 189 param->cons_bmiss_stats.num_bcn_hist_lost = 190 wmi_stats_buf->cons_bmiss_stats.num_bcn_hist_lost; 191 wmi_debug("num_pre_bmiss = %u", wmi_stats_buf->num_pre_bmiss); 192 wmi_debug("num_first_bmiss = %u num_final_bmiss = %u, num_null_sent_in_first_bmiss = %u, num_null_failed_in_first_bmiss = %u", 193 wmi_stats_buf->num_first_bmiss, 194 wmi_stats_buf->num_final_bmiss, 195 wmi_stats_buf->num_null_sent_in_first_bmiss, 196 wmi_stats_buf->num_null_failed_in_first_bmiss); 197 wmi_debug("num_null_sent_in_final_bmiss %u null_fail_cnt_final_bmiss = %u rssi_sample_curr_index = %u", 198 wmi_stats_buf->num_null_sent_in_final_bmiss, 199 wmi_stats_buf->num_null_failed_in_final_bmiss, 200 wmi_stats_buf->rssi_sample_curr_index); 201 for (idx = 0; idx < BMISS_STATS_RSSI_SAMPLES_MAX; idx++) { 202 wmi_debug("rssi_sample-%u: rssi=%u", idx, 203 wmi_stats_buf->rssi_samples[idx].rssi); 204 wmi_debug("rssi_sample-%u: sampletime=%u", idx, 205 wmi_stats_buf->rssi_samples[idx].sample_time); 206 } 207 wmi_debug("num_of_bmiss_sequences %u num_bitmask_wraparound = %u num_bcn_hist_lost = %u", 208 wmi_stats_buf->cons_bmiss_stats.num_of_bmiss_sequences, 209 wmi_stats_buf->cons_bmiss_stats.num_bitmask_wraparound, 210 wmi_stats_buf->cons_bmiss_stats.num_bcn_hist_lost); 211 } 212 213 static void wmi_bmiss_extract_stats_struct(void *tag_buf, 214 struct infra_cp_stats_event *params) 215 { 216 struct bmiss_infra_cp_stats_event *bmiss_params; 217 218 bmiss_params = params->bmiss_infra_cp_stats; 219 wmi_debug("BMISS stats struct found"); 220 wmi_extract_ctrl_path_bmiss_stats_tlv(tag_buf, bmiss_params); 221 } 222 223 #else /* CONFIG_WLAN_BMISS */ 224 static inline 225 void wmi_bmiss_extract_stats_struct(void *tag_buf, 226 struct infra_cp_stats_event *params) 227 228 { 229 } 230 231 #endif/* CONFIG_WLAN_BMISS */ 232 233 #ifdef WLAN_TELEMETRY_STATS_SUPPORT 234 static void 235 wmi_extract_ctrl_path_pmlo_stats_tlv(wmi_unified_t wmi_handle, void *tag_buf, 236 struct ctrl_path_pmlo_telemetry_stats_struct *param) 237 { 238 int idx = 0; 239 wmi_ctrl_path_pmlo_stats_struct *wmi_stats_buf = tag_buf; 240 241 param->pdev_id = 242 wmi_handle->ops->convert_target_pdev_id_to_host(wmi_handle, 243 wmi_stats_buf->pdev_id); 244 param->dl_inbss_airtime_ac_be = 245 WMI_PMLO_UL_DL_INBSS_AT_GET_BE(wmi_stats_buf->dl_inbss_airtime_per_ac); 246 param->dl_inbss_airtime_ac_bk = 247 WMI_PMLO_UL_DL_INBSS_AT_GET_BK(wmi_stats_buf->dl_inbss_airtime_per_ac); 248 param->dl_inbss_airtime_ac_vi = 249 WMI_PMLO_UL_DL_INBSS_AT_GET_VI(wmi_stats_buf->dl_inbss_airtime_per_ac); 250 param->dl_inbss_airtime_ac_vo = 251 WMI_PMLO_UL_DL_INBSS_AT_GET_VO(wmi_stats_buf->dl_inbss_airtime_per_ac); 252 param->ul_inbss_airtime_ac_be = 253 WMI_PMLO_UL_DL_INBSS_AT_GET_BE(wmi_stats_buf->ul_inbss_airtime_per_ac); 254 param->ul_inbss_airtime_ac_bk = 255 WMI_PMLO_UL_DL_INBSS_AT_GET_BK(wmi_stats_buf->ul_inbss_airtime_per_ac); 256 param->ul_inbss_airtime_ac_vi = 257 WMI_PMLO_UL_DL_INBSS_AT_GET_VI(wmi_stats_buf->ul_inbss_airtime_per_ac); 258 param->ul_inbss_airtime_ac_vo = 259 WMI_PMLO_UL_DL_INBSS_AT_GET_VO(wmi_stats_buf->ul_inbss_airtime_per_ac); 260 param->estimated_air_time_ac_be = 261 WMI_PMLO_UL_DL_INBSS_AT_GET_BE(wmi_stats_buf->estimated_air_time_per_ac); 262 param->estimated_air_time_ac_bk = 263 WMI_PMLO_UL_DL_INBSS_AT_GET_BK(wmi_stats_buf->estimated_air_time_per_ac); 264 param->estimated_air_time_ac_vi = 265 WMI_PMLO_UL_DL_INBSS_AT_GET_VI(wmi_stats_buf->estimated_air_time_per_ac); 266 param->estimated_air_time_ac_vo = 267 WMI_PMLO_UL_DL_INBSS_AT_GET_VO(wmi_stats_buf->estimated_air_time_per_ac); 268 param->link_obss_airtime = 269 WMI_PMLO_LINK_OBSS_AT_GET(wmi_stats_buf->ul_dl_obss_free_aa_word32); 270 param->link_idle_airtime = 271 WMI_PMLO_LINK_AA_GET(wmi_stats_buf->ul_dl_obss_free_aa_word32); 272 param->ul_inbss_airtime_non_ac = 273 WMI_PMLO_UL_AIRTIME_NON_AC_GET(wmi_stats_buf->ul_dl_obss_free_aa_word32); 274 param->dl_inbss_airtime_non_ac = 275 WMI_PMLO_DL_AIRTIME_NON_AC_GET(wmi_stats_buf->ul_dl_obss_free_aa_word32); 276 for (idx = 0; idx < WMI_AC_MAX; idx++) { 277 param->avg_chan_lat_per_ac[idx] = 278 wmi_stats_buf->avg_chan_lat_per_ac[idx]; 279 } 280 281 wmi_debug("pdev_id = %u", wmi_stats_buf->pdev_id); 282 wmi_debug("dl_inbss_airtime_per_ac = %u, ul_inbss_airtime_per_ac = %u, estimated_air_time_per_ac = %u, ul_dl_obss_free_aa_word32 = %u", 283 wmi_stats_buf->dl_inbss_airtime_per_ac, 284 wmi_stats_buf->ul_inbss_airtime_per_ac, 285 wmi_stats_buf->estimated_air_time_per_ac, 286 wmi_stats_buf->ul_dl_obss_free_aa_word32); 287 288 for (idx = 0; idx < WMI_AC_MAX; idx++) { 289 wmi_debug("avg_chan_lat_per_ac_sample-%u: avg_chan_lat_per_ac=%u", 290 idx, 291 wmi_stats_buf->avg_chan_lat_per_ac[idx]); 292 } 293 } 294 295 static void wmi_pmlo_extract_stats_struct(wmi_unified_t wmi_handle, 296 void *tag_buf, 297 struct infra_cp_stats_event *params) 298 { 299 struct ctrl_path_pmlo_telemetry_stats_struct *pmlo_params; 300 301 pmlo_params = params->telemetry_stats; 302 wmi_debug("PMLO TELEMETRY stats struct found"); 303 wmi_extract_ctrl_path_pmlo_stats_tlv(wmi_handle, tag_buf, pmlo_params); 304 } 305 #else 306 static void wmi_pmlo_extract_stats_struct(wmi_unified_t wmi_handle, 307 void *tag_buf, 308 struct infra_cp_stats_event *params) 309 { } 310 #endif 311 312 /** 313 * wmi_stats_extract_tag_struct: function to extract tag structs 314 * @wmi_handle: wmi handle 315 * @tag_type: tag type that is to be printed 316 * @tag_buf: pointer to the tag structure 317 * @params: buffer to hold parameters extracted from response event 318 * 319 * Return: None 320 */ 321 static void wmi_stats_extract_tag_struct(wmi_unified_t wmi_handle, 322 uint32_t tag_type, void *tag_buf, 323 struct infra_cp_stats_event *params) 324 { 325 wmi_debug("tag_type %d", tag_type); 326 327 switch (tag_type) { 328 case WMITLV_TAG_STRUC_wmi_ctrl_path_pdev_stats_struct: 329 break; 330 331 case WMITLV_TAG_STRUC_wmi_ctrl_path_mem_stats_struct: 332 break; 333 334 case WMITLV_TAG_STRUC_wmi_ctrl_path_twt_stats_struct: 335 wmi_twt_extract_stats_struct(tag_buf, params); 336 break; 337 338 case WMITLV_TAG_STRUC_wmi_ctrl_path_bmiss_stats_struct: 339 wmi_bmiss_extract_stats_struct(tag_buf, params); 340 break; 341 342 case WMITLV_TAG_STRUC_wmi_ctrl_path_pmlo_stats_struct: 343 wmi_pmlo_extract_stats_struct(wmi_handle, tag_buf, params); 344 break; 345 346 default: 347 break; 348 } 349 } 350 351 QDF_STATUS wmi_stats_handler(wmi_unified_t wmi_handle, void *buff, int32_t len, 352 struct infra_cp_stats_event *params) 353 { 354 WMI_CTRL_PATH_STATS_EVENTID_param_tlvs *param_buf; 355 wmi_ctrl_path_stats_event_fixed_param *ev; 356 uint8_t *buf_ptr = (uint8_t *)buff; 357 uint32_t curr_tlv_tag; 358 uint32_t curr_tlv_len; 359 uint8_t *tag_start_ptr; 360 361 param_buf = (WMI_CTRL_PATH_STATS_EVENTID_param_tlvs *)buff; 362 if (!param_buf) { 363 wmi_err_rl("param_buf is NULL"); 364 return QDF_STATUS_E_FAILURE; 365 } 366 ev = (wmi_ctrl_path_stats_event_fixed_param *)param_buf->fixed_param; 367 368 curr_tlv_tag = WMITLV_GET_TLVTAG(ev->tlv_header); 369 curr_tlv_len = WMITLV_GET_TLVLEN(ev->tlv_header); 370 buf_ptr = (uint8_t *)param_buf->fixed_param; 371 wmi_debug("Fixed param more %d req_id %d status %d", ev->more, 372 ev->request_id, ev->status); 373 params->request_id = ev->request_id; 374 params->status = ev->status; 375 376 /* buffer should point to next TLV in event */ 377 buf_ptr += (curr_tlv_len + WMI_TLV_HDR_SIZE); 378 len -= (curr_tlv_len + WMI_TLV_HDR_SIZE); 379 380 curr_tlv_tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(buf_ptr)); 381 curr_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr)); 382 383 wmi_debug("curr_tlv_len %d curr_tlv_tag %d rem_len %d", len, 384 curr_tlv_len, curr_tlv_tag); 385 386 while ((len >= curr_tlv_len) && 387 (curr_tlv_tag >= WMITLV_TAG_FIRST_ARRAY_ENUM)) { 388 if (curr_tlv_tag == WMITLV_TAG_ARRAY_STRUC) { 389 /* Move to next WMITLV_TAG_ARRAY_STRUC */ 390 buf_ptr += WMI_TLV_HDR_SIZE; 391 len -= WMI_TLV_HDR_SIZE; 392 if (len <= 0) 393 break; 394 } 395 curr_tlv_tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(buf_ptr)); 396 curr_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr)); 397 398 wmi_debug("curr_tlv_len %d curr_tlv_tag %d rem_len %d", 399 len, curr_tlv_len, curr_tlv_tag); 400 if (curr_tlv_len) { 401 /* point to the tag inside WMITLV_TAG_ARRAY_STRUC */ 402 tag_start_ptr = buf_ptr + WMI_TLV_HDR_SIZE; 403 curr_tlv_tag = WMITLV_GET_TLVTAG( 404 WMITLV_GET_HDR(tag_start_ptr)); 405 wmi_stats_extract_tag_struct(wmi_handle, curr_tlv_tag, 406 (void *)tag_start_ptr, 407 params); 408 /* Move to next tag */ 409 buf_ptr += curr_tlv_len + WMI_TLV_HDR_SIZE; 410 len -= (curr_tlv_len + WMI_TLV_HDR_SIZE); 411 } 412 if (len <= 0) 413 break; 414 } 415 416 return QDF_STATUS_SUCCESS; 417 } 418 419 /** 420 * extract_infra_cp_stats_tlv - api to extract stats information from 421 * event buffer 422 * @wmi_handle: wmi handle 423 * @evt_buf: event buffer 424 * @evt_buf_len: length of the event buffer 425 * @params: buffer to populate more flag 426 * 427 * Return: QDF_STATUS_SUCCESS on success, else other qdf error values 428 */ 429 QDF_STATUS 430 extract_infra_cp_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, 431 uint32_t evt_buf_len, 432 struct infra_cp_stats_event *params) 433 { 434 wmi_stats_handler(wmi_handle, evt_buf, evt_buf_len, params); 435 return QDF_STATUS_SUCCESS; 436 } 437 438 /** 439 * prepare_infra_cp_stats_buf() - Allocate and prepate wmi cmd request buffer 440 * @wmi_handle: wmi handle 441 * @stats_req: Request parameters to be filled in wmi cmd request buffer 442 * @req_buf_len: length of the output wmi cmd buffer allocated 443 * 444 * Return: Valid wmi buffer pointer on success and NULL pointer for failure 445 */ 446 static wmi_buf_t 447 prepare_infra_cp_stats_buf(wmi_unified_t wmi_handle, 448 struct infra_cp_stats_cmd_info *stats_req, 449 uint32_t *req_buf_len) 450 { 451 wmi_request_ctrl_path_stats_cmd_fixed_param *cmd_fixed_param; 452 uint32_t index; 453 wmi_buf_t req_buf; 454 uint8_t *buf_ptr; 455 uint32_t *pdev_id_array; 456 uint32_t *vdev_id_array; 457 uint8_t *mac_addr_array; 458 uint32_t *dialog_id_array; 459 uint32_t num_pdev_ids = stats_req->num_pdev_ids; 460 uint32_t num_vdev_ids = stats_req->num_vdev_ids; 461 uint32_t num_mac_addr_list = stats_req->num_mac_addr_list; 462 uint32_t num_dialog_ids = INFRA_CP_STATS_MAX_REQ_TWT_DIALOG_ID; 463 464 /* Calculate total buffer length */ 465 *req_buf_len = (sizeof(wmi_request_ctrl_path_stats_cmd_fixed_param) + 466 WMI_TLV_HDR_SIZE + (sizeof(A_UINT32) * (num_pdev_ids)) + 467 WMI_TLV_HDR_SIZE + sizeof(A_UINT32) * (num_vdev_ids) + 468 WMI_TLV_HDR_SIZE + 469 sizeof(wmi_mac_addr) * (num_mac_addr_list) + 470 WMI_TLV_HDR_SIZE + 471 (sizeof(A_UINT32) * (num_dialog_ids))); 472 req_buf = wmi_buf_alloc(wmi_handle, *req_buf_len); 473 if (!req_buf) 474 return NULL; 475 476 cmd_fixed_param = (wmi_request_ctrl_path_stats_cmd_fixed_param *) 477 wmi_buf_data(req_buf); 478 479 /*Set TLV header*/ 480 WMITLV_SET_HDR(&cmd_fixed_param->tlv_header, 481 WMITLV_TAG_STRUC_wmi_request_ctrl_path_stats_cmd_fixed_param, 482 WMITLV_GET_STRUCT_TLVLEN( 483 wmi_request_ctrl_path_stats_cmd_fixed_param)); 484 485 index = get_infra_cp_stats_id(stats_req->stats_id); 486 cmd_fixed_param->stats_id_mask = (1 << index); 487 488 cmd_fixed_param->request_id = stats_req->request_id; 489 cmd_fixed_param->action = get_infra_cp_stats_action(stats_req->action); 490 cmd_fixed_param->stat_periodicity = stats_req->stat_periodicity; 491 492 buf_ptr = (uint8_t *)cmd_fixed_param; 493 /* Setting tlv header for pdev id arrays*/ 494 buf_ptr = buf_ptr + sizeof(*cmd_fixed_param); 495 pdev_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); 496 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 497 sizeof(A_UINT32) * num_pdev_ids); 498 499 /* Setting tlv header for vdev id arrays*/ 500 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE + 501 (sizeof(A_UINT32) * num_pdev_ids); 502 vdev_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); 503 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 504 sizeof(A_UINT32) * num_vdev_ids); 505 506 /* Setting tlv header for mac addr arrays*/ 507 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE + 508 (sizeof(A_UINT32) * num_vdev_ids); 509 mac_addr_array = buf_ptr + WMI_TLV_HDR_SIZE; 510 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, 511 sizeof(wmi_mac_addr) * num_mac_addr_list); 512 513 /* Setting tlv header for dialog id arrays*/ 514 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE + 515 sizeof(wmi_mac_addr) * num_mac_addr_list; 516 dialog_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); 517 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 518 sizeof(A_UINT32) * num_dialog_ids); 519 520 for (index = 0; index < num_pdev_ids; index++) { 521 pdev_id_array[index] = 522 wmi_handle->ops->convert_pdev_id_host_to_target( 523 wmi_handle, 524 stats_req->pdev_id[index]); 525 } 526 527 for (index = 0; index < num_vdev_ids; index++) 528 vdev_id_array[index] = stats_req->vdev_id[index]; 529 530 for (index = 0; index < num_mac_addr_list; index++) { 531 qdf_mem_copy(mac_addr_array, stats_req->peer_mac_addr[index], 532 QDF_MAC_ADDR_SIZE); 533 mac_addr_array += QDF_MAC_ADDR_SIZE; 534 } 535 536 dialog_id_array[0] = get_stats_req_twt_dialog_id(stats_req); 537 538 wmi_debug("stats_id_mask 0x%x action 0x%x dialog_id %d", 539 cmd_fixed_param->stats_id_mask, cmd_fixed_param->action, 540 dialog_id_array[0]); 541 wmi_debug("num_pdev_ids %d num_vdev_ids %d num_dialog_ids %d \ 542 num_mac_addr %d", num_pdev_ids, num_vdev_ids, 543 num_dialog_ids, num_mac_addr_list); 544 545 return req_buf; 546 } 547 548 /** 549 * send_infra_cp_stats_request_cmd_tlv() - Prepare and send infra_cp_stats 550 * wmi cmd to firmware 551 * @wmi_handle: wmi handle 552 * @param: Pointer to request structure 553 * 554 * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes 555 * on failure 556 */ 557 static QDF_STATUS 558 send_infra_cp_stats_request_cmd_tlv(wmi_unified_t wmi_handle, 559 struct infra_cp_stats_cmd_info *param) 560 { 561 uint32_t len; 562 wmi_buf_t buf; 563 QDF_STATUS status; 564 565 buf = prepare_infra_cp_stats_buf(wmi_handle, param, &len); 566 if (!buf) 567 return QDF_STATUS_E_NOMEM; 568 569 wmi_debug("buf_len %d", len); 570 571 wmi_mtrace(WMI_REQUEST_CTRL_PATH_STATS_CMDID, NO_SESSION, 0); 572 status = wmi_unified_cmd_send(wmi_handle, buf, 573 len, WMI_REQUEST_CTRL_PATH_STATS_CMDID); 574 575 if (QDF_IS_STATUS_ERROR(status)) { 576 wmi_buf_free(buf); 577 return QDF_STATUS_E_FAILURE; 578 } 579 580 return QDF_STATUS_SUCCESS; 581 } 582 #else 583 static inline QDF_STATUS 584 send_infra_cp_stats_request_cmd_tlv(wmi_unified_t wmi_handle, 585 struct infra_cp_stats_cmd_info *param) 586 { 587 return QDF_STATUS_SUCCESS; 588 } 589 #endif 590 591 #ifdef QCA_WIFI_EMULATION 592 /** 593 * send_stats_request_cmd_tlv() - WMI request stats function 594 * @wmi_handle: handle to WMI. 595 * @macaddr: MAC address 596 * @param: pointer to hold stats request parameter 597 * 598 * Return: QDF_STATUS on success, else failure. 599 */ 600 static QDF_STATUS 601 send_stats_request_cmd_tlv(wmi_unified_t wmi_handle, 602 uint8_t macaddr[QDF_MAC_ADDR_SIZE], 603 struct stats_request_params *param) 604 { 605 return QDF_STATUS_SUCCESS; 606 } 607 #else 608 static QDF_STATUS 609 send_stats_request_cmd_tlv(wmi_unified_t wmi_handle, 610 uint8_t macaddr[QDF_MAC_ADDR_SIZE], 611 struct stats_request_params *param) 612 { 613 int32_t ret; 614 wmi_request_stats_cmd_fixed_param *cmd; 615 wmi_buf_t buf; 616 uint16_t len = sizeof(wmi_request_stats_cmd_fixed_param); 617 bool is_qmi_send_support; 618 619 buf = wmi_buf_alloc(wmi_handle, len); 620 if (!buf) 621 return QDF_STATUS_E_NOMEM; 622 623 cmd = (wmi_request_stats_cmd_fixed_param *) wmi_buf_data(buf); 624 WMITLV_SET_HDR(&cmd->tlv_header, 625 WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, 626 WMITLV_GET_STRUCT_TLVLEN 627 (wmi_request_stats_cmd_fixed_param)); 628 cmd->stats_id = param->stats_id; 629 cmd->vdev_id = param->vdev_id; 630 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target( 631 wmi_handle, 632 param->pdev_id); 633 is_qmi_send_support = param->is_qmi_send_support; 634 635 WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->peer_macaddr); 636 637 wmi_debug("STATS REQ STATS_ID:%d VDEV_ID:%d PDEV_ID:%d, is_qmi_send_support %d", 638 cmd->stats_id, cmd->vdev_id, cmd->pdev_id, 639 is_qmi_send_support); 640 641 wmi_mtrace(WMI_REQUEST_STATS_CMDID, cmd->vdev_id, 0); 642 ret = wmi_unified_cmd_send_pm_chk(wmi_handle, buf, len, 643 WMI_REQUEST_STATS_CMDID, 644 is_qmi_send_support); 645 646 if (ret) { 647 wmi_err("Failed to send stats request to fw =%d", ret); 648 wmi_buf_free(buf); 649 } 650 651 return qdf_status_from_os_return(ret); 652 } 653 #endif 654 655 #ifdef WLAN_FEATURE_BIG_DATA_STATS 656 /** 657 * send_big_data_stats_request_cmd_tlv () - send big data stats cmd 658 * @wmi_handle: wmi handle 659 * @param: pointer to command request param 660 * 661 * Return: QDF_STATUS_SUCCESS for success or error code 662 */ 663 static QDF_STATUS 664 send_big_data_stats_request_cmd_tlv(wmi_unified_t wmi_handle, 665 struct stats_request_params *param) 666 { 667 int32_t ret = 0; 668 wmi_vdev_get_big_data_p2_cmd_fixed_param *cmd; 669 wmi_buf_t buf; 670 uint16_t len = sizeof(wmi_vdev_get_big_data_p2_cmd_fixed_param); 671 672 buf = wmi_buf_alloc(wmi_handle, len); 673 if (!buf) 674 return QDF_STATUS_E_NOMEM; 675 676 cmd = (wmi_vdev_get_big_data_p2_cmd_fixed_param *)wmi_buf_data(buf); 677 WMITLV_SET_HDR( 678 &cmd->tlv_header, 679 WMITLV_TAG_STRUC_wmi_vdev_get_big_data_p2_cmd_fixed_param, 680 WMITLV_GET_STRUCT_TLVLEN 681 (wmi_vdev_get_big_data_p2_cmd_fixed_param)); 682 683 cmd->vdev_id = param->vdev_id; 684 685 wmi_debug("STATS VDEV_ID:%d -->", cmd->vdev_id); 686 687 wmi_mtrace(WMI_VDEV_GET_BIG_DATA_P2_CMDID, cmd->vdev_id, 0); 688 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 689 WMI_VDEV_GET_BIG_DATA_P2_CMDID); 690 691 if (ret) { 692 wmi_err("Failed to send big data stats request to fw =%d", ret); 693 wmi_buf_free(buf); 694 } 695 696 return qdf_status_from_os_return(ret); 697 } 698 #endif 699 700 /** 701 * extract_all_stats_counts_tlv() - extract all stats count from event 702 * @wmi_handle: wmi handle 703 * @evt_buf: pointer to event buffer 704 * @stats_param: Pointer to hold stats count 705 * 706 * Return: QDF_STATUS_SUCCESS for success or error code 707 */ 708 static QDF_STATUS 709 extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, void *evt_buf, 710 wmi_host_stats_event *stats_param) 711 { 712 wmi_stats_event_fixed_param *ev; 713 wmi_per_chain_rssi_stats *rssi_event; 714 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 715 uint64_t min_data_len; 716 uint32_t i; 717 718 qdf_mem_zero(stats_param, sizeof(*stats_param)); 719 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; 720 ev = (wmi_stats_event_fixed_param *) param_buf->fixed_param; 721 rssi_event = param_buf->chain_stats; 722 if (!ev) { 723 wmi_err("event fixed param NULL"); 724 return QDF_STATUS_E_FAILURE; 725 } 726 727 if (param_buf->num_data > WMI_SVC_MSG_MAX_SIZE - sizeof(*ev)) { 728 wmi_err("num_data : %u is invalid", param_buf->num_data); 729 return QDF_STATUS_E_FAULT; 730 } 731 732 for (i = 1; i <= WMI_REQUEST_PDEV_TELEMETRY_STAT; i = i << 1) { 733 switch (ev->stats_id & i) { 734 case WMI_REQUEST_PEER_STAT: 735 stats_param->stats_id |= WMI_HOST_REQUEST_PEER_STAT; 736 break; 737 738 case WMI_REQUEST_AP_STAT: 739 stats_param->stats_id |= WMI_HOST_REQUEST_AP_STAT; 740 break; 741 742 case WMI_REQUEST_PDEV_STAT: 743 stats_param->stats_id |= WMI_HOST_REQUEST_PDEV_STAT; 744 break; 745 746 case WMI_REQUEST_VDEV_STAT: 747 stats_param->stats_id |= WMI_HOST_REQUEST_VDEV_STAT; 748 break; 749 750 case WMI_REQUEST_BCNFLT_STAT: 751 stats_param->stats_id |= WMI_HOST_REQUEST_BCNFLT_STAT; 752 break; 753 754 case WMI_REQUEST_VDEV_RATE_STAT: 755 stats_param->stats_id |= 756 WMI_HOST_REQUEST_VDEV_RATE_STAT; 757 break; 758 759 case WMI_REQUEST_BCN_STAT: 760 stats_param->stats_id |= WMI_HOST_REQUEST_BCN_STAT; 761 break; 762 case WMI_REQUEST_PEER_EXTD_STAT: 763 stats_param->stats_id |= WMI_REQUEST_PEER_EXTD_STAT; 764 break; 765 766 case WMI_REQUEST_PEER_EXTD2_STAT: 767 stats_param->stats_id |= 768 WMI_HOST_REQUEST_PEER_ADV_STATS; 769 break; 770 771 case WMI_REQUEST_PMF_BCN_PROTECT_STAT: 772 stats_param->stats_id |= 773 WMI_HOST_REQUEST_PMF_BCN_PROTECT_STAT; 774 break; 775 776 case WMI_REQUEST_VDEV_EXTD_STAT: 777 stats_param->stats_id |= 778 WMI_HOST_REQUEST_VDEV_PRB_FILS_STAT; 779 break; 780 781 case WMI_REQUEST_PDEV_EXTD_STAT: 782 stats_param->stats_id |= 783 WMI_HOST_REQUEST_PDEV_EXTD_STAT; 784 break; 785 786 case WMI_REQUEST_PDEV_TELEMETRY_STAT: 787 stats_param->stats_id |= 788 WMI_HOST_REQUEST_PDEV_TELEMETRY_STAT; 789 break; 790 } 791 } 792 793 /* ev->num_*_stats may cause uint32_t overflow, so use uint64_t 794 * to save total length calculated 795 */ 796 min_data_len = 797 (((uint64_t)ev->num_pdev_stats) * sizeof(wmi_pdev_stats)) + 798 (((uint64_t)ev->num_vdev_stats) * sizeof(wmi_vdev_stats)) + 799 (((uint64_t)ev->num_peer_stats) * sizeof(wmi_peer_stats)) + 800 (((uint64_t)ev->num_bcnflt_stats) * 801 sizeof(wmi_bcnfilter_stats_t)) + 802 (((uint64_t)ev->num_chan_stats) * sizeof(wmi_chan_stats)) + 803 (((uint64_t)ev->num_mib_stats) * sizeof(wmi_mib_stats)) + 804 (((uint64_t)ev->num_bcn_stats) * sizeof(wmi_bcn_stats)) + 805 (((uint64_t)ev->num_peer_extd_stats) * 806 sizeof(wmi_peer_extd_stats)) + 807 (((uint64_t)ev->num_mib_extd_stats) * 808 sizeof(wmi_mib_extd_stats)); 809 if (param_buf->num_data != min_data_len) { 810 wmi_err("data len: %u isn't same as calculated: %llu", 811 param_buf->num_data, min_data_len); 812 return QDF_STATUS_E_FAULT; 813 } 814 815 stats_param->last_event = ev->last_event; 816 stats_param->num_pdev_stats = ev->num_pdev_stats; 817 stats_param->num_pdev_ext_stats = param_buf->num_pdev_extd_stats; 818 stats_param->num_vdev_stats = ev->num_vdev_stats; 819 stats_param->num_peer_stats = ev->num_peer_stats; 820 stats_param->num_peer_extd_stats = ev->num_peer_extd_stats; 821 stats_param->num_bcnflt_stats = ev->num_bcnflt_stats; 822 stats_param->num_chan_stats = ev->num_chan_stats; 823 stats_param->num_mib_stats = ev->num_mib_stats; 824 stats_param->num_mib_extd_stats = ev->num_mib_extd_stats; 825 stats_param->num_bcn_stats = ev->num_bcn_stats; 826 stats_param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host( 827 wmi_handle, 828 ev->pdev_id); 829 830 /* if chain_stats is not populated */ 831 if (!param_buf->chain_stats || !param_buf->num_chain_stats) 832 return QDF_STATUS_SUCCESS; 833 834 if (WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats != 835 WMITLV_GET_TLVTAG(rssi_event->tlv_header)) 836 return QDF_STATUS_SUCCESS; 837 838 if (WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats) != 839 WMITLV_GET_TLVLEN(rssi_event->tlv_header)) 840 return QDF_STATUS_SUCCESS; 841 842 if (rssi_event->num_per_chain_rssi_stats >= 843 WMITLV_GET_TLVLEN(rssi_event->tlv_header)) { 844 wmi_err("num_per_chain_rssi_stats:%u is out of bounds", 845 rssi_event->num_per_chain_rssi_stats); 846 return QDF_STATUS_E_INVAL; 847 } 848 stats_param->num_rssi_stats = rssi_event->num_per_chain_rssi_stats; 849 850 if (param_buf->vdev_extd_stats) 851 stats_param->num_vdev_extd_stats = 852 param_buf->num_vdev_extd_stats; 853 854 /* if peer_adv_stats is not populated */ 855 if (param_buf->num_peer_extd2_stats) 856 stats_param->num_peer_adv_stats = 857 param_buf->num_peer_extd2_stats; 858 859 return QDF_STATUS_SUCCESS; 860 } 861 862 /** 863 * extract_pdev_tx_stats() - extract pdev tx stats from event 864 * @tx: destination 865 * @tx_stats: source event data 866 */ 867 static void extract_pdev_tx_stats(wmi_host_dbg_tx_stats *tx, 868 struct wlan_dbg_tx_stats *tx_stats) 869 { 870 /* Tx Stats */ 871 tx->comp_queued = tx_stats->comp_queued; 872 tx->comp_delivered = tx_stats->comp_delivered; 873 tx->msdu_enqued = tx_stats->msdu_enqued; 874 tx->mpdu_enqued = tx_stats->mpdu_enqued; 875 tx->wmm_drop = tx_stats->wmm_drop; 876 tx->local_enqued = tx_stats->local_enqued; 877 tx->local_freed = tx_stats->local_freed; 878 tx->hw_queued = tx_stats->hw_queued; 879 tx->hw_reaped = tx_stats->hw_reaped; 880 tx->underrun = tx_stats->underrun; 881 tx->tx_abort = tx_stats->tx_abort; 882 tx->mpdus_requed = tx_stats->mpdus_requed; 883 tx->data_rc = tx_stats->data_rc; 884 tx->self_triggers = tx_stats->self_triggers; 885 tx->sw_retry_failure = tx_stats->sw_retry_failure; 886 tx->illgl_rate_phy_err = tx_stats->illgl_rate_phy_err; 887 tx->pdev_cont_xretry = tx_stats->pdev_cont_xretry; 888 tx->pdev_tx_timeout = tx_stats->pdev_tx_timeout; 889 tx->pdev_resets = tx_stats->pdev_resets; 890 tx->stateless_tid_alloc_failure = tx_stats->stateless_tid_alloc_failure; 891 tx->phy_underrun = tx_stats->phy_underrun; 892 tx->txop_ovf = tx_stats->txop_ovf; 893 894 return; 895 } 896 897 898 /** 899 * extract_pdev_rx_stats() - extract pdev rx stats from event 900 * @rx: destination 901 * @rx_stats: source event data 902 */ 903 static void extract_pdev_rx_stats(wmi_host_dbg_rx_stats *rx, 904 struct wlan_dbg_rx_stats *rx_stats) 905 { 906 /* Rx Stats */ 907 rx->mid_ppdu_route_change = rx_stats->mid_ppdu_route_change; 908 rx->status_rcvd = rx_stats->status_rcvd; 909 rx->r0_frags = rx_stats->r0_frags; 910 rx->r1_frags = rx_stats->r1_frags; 911 rx->r2_frags = rx_stats->r2_frags; 912 /* Only TLV */ 913 rx->r3_frags = 0; 914 rx->htt_msdus = rx_stats->htt_msdus; 915 rx->htt_mpdus = rx_stats->htt_mpdus; 916 rx->loc_msdus = rx_stats->loc_msdus; 917 rx->loc_mpdus = rx_stats->loc_mpdus; 918 rx->oversize_amsdu = rx_stats->oversize_amsdu; 919 rx->phy_errs = rx_stats->phy_errs; 920 rx->phy_err_drop = rx_stats->phy_err_drop; 921 rx->mpdu_errs = rx_stats->mpdu_errs; 922 923 return; 924 } 925 926 /** 927 * extract_pdev_stats_tlv() - extract pdev stats from event 928 * @wmi_handle: wmi handle 929 * @evt_buf: pointer to event buffer 930 * @index: Index into pdev stats 931 * @pdev_stats: Pointer to hold pdev stats 932 * 933 * Return: QDF_STATUS_SUCCESS for success or error code 934 */ 935 static QDF_STATUS 936 extract_pdev_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index, 937 wmi_host_pdev_stats *pdev_stats) 938 { 939 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 940 wmi_stats_event_fixed_param *ev_param; 941 uint8_t *data; 942 943 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; 944 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param; 945 pdev_stats->pdev_id = 946 wmi_handle->ops->convert_target_pdev_id_to_host(wmi_handle, 947 ev_param->pdev_id); 948 949 data = param_buf->data; 950 951 if (index < ev_param->num_pdev_stats) { 952 wmi_pdev_stats *ev = (wmi_pdev_stats *) ((data) + 953 (index * sizeof(wmi_pdev_stats))); 954 955 pdev_stats->chan_nf = ev->chan_nf; 956 pdev_stats->tx_frame_count = ev->tx_frame_count; 957 pdev_stats->rx_frame_count = ev->rx_frame_count; 958 pdev_stats->rx_clear_count = ev->rx_clear_count; 959 pdev_stats->cycle_count = ev->cycle_count; 960 pdev_stats->phy_err_count = ev->phy_err_count; 961 pdev_stats->chan_tx_pwr = ev->chan_tx_pwr; 962 963 extract_pdev_tx_stats(&(pdev_stats->pdev_stats.tx), 964 &(ev->pdev_stats.tx)); 965 extract_pdev_rx_stats(&(pdev_stats->pdev_stats.rx), 966 &(ev->pdev_stats.rx)); 967 } 968 969 return QDF_STATUS_SUCCESS; 970 } 971 972 /** 973 * extract_vdev_stats_tlv() - extract vdev stats from event 974 * @wmi_handle: wmi handle 975 * @evt_buf: pointer to event buffer 976 * @index: Index into vdev stats 977 * @vdev_stats: Pointer to hold vdev stats 978 * 979 * Return: QDF_STATUS_SUCCESS for success or error code 980 */ 981 static QDF_STATUS extract_vdev_stats_tlv(wmi_unified_t wmi_handle, 982 void *evt_buf, uint32_t index, wmi_host_vdev_stats *vdev_stats) 983 { 984 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 985 wmi_stats_event_fixed_param *ev_param; 986 uint8_t *data; 987 988 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; 989 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param; 990 data = (uint8_t *) param_buf->data; 991 992 if (index < ev_param->num_vdev_stats) { 993 wmi_vdev_stats *ev = (wmi_vdev_stats *) ((data) + 994 ((ev_param->num_pdev_stats) * 995 sizeof(wmi_pdev_stats)) + 996 (index * sizeof(wmi_vdev_stats))); 997 998 vdev_stats->vdev_id = ev->vdev_id; 999 vdev_stats->vdev_snr.bcn_snr = ev->vdev_snr.bcn_snr; 1000 vdev_stats->vdev_snr.dat_snr = ev->vdev_snr.dat_snr; 1001 1002 OS_MEMCPY(vdev_stats->tx_frm_cnt, ev->tx_frm_cnt, 1003 sizeof(ev->tx_frm_cnt)); 1004 vdev_stats->rx_frm_cnt = ev->rx_frm_cnt; 1005 OS_MEMCPY(vdev_stats->multiple_retry_cnt, 1006 ev->multiple_retry_cnt, 1007 sizeof(ev->multiple_retry_cnt)); 1008 OS_MEMCPY(vdev_stats->fail_cnt, ev->fail_cnt, 1009 sizeof(ev->fail_cnt)); 1010 vdev_stats->rts_fail_cnt = ev->rts_fail_cnt; 1011 vdev_stats->rts_succ_cnt = ev->rts_succ_cnt; 1012 vdev_stats->rx_err_cnt = ev->rx_err_cnt; 1013 vdev_stats->rx_discard_cnt = ev->rx_discard_cnt; 1014 vdev_stats->ack_fail_cnt = ev->ack_fail_cnt; 1015 OS_MEMCPY(vdev_stats->tx_rate_history, ev->tx_rate_history, 1016 sizeof(ev->tx_rate_history)); 1017 OS_MEMCPY(vdev_stats->bcn_rssi_history, ev->bcn_rssi_history, 1018 sizeof(ev->bcn_rssi_history)); 1019 1020 } 1021 1022 return QDF_STATUS_SUCCESS; 1023 } 1024 1025 /** 1026 * extract_peer_stats_tlv() - extract peer stats from event 1027 * @wmi_handle: wmi handle 1028 * @evt_buf: pointer to event buffer 1029 * @index: Index into peer stats 1030 * @peer_stats: Pointer to hold peer stats 1031 * 1032 * Return: QDF_STATUS_SUCCESS for success or error code 1033 */ 1034 static QDF_STATUS 1035 extract_peer_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index, 1036 wmi_host_peer_stats *peer_stats) 1037 { 1038 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 1039 wmi_stats_event_fixed_param *ev_param; 1040 uint8_t *data; 1041 1042 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; 1043 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param; 1044 data = (uint8_t *) param_buf->data; 1045 1046 if (index < ev_param->num_peer_stats) { 1047 wmi_peer_stats *ev = (wmi_peer_stats *) ((data) + 1048 ((ev_param->num_pdev_stats) * sizeof(wmi_pdev_stats)) + 1049 ((ev_param->num_vdev_stats) * sizeof(wmi_vdev_stats)) + 1050 (index * sizeof(wmi_peer_stats))); 1051 1052 OS_MEMSET(peer_stats, 0, sizeof(wmi_host_peer_stats)); 1053 1054 OS_MEMCPY(&(peer_stats->peer_macaddr), 1055 &(ev->peer_macaddr), sizeof(wmi_mac_addr)); 1056 1057 peer_stats->peer_rssi = ev->peer_rssi; 1058 peer_stats->peer_tx_rate = ev->peer_tx_rate; 1059 peer_stats->peer_rx_rate = ev->peer_rx_rate; 1060 } 1061 1062 return QDF_STATUS_SUCCESS; 1063 } 1064 1065 /** 1066 * extract_peer_extd_stats_tlv() - extract extended peer stats from event 1067 * @wmi_handle: wmi handle 1068 * @evt_buf: pointer to event buffer 1069 * @index: Index into extended peer stats 1070 * @peer_extd_stats: Pointer to hold extended peer stats 1071 * 1072 * Return: QDF_STATUS_SUCCESS for success or error code 1073 */ 1074 static QDF_STATUS 1075 extract_peer_extd_stats_tlv(wmi_unified_t wmi_handle, 1076 void *evt_buf, uint32_t index, 1077 wmi_host_peer_extd_stats *peer_extd_stats) 1078 { 1079 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 1080 wmi_stats_event_fixed_param *ev_param; 1081 uint8_t *data; 1082 1083 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf; 1084 ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param; 1085 data = (uint8_t *)param_buf->data; 1086 if (!data) 1087 return QDF_STATUS_E_FAILURE; 1088 1089 if (index < ev_param->num_peer_extd_stats) { 1090 wmi_peer_extd_stats *ev = (wmi_peer_extd_stats *) (data + 1091 (ev_param->num_pdev_stats * sizeof(wmi_pdev_stats)) + 1092 (ev_param->num_vdev_stats * sizeof(wmi_vdev_stats)) + 1093 (ev_param->num_peer_stats * sizeof(wmi_peer_stats)) + 1094 (ev_param->num_bcnflt_stats * 1095 sizeof(wmi_bcnfilter_stats_t)) + 1096 (ev_param->num_chan_stats * sizeof(wmi_chan_stats)) + 1097 (ev_param->num_mib_stats * sizeof(wmi_mib_stats)) + 1098 (ev_param->num_bcn_stats * sizeof(wmi_bcn_stats)) + 1099 (index * sizeof(wmi_peer_extd_stats))); 1100 1101 qdf_mem_zero(peer_extd_stats, sizeof(wmi_host_peer_extd_stats)); 1102 qdf_mem_copy(&peer_extd_stats->peer_macaddr, &ev->peer_macaddr, 1103 sizeof(wmi_mac_addr)); 1104 1105 peer_extd_stats->rx_mc_bc_cnt = ev->rx_mc_bc_cnt; 1106 } 1107 1108 return QDF_STATUS_SUCCESS; 1109 1110 } 1111 1112 /** 1113 * extract_pmf_bcn_protect_stats_tlv() - extract pmf bcn stats from event 1114 * @wmi_handle: wmi handle 1115 * @evt_buf: pointer to event buffer 1116 * @pmf_bcn_stats: Pointer to hold pmf bcn protect stats 1117 * 1118 * Return: QDF_STATUS_SUCCESS for success or error code 1119 */ 1120 1121 static QDF_STATUS 1122 extract_pmf_bcn_protect_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, 1123 wmi_host_pmf_bcn_protect_stats *pmf_bcn_stats) 1124 { 1125 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 1126 wmi_stats_event_fixed_param *ev_param; 1127 1128 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf; 1129 if (!param_buf) 1130 return QDF_STATUS_E_FAILURE; 1131 1132 ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param; 1133 1134 if ((ev_param->stats_id & WMI_REQUEST_PMF_BCN_PROTECT_STAT) && 1135 param_buf->pmf_bcn_protect_stats) { 1136 pmf_bcn_stats->igtk_mic_fail_cnt = 1137 param_buf->pmf_bcn_protect_stats->igtk_mic_fail_cnt; 1138 pmf_bcn_stats->igtk_replay_cnt = 1139 param_buf->pmf_bcn_protect_stats->igtk_replay_cnt; 1140 pmf_bcn_stats->bcn_mic_fail_cnt = 1141 param_buf->pmf_bcn_protect_stats->bcn_mic_fail_cnt; 1142 pmf_bcn_stats->bcn_replay_cnt = 1143 param_buf->pmf_bcn_protect_stats->bcn_replay_cnt; 1144 } 1145 1146 return QDF_STATUS_SUCCESS; 1147 } 1148 1149 #if defined(WLAN_SUPPORT_INFRA_CTRL_PATH_STATS) || \ 1150 defined(WLAN_TELEMETRY_STATS_SUPPORT) 1151 static void wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops *ops) 1152 { 1153 ops->send_infra_cp_stats_request_cmd = 1154 send_infra_cp_stats_request_cmd_tlv; 1155 } 1156 #else 1157 static void wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops *ops) 1158 { 1159 } 1160 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ 1161 1162 #ifdef WLAN_FEATURE_SON 1163 /** 1164 * extract_inst_rssi_stats_resp_tlv() - extract inst rssi stats from event 1165 * @wmi_handle: wmi handle 1166 * @evt_buf: pointer to event buffer 1167 * @inst_rssi_resp: Pointer to hold inst rssi response 1168 * 1169 * Return: QDF_STATUS_SUCCESS for success or error code 1170 */ 1171 static QDF_STATUS 1172 extract_inst_rssi_stats_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf, 1173 struct wmi_host_inst_rssi_stats_resp *inst_rssi_resp) 1174 { 1175 WMI_INST_RSSI_STATS_EVENTID_param_tlvs *param_buf; 1176 wmi_inst_rssi_stats_resp_fixed_param *event; 1177 1178 param_buf = (WMI_INST_RSSI_STATS_EVENTID_param_tlvs *)evt_buf; 1179 event = (wmi_inst_rssi_stats_resp_fixed_param *)param_buf->fixed_param; 1180 1181 inst_rssi_resp->inst_rssi = event->iRSSI; 1182 WMI_CHAR_ARRAY_TO_MAC_ADDR(inst_rssi_resp->peer_macaddr.bytes, 1183 &event->peer_macaddr); 1184 inst_rssi_resp->vdev_id = event->vdev_id; 1185 1186 return QDF_STATUS_SUCCESS; 1187 } 1188 1189 static void 1190 wmi_inst_rssi_stats_ops_attach_tlv(struct wmi_ops *ops) 1191 { 1192 ops->extract_inst_rssi_stats_resp = extract_inst_rssi_stats_resp_tlv; 1193 } 1194 #else 1195 static void 1196 wmi_inst_rssi_stats_ops_attach_tlv(struct wmi_ops *ops) 1197 { 1198 } 1199 #endif 1200 1201 void wmi_cp_stats_attach_tlv(wmi_unified_t wmi_handle) 1202 { 1203 struct wmi_ops *ops = wmi_handle->ops; 1204 1205 ops->send_stats_request_cmd = send_stats_request_cmd_tlv; 1206 #ifdef WLAN_FEATURE_BIG_DATA_STATS 1207 ops->send_big_data_stats_request_cmd = 1208 send_big_data_stats_request_cmd_tlv; 1209 #endif 1210 ops->extract_all_stats_count = extract_all_stats_counts_tlv; 1211 ops->extract_pdev_stats = extract_pdev_stats_tlv; 1212 ops->extract_vdev_stats = extract_vdev_stats_tlv; 1213 ops->extract_peer_stats = extract_peer_stats_tlv; 1214 ops->extract_peer_extd_stats = extract_peer_extd_stats_tlv; 1215 wmi_infra_cp_stats_ops_attach_tlv(ops); 1216 ops->extract_pmf_bcn_protect_stats = extract_pmf_bcn_protect_stats_tlv, 1217 wmi_inst_rssi_stats_ops_attach_tlv(ops); 1218 1219 wmi_mc_cp_stats_attach_tlv(wmi_handle); 1220 } 1221