xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_cp_stats_tlv.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
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