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