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