1 /* 2 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "osdep.h" 18 #include "wmi.h" 19 #include "wmi_unified_priv.h" 20 #include "wmi_unified_param.h" 21 22 /** 23 * send_stats_request_cmd_tlv() - WMI request stats function 24 * @param wmi_handle: handle to WMI. 25 * @param macaddr: MAC address 26 * @param param: pointer to hold stats request parameter 27 * 28 * Return: 0 on success and -ve on failure. 29 */ 30 static QDF_STATUS 31 send_stats_request_cmd_tlv(wmi_unified_t wmi_handle, 32 uint8_t macaddr[QDF_MAC_ADDR_SIZE], 33 struct stats_request_params *param) 34 { 35 int32_t ret; 36 wmi_request_stats_cmd_fixed_param *cmd; 37 wmi_buf_t buf; 38 uint16_t len = sizeof(wmi_request_stats_cmd_fixed_param); 39 40 buf = wmi_buf_alloc(wmi_handle, len); 41 if (!buf) 42 return QDF_STATUS_E_NOMEM; 43 44 cmd = (wmi_request_stats_cmd_fixed_param *) wmi_buf_data(buf); 45 WMITLV_SET_HDR(&cmd->tlv_header, 46 WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, 47 WMITLV_GET_STRUCT_TLVLEN 48 (wmi_request_stats_cmd_fixed_param)); 49 cmd->stats_id = param->stats_id; 50 cmd->vdev_id = param->vdev_id; 51 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target( 52 wmi_handle, 53 param->pdev_id); 54 55 WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->peer_macaddr); 56 57 wmi_debug("STATS REQ STATS_ID:%d VDEV_ID:%d PDEV_ID:%d-->", 58 cmd->stats_id, cmd->vdev_id, cmd->pdev_id); 59 60 wmi_mtrace(WMI_REQUEST_STATS_CMDID, cmd->vdev_id, 0); 61 ret = wmi_unified_cmd_send_pm_chk(wmi_handle, buf, len, 62 WMI_REQUEST_STATS_CMDID); 63 64 if (ret) { 65 wmi_err("Failed to send status request to fw =%d", ret); 66 wmi_buf_free(buf); 67 } 68 69 return qdf_status_from_os_return(ret); 70 } 71 72 /** 73 * extract_all_stats_counts_tlv() - extract all stats count from event 74 * @param wmi_handle: wmi handle 75 * @param evt_buf: pointer to event buffer 76 * @param stats_param: Pointer to hold stats count 77 * 78 * Return: QDF_STATUS_SUCCESS for success or error code 79 */ 80 static QDF_STATUS 81 extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, void *evt_buf, 82 wmi_host_stats_event *stats_param) 83 { 84 wmi_stats_event_fixed_param *ev; 85 wmi_per_chain_rssi_stats *rssi_event; 86 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 87 uint64_t min_data_len; 88 uint32_t i; 89 90 qdf_mem_zero(stats_param, sizeof(*stats_param)); 91 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; 92 ev = (wmi_stats_event_fixed_param *) param_buf->fixed_param; 93 rssi_event = param_buf->chain_stats; 94 if (!ev) { 95 wmi_err("event fixed param NULL"); 96 return QDF_STATUS_E_FAILURE; 97 } 98 99 if (param_buf->num_data > WMI_SVC_MSG_MAX_SIZE - sizeof(*ev)) { 100 wmi_err("num_data : %u is invalid", param_buf->num_data); 101 return QDF_STATUS_E_FAULT; 102 } 103 104 for (i = 1; i <= WMI_REQUEST_VDEV_EXTD_STAT; i = i << 1) { 105 switch (ev->stats_id & i) { 106 case WMI_REQUEST_PEER_STAT: 107 stats_param->stats_id |= WMI_HOST_REQUEST_PEER_STAT; 108 break; 109 110 case WMI_REQUEST_AP_STAT: 111 stats_param->stats_id |= WMI_HOST_REQUEST_AP_STAT; 112 break; 113 114 case WMI_REQUEST_PDEV_STAT: 115 stats_param->stats_id |= WMI_HOST_REQUEST_PDEV_STAT; 116 break; 117 118 case WMI_REQUEST_VDEV_STAT: 119 stats_param->stats_id |= WMI_HOST_REQUEST_VDEV_STAT; 120 break; 121 122 case WMI_REQUEST_BCNFLT_STAT: 123 stats_param->stats_id |= WMI_HOST_REQUEST_BCNFLT_STAT; 124 break; 125 126 case WMI_REQUEST_VDEV_RATE_STAT: 127 stats_param->stats_id |= 128 WMI_HOST_REQUEST_VDEV_RATE_STAT; 129 break; 130 131 case WMI_REQUEST_BCN_STAT: 132 stats_param->stats_id |= WMI_HOST_REQUEST_BCN_STAT; 133 break; 134 case WMI_REQUEST_PEER_EXTD_STAT: 135 stats_param->stats_id |= WMI_REQUEST_PEER_EXTD_STAT; 136 break; 137 138 case WMI_REQUEST_PEER_EXTD2_STAT: 139 stats_param->stats_id |= 140 WMI_HOST_REQUEST_PEER_ADV_STATS; 141 break; 142 143 case WMI_REQUEST_PMF_BCN_PROTECT_STAT: 144 stats_param->stats_id |= 145 WMI_HOST_REQUEST_PMF_BCN_PROTECT_STAT; 146 break; 147 148 case WMI_REQUEST_VDEV_EXTD_STAT: 149 stats_param->stats_id |= 150 WMI_HOST_REQUEST_VDEV_PRB_FILS_STAT; 151 break; 152 } 153 } 154 155 /* ev->num_*_stats may cause uint32_t overflow, so use uint64_t 156 * to save total length calculated 157 */ 158 min_data_len = 159 (((uint64_t)ev->num_pdev_stats) * sizeof(wmi_pdev_stats)) + 160 (((uint64_t)ev->num_vdev_stats) * sizeof(wmi_vdev_stats)) + 161 (((uint64_t)ev->num_peer_stats) * sizeof(wmi_peer_stats)) + 162 (((uint64_t)ev->num_bcnflt_stats) * 163 sizeof(wmi_bcnfilter_stats_t)) + 164 (((uint64_t)ev->num_chan_stats) * sizeof(wmi_chan_stats)) + 165 (((uint64_t)ev->num_mib_stats) * sizeof(wmi_mib_stats)) + 166 (((uint64_t)ev->num_bcn_stats) * sizeof(wmi_bcn_stats)) + 167 (((uint64_t)ev->num_peer_extd_stats) * 168 sizeof(wmi_peer_extd_stats)) + 169 (((uint64_t)ev->num_mib_extd_stats) * 170 sizeof(wmi_mib_extd_stats)); 171 if (param_buf->num_data != min_data_len) { 172 wmi_err("data len: %u isn't same as calculated: %llu", 173 param_buf->num_data, min_data_len); 174 return QDF_STATUS_E_FAULT; 175 } 176 177 stats_param->last_event = ev->last_event; 178 stats_param->num_pdev_stats = ev->num_pdev_stats; 179 stats_param->num_pdev_ext_stats = 0; 180 stats_param->num_vdev_stats = ev->num_vdev_stats; 181 stats_param->num_peer_stats = ev->num_peer_stats; 182 stats_param->num_peer_extd_stats = ev->num_peer_extd_stats; 183 stats_param->num_bcnflt_stats = ev->num_bcnflt_stats; 184 stats_param->num_chan_stats = ev->num_chan_stats; 185 stats_param->num_mib_stats = ev->num_mib_stats; 186 stats_param->num_mib_extd_stats = ev->num_mib_extd_stats; 187 stats_param->num_bcn_stats = ev->num_bcn_stats; 188 stats_param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host( 189 wmi_handle, 190 ev->pdev_id); 191 192 /* if chain_stats is not populated */ 193 if (!param_buf->chain_stats || !param_buf->num_chain_stats) 194 return QDF_STATUS_SUCCESS; 195 196 if (WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats != 197 WMITLV_GET_TLVTAG(rssi_event->tlv_header)) 198 return QDF_STATUS_SUCCESS; 199 200 if (WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats) != 201 WMITLV_GET_TLVLEN(rssi_event->tlv_header)) 202 return QDF_STATUS_SUCCESS; 203 204 if (rssi_event->num_per_chain_rssi_stats >= 205 WMITLV_GET_TLVLEN(rssi_event->tlv_header)) { 206 wmi_err("num_per_chain_rssi_stats:%u is out of bounds", 207 rssi_event->num_per_chain_rssi_stats); 208 return QDF_STATUS_E_INVAL; 209 } 210 stats_param->num_rssi_stats = rssi_event->num_per_chain_rssi_stats; 211 212 if (param_buf->vdev_extd_stats) 213 stats_param->num_vdev_extd_stats = 214 param_buf->num_vdev_extd_stats; 215 216 /* if peer_adv_stats is not populated */ 217 if (param_buf->num_peer_extd2_stats) 218 stats_param->num_peer_adv_stats = 219 param_buf->num_peer_extd2_stats; 220 221 return QDF_STATUS_SUCCESS; 222 } 223 224 /** 225 * extract_pdev_tx_stats() - extract pdev tx stats from event 226 */ 227 static void extract_pdev_tx_stats(wmi_host_dbg_tx_stats *tx, 228 struct wlan_dbg_tx_stats *tx_stats) 229 { 230 /* Tx Stats */ 231 tx->comp_queued = tx_stats->comp_queued; 232 tx->comp_delivered = tx_stats->comp_delivered; 233 tx->msdu_enqued = tx_stats->msdu_enqued; 234 tx->mpdu_enqued = tx_stats->mpdu_enqued; 235 tx->wmm_drop = tx_stats->wmm_drop; 236 tx->local_enqued = tx_stats->local_enqued; 237 tx->local_freed = tx_stats->local_freed; 238 tx->hw_queued = tx_stats->hw_queued; 239 tx->hw_reaped = tx_stats->hw_reaped; 240 tx->underrun = tx_stats->underrun; 241 tx->tx_abort = tx_stats->tx_abort; 242 tx->mpdus_requed = tx_stats->mpdus_requed; 243 tx->data_rc = tx_stats->data_rc; 244 tx->self_triggers = tx_stats->self_triggers; 245 tx->sw_retry_failure = tx_stats->sw_retry_failure; 246 tx->illgl_rate_phy_err = tx_stats->illgl_rate_phy_err; 247 tx->pdev_cont_xretry = tx_stats->pdev_cont_xretry; 248 tx->pdev_tx_timeout = tx_stats->pdev_tx_timeout; 249 tx->pdev_resets = tx_stats->pdev_resets; 250 tx->stateless_tid_alloc_failure = tx_stats->stateless_tid_alloc_failure; 251 tx->phy_underrun = tx_stats->phy_underrun; 252 tx->txop_ovf = tx_stats->txop_ovf; 253 254 return; 255 } 256 257 258 /** 259 * extract_pdev_rx_stats() - extract pdev rx stats from event 260 */ 261 static void extract_pdev_rx_stats(wmi_host_dbg_rx_stats *rx, 262 struct wlan_dbg_rx_stats *rx_stats) 263 { 264 /* Rx Stats */ 265 rx->mid_ppdu_route_change = rx_stats->mid_ppdu_route_change; 266 rx->status_rcvd = rx_stats->status_rcvd; 267 rx->r0_frags = rx_stats->r0_frags; 268 rx->r1_frags = rx_stats->r1_frags; 269 rx->r2_frags = rx_stats->r2_frags; 270 /* Only TLV */ 271 rx->r3_frags = 0; 272 rx->htt_msdus = rx_stats->htt_msdus; 273 rx->htt_mpdus = rx_stats->htt_mpdus; 274 rx->loc_msdus = rx_stats->loc_msdus; 275 rx->loc_mpdus = rx_stats->loc_mpdus; 276 rx->oversize_amsdu = rx_stats->oversize_amsdu; 277 rx->phy_errs = rx_stats->phy_errs; 278 rx->phy_err_drop = rx_stats->phy_err_drop; 279 rx->mpdu_errs = rx_stats->mpdu_errs; 280 281 return; 282 } 283 284 /** 285 * extract_pdev_stats_tlv() - extract pdev stats from event 286 * @param wmi_handle: wmi handle 287 * @param evt_buf: pointer to event buffer 288 * @param index: Index into pdev stats 289 * @param pdev_stats: Pointer to hold pdev stats 290 * 291 * Return: QDF_STATUS_SUCCESS for success or error code 292 */ 293 static QDF_STATUS 294 extract_pdev_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index, 295 wmi_host_pdev_stats *pdev_stats) 296 { 297 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 298 wmi_stats_event_fixed_param *ev_param; 299 uint8_t *data; 300 301 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; 302 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param; 303 304 data = param_buf->data; 305 306 if (index < ev_param->num_pdev_stats) { 307 wmi_pdev_stats *ev = (wmi_pdev_stats *) ((data) + 308 (index * sizeof(wmi_pdev_stats))); 309 310 pdev_stats->chan_nf = ev->chan_nf; 311 pdev_stats->tx_frame_count = ev->tx_frame_count; 312 pdev_stats->rx_frame_count = ev->rx_frame_count; 313 pdev_stats->rx_clear_count = ev->rx_clear_count; 314 pdev_stats->cycle_count = ev->cycle_count; 315 pdev_stats->phy_err_count = ev->phy_err_count; 316 pdev_stats->chan_tx_pwr = ev->chan_tx_pwr; 317 318 extract_pdev_tx_stats(&(pdev_stats->pdev_stats.tx), 319 &(ev->pdev_stats.tx)); 320 extract_pdev_rx_stats(&(pdev_stats->pdev_stats.rx), 321 &(ev->pdev_stats.rx)); 322 } 323 324 return QDF_STATUS_SUCCESS; 325 } 326 327 /** 328 * extract_vdev_stats_tlv() - extract vdev stats from event 329 * @param wmi_handle: wmi handle 330 * @param evt_buf: pointer to event buffer 331 * @param index: Index into vdev stats 332 * @param vdev_stats: Pointer to hold vdev stats 333 * 334 * Return: QDF_STATUS_SUCCESS for success or error code 335 */ 336 static QDF_STATUS extract_vdev_stats_tlv(wmi_unified_t wmi_handle, 337 void *evt_buf, uint32_t index, wmi_host_vdev_stats *vdev_stats) 338 { 339 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 340 wmi_stats_event_fixed_param *ev_param; 341 uint8_t *data; 342 343 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; 344 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param; 345 data = (uint8_t *) param_buf->data; 346 347 if (index < ev_param->num_vdev_stats) { 348 wmi_vdev_stats *ev = (wmi_vdev_stats *) ((data) + 349 ((ev_param->num_pdev_stats) * 350 sizeof(wmi_pdev_stats)) + 351 (index * sizeof(wmi_vdev_stats))); 352 353 vdev_stats->vdev_id = ev->vdev_id; 354 vdev_stats->vdev_snr.bcn_snr = ev->vdev_snr.bcn_snr; 355 vdev_stats->vdev_snr.dat_snr = ev->vdev_snr.dat_snr; 356 357 OS_MEMCPY(vdev_stats->tx_frm_cnt, ev->tx_frm_cnt, 358 sizeof(ev->tx_frm_cnt)); 359 vdev_stats->rx_frm_cnt = ev->rx_frm_cnt; 360 OS_MEMCPY(vdev_stats->multiple_retry_cnt, 361 ev->multiple_retry_cnt, 362 sizeof(ev->multiple_retry_cnt)); 363 OS_MEMCPY(vdev_stats->fail_cnt, ev->fail_cnt, 364 sizeof(ev->fail_cnt)); 365 vdev_stats->rts_fail_cnt = ev->rts_fail_cnt; 366 vdev_stats->rts_succ_cnt = ev->rts_succ_cnt; 367 vdev_stats->rx_err_cnt = ev->rx_err_cnt; 368 vdev_stats->rx_discard_cnt = ev->rx_discard_cnt; 369 vdev_stats->ack_fail_cnt = ev->ack_fail_cnt; 370 OS_MEMCPY(vdev_stats->tx_rate_history, ev->tx_rate_history, 371 sizeof(ev->tx_rate_history)); 372 OS_MEMCPY(vdev_stats->bcn_rssi_history, ev->bcn_rssi_history, 373 sizeof(ev->bcn_rssi_history)); 374 375 } 376 377 return QDF_STATUS_SUCCESS; 378 } 379 380 /** 381 * extract_peer_stats_tlv() - extract peer stats from event 382 * @param wmi_handle: wmi handle 383 * @param evt_buf: pointer to event buffer 384 * @param index: Index into peer stats 385 * @param peer_stats: Pointer to hold peer stats 386 * 387 * Return: QDF_STATUS_SUCCESS for success or error code 388 */ 389 static QDF_STATUS 390 extract_peer_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index, 391 wmi_host_peer_stats *peer_stats) 392 { 393 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 394 wmi_stats_event_fixed_param *ev_param; 395 uint8_t *data; 396 397 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf; 398 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param; 399 data = (uint8_t *) param_buf->data; 400 401 if (index < ev_param->num_peer_stats) { 402 wmi_peer_stats *ev = (wmi_peer_stats *) ((data) + 403 ((ev_param->num_pdev_stats) * sizeof(wmi_pdev_stats)) + 404 ((ev_param->num_vdev_stats) * sizeof(wmi_vdev_stats)) + 405 (index * sizeof(wmi_peer_stats))); 406 407 OS_MEMSET(peer_stats, 0, sizeof(wmi_host_peer_stats)); 408 409 OS_MEMCPY(&(peer_stats->peer_macaddr), 410 &(ev->peer_macaddr), sizeof(wmi_mac_addr)); 411 412 peer_stats->peer_rssi = ev->peer_rssi; 413 peer_stats->peer_tx_rate = ev->peer_tx_rate; 414 peer_stats->peer_rx_rate = ev->peer_rx_rate; 415 } 416 417 return QDF_STATUS_SUCCESS; 418 } 419 420 /** 421 * extract_peer_extd_stats_tlv() - extract extended peer stats from event 422 * @param wmi_handle: wmi handle 423 * @param evt_buf: pointer to event buffer 424 * @param index: Index into extended peer stats 425 * @param peer_extd_stats: Pointer to hold extended peer stats 426 * 427 * Return: QDF_STATUS_SUCCESS for success or error code 428 */ 429 static QDF_STATUS 430 extract_peer_extd_stats_tlv(wmi_unified_t wmi_handle, 431 void *evt_buf, uint32_t index, 432 wmi_host_peer_extd_stats *peer_extd_stats) 433 { 434 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 435 wmi_stats_event_fixed_param *ev_param; 436 uint8_t *data; 437 438 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf; 439 ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param; 440 data = (uint8_t *)param_buf->data; 441 if (!data) 442 return QDF_STATUS_E_FAILURE; 443 444 if (index < ev_param->num_peer_extd_stats) { 445 wmi_peer_extd_stats *ev = (wmi_peer_extd_stats *) (data + 446 (ev_param->num_pdev_stats * sizeof(wmi_pdev_stats)) + 447 (ev_param->num_vdev_stats * sizeof(wmi_vdev_stats)) + 448 (ev_param->num_peer_stats * sizeof(wmi_peer_stats)) + 449 (ev_param->num_bcnflt_stats * 450 sizeof(wmi_bcnfilter_stats_t)) + 451 (ev_param->num_chan_stats * sizeof(wmi_chan_stats)) + 452 (ev_param->num_mib_stats * sizeof(wmi_mib_stats)) + 453 (ev_param->num_bcn_stats * sizeof(wmi_bcn_stats)) + 454 (index * sizeof(wmi_peer_extd_stats))); 455 456 qdf_mem_zero(peer_extd_stats, sizeof(wmi_host_peer_extd_stats)); 457 qdf_mem_copy(&peer_extd_stats->peer_macaddr, &ev->peer_macaddr, 458 sizeof(wmi_mac_addr)); 459 460 peer_extd_stats->rx_mc_bc_cnt = ev->rx_mc_bc_cnt; 461 } 462 463 return QDF_STATUS_SUCCESS; 464 465 } 466 467 /** 468 * extract_pmf_bcn_protect_stats_tlv() - extract pmf bcn stats from event 469 * @wmi_handle: wmi handle 470 * @evt_buf: pointer to event buffer 471 * @pmf_bcn_stats: Pointer to hold pmf bcn protect stats 472 * 473 * Return: QDF_STATUS_SUCCESS for success or error code 474 */ 475 476 static QDF_STATUS 477 extract_pmf_bcn_protect_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, 478 wmi_host_pmf_bcn_protect_stats *pmf_bcn_stats) 479 { 480 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; 481 wmi_stats_event_fixed_param *ev_param; 482 483 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf; 484 if (!param_buf) 485 return QDF_STATUS_E_FAILURE; 486 487 ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param; 488 489 if ((ev_param->stats_id & WMI_REQUEST_PMF_BCN_PROTECT_STAT) && 490 param_buf->pmf_bcn_protect_stats) { 491 pmf_bcn_stats->igtk_mic_fail_cnt = 492 param_buf->pmf_bcn_protect_stats->igtk_mic_fail_cnt; 493 pmf_bcn_stats->igtk_replay_cnt = 494 param_buf->pmf_bcn_protect_stats->igtk_replay_cnt; 495 pmf_bcn_stats->bcn_mic_fail_cnt = 496 param_buf->pmf_bcn_protect_stats->bcn_mic_fail_cnt; 497 pmf_bcn_stats->bcn_replay_cnt = 498 param_buf->pmf_bcn_protect_stats->bcn_replay_cnt; 499 } 500 501 return QDF_STATUS_SUCCESS; 502 } 503 504 void wmi_cp_stats_attach_tlv(wmi_unified_t wmi_handle) 505 { 506 struct wmi_ops *ops = wmi_handle->ops; 507 508 ops->send_stats_request_cmd = send_stats_request_cmd_tlv; 509 ops->extract_all_stats_count = extract_all_stats_counts_tlv; 510 ops->extract_pdev_stats = extract_pdev_stats_tlv; 511 ops->extract_vdev_stats = extract_vdev_stats_tlv; 512 ops->extract_peer_stats = extract_peer_stats_tlv; 513 ops->extract_peer_extd_stats = extract_peer_extd_stats_tlv; 514 ops->extract_pmf_bcn_protect_stats = extract_pmf_bcn_protect_stats_tlv, 515 516 wmi_mc_cp_stats_attach_tlv(wmi_handle); 517 } 518