xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_cp_stats_tlv.c (revision 19ceffca9d494f2431432fa8123aa187c91cb4fb)
1 /*
2  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021 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_VDEV_EXTD_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 	}
646 
647 	/* ev->num_*_stats may cause uint32_t overflow, so use uint64_t
648 	 * to save total length calculated
649 	 */
650 	min_data_len =
651 		(((uint64_t)ev->num_pdev_stats) * sizeof(wmi_pdev_stats)) +
652 		(((uint64_t)ev->num_vdev_stats) * sizeof(wmi_vdev_stats)) +
653 		(((uint64_t)ev->num_peer_stats) * sizeof(wmi_peer_stats)) +
654 		(((uint64_t)ev->num_bcnflt_stats) *
655 		 sizeof(wmi_bcnfilter_stats_t)) +
656 		(((uint64_t)ev->num_chan_stats) * sizeof(wmi_chan_stats)) +
657 		(((uint64_t)ev->num_mib_stats) * sizeof(wmi_mib_stats)) +
658 		(((uint64_t)ev->num_bcn_stats) * sizeof(wmi_bcn_stats)) +
659 		(((uint64_t)ev->num_peer_extd_stats) *
660 		 sizeof(wmi_peer_extd_stats)) +
661 		(((uint64_t)ev->num_mib_extd_stats) *
662 		 sizeof(wmi_mib_extd_stats));
663 	if (param_buf->num_data != min_data_len) {
664 		wmi_err("data len: %u isn't same as calculated: %llu",
665 			 param_buf->num_data, min_data_len);
666 		return QDF_STATUS_E_FAULT;
667 	}
668 
669 	stats_param->last_event = ev->last_event;
670 	stats_param->num_pdev_stats = ev->num_pdev_stats;
671 	stats_param->num_pdev_ext_stats = 0;
672 	stats_param->num_vdev_stats = ev->num_vdev_stats;
673 	stats_param->num_peer_stats = ev->num_peer_stats;
674 	stats_param->num_peer_extd_stats = ev->num_peer_extd_stats;
675 	stats_param->num_bcnflt_stats = ev->num_bcnflt_stats;
676 	stats_param->num_chan_stats = ev->num_chan_stats;
677 	stats_param->num_mib_stats = ev->num_mib_stats;
678 	stats_param->num_mib_extd_stats = ev->num_mib_extd_stats;
679 	stats_param->num_bcn_stats = ev->num_bcn_stats;
680 	stats_param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
681 							wmi_handle,
682 							ev->pdev_id);
683 
684 	/* if chain_stats is not populated */
685 	if (!param_buf->chain_stats || !param_buf->num_chain_stats)
686 		return QDF_STATUS_SUCCESS;
687 
688 	if (WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats !=
689 	    WMITLV_GET_TLVTAG(rssi_event->tlv_header))
690 		return QDF_STATUS_SUCCESS;
691 
692 	if (WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats) !=
693 	    WMITLV_GET_TLVLEN(rssi_event->tlv_header))
694 		return QDF_STATUS_SUCCESS;
695 
696 	if (rssi_event->num_per_chain_rssi_stats >=
697 	    WMITLV_GET_TLVLEN(rssi_event->tlv_header)) {
698 		wmi_err("num_per_chain_rssi_stats:%u is out of bounds",
699 			 rssi_event->num_per_chain_rssi_stats);
700 		return QDF_STATUS_E_INVAL;
701 	}
702 	stats_param->num_rssi_stats = rssi_event->num_per_chain_rssi_stats;
703 
704 	if (param_buf->vdev_extd_stats)
705 		stats_param->num_vdev_extd_stats =
706 			param_buf->num_vdev_extd_stats;
707 
708 	/* if peer_adv_stats is not populated */
709 	if (param_buf->num_peer_extd2_stats)
710 		stats_param->num_peer_adv_stats =
711 			param_buf->num_peer_extd2_stats;
712 
713 	return QDF_STATUS_SUCCESS;
714 }
715 
716 /**
717  * extract_pdev_tx_stats() - extract pdev tx stats from event
718  */
719 static void extract_pdev_tx_stats(wmi_host_dbg_tx_stats *tx,
720 				  struct wlan_dbg_tx_stats *tx_stats)
721 {
722 	/* Tx Stats */
723 	tx->comp_queued = tx_stats->comp_queued;
724 	tx->comp_delivered = tx_stats->comp_delivered;
725 	tx->msdu_enqued = tx_stats->msdu_enqued;
726 	tx->mpdu_enqued = tx_stats->mpdu_enqued;
727 	tx->wmm_drop = tx_stats->wmm_drop;
728 	tx->local_enqued = tx_stats->local_enqued;
729 	tx->local_freed = tx_stats->local_freed;
730 	tx->hw_queued = tx_stats->hw_queued;
731 	tx->hw_reaped = tx_stats->hw_reaped;
732 	tx->underrun = tx_stats->underrun;
733 	tx->tx_abort = tx_stats->tx_abort;
734 	tx->mpdus_requed = tx_stats->mpdus_requed;
735 	tx->data_rc = tx_stats->data_rc;
736 	tx->self_triggers = tx_stats->self_triggers;
737 	tx->sw_retry_failure = tx_stats->sw_retry_failure;
738 	tx->illgl_rate_phy_err = tx_stats->illgl_rate_phy_err;
739 	tx->pdev_cont_xretry = tx_stats->pdev_cont_xretry;
740 	tx->pdev_tx_timeout = tx_stats->pdev_tx_timeout;
741 	tx->pdev_resets = tx_stats->pdev_resets;
742 	tx->stateless_tid_alloc_failure = tx_stats->stateless_tid_alloc_failure;
743 	tx->phy_underrun = tx_stats->phy_underrun;
744 	tx->txop_ovf = tx_stats->txop_ovf;
745 
746 	return;
747 }
748 
749 
750 /**
751  * extract_pdev_rx_stats() - extract pdev rx stats from event
752  */
753 static void extract_pdev_rx_stats(wmi_host_dbg_rx_stats *rx,
754 				  struct wlan_dbg_rx_stats *rx_stats)
755 {
756 	/* Rx Stats */
757 	rx->mid_ppdu_route_change = rx_stats->mid_ppdu_route_change;
758 	rx->status_rcvd = rx_stats->status_rcvd;
759 	rx->r0_frags = rx_stats->r0_frags;
760 	rx->r1_frags = rx_stats->r1_frags;
761 	rx->r2_frags = rx_stats->r2_frags;
762 	/* Only TLV */
763 	rx->r3_frags = 0;
764 	rx->htt_msdus = rx_stats->htt_msdus;
765 	rx->htt_mpdus = rx_stats->htt_mpdus;
766 	rx->loc_msdus = rx_stats->loc_msdus;
767 	rx->loc_mpdus = rx_stats->loc_mpdus;
768 	rx->oversize_amsdu = rx_stats->oversize_amsdu;
769 	rx->phy_errs = rx_stats->phy_errs;
770 	rx->phy_err_drop = rx_stats->phy_err_drop;
771 	rx->mpdu_errs = rx_stats->mpdu_errs;
772 
773 	return;
774 }
775 
776 /**
777  * extract_pdev_stats_tlv() - extract pdev stats from event
778  * @param wmi_handle: wmi handle
779  * @param evt_buf: pointer to event buffer
780  * @param index: Index into pdev stats
781  * @param pdev_stats: Pointer to hold pdev stats
782  *
783  * Return: QDF_STATUS_SUCCESS for success or error code
784  */
785 static QDF_STATUS
786 extract_pdev_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index,
787 		       wmi_host_pdev_stats *pdev_stats)
788 {
789 	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
790 	wmi_stats_event_fixed_param *ev_param;
791 	uint8_t *data;
792 
793 	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
794 	ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
795 	pdev_stats->pdev_id =
796 	     wmi_handle->ops->convert_pdev_id_target_to_host(wmi_handle,
797 							     ev_param->pdev_id);
798 
799 	data = param_buf->data;
800 
801 	if (index < ev_param->num_pdev_stats) {
802 		wmi_pdev_stats *ev = (wmi_pdev_stats *) ((data) +
803 				(index * sizeof(wmi_pdev_stats)));
804 
805 		pdev_stats->chan_nf = ev->chan_nf;
806 		pdev_stats->tx_frame_count = ev->tx_frame_count;
807 		pdev_stats->rx_frame_count = ev->rx_frame_count;
808 		pdev_stats->rx_clear_count = ev->rx_clear_count;
809 		pdev_stats->cycle_count = ev->cycle_count;
810 		pdev_stats->phy_err_count = ev->phy_err_count;
811 		pdev_stats->chan_tx_pwr = ev->chan_tx_pwr;
812 
813 		extract_pdev_tx_stats(&(pdev_stats->pdev_stats.tx),
814 			&(ev->pdev_stats.tx));
815 		extract_pdev_rx_stats(&(pdev_stats->pdev_stats.rx),
816 			&(ev->pdev_stats.rx));
817 	}
818 
819 	return QDF_STATUS_SUCCESS;
820 }
821 
822 /**
823  * extract_vdev_stats_tlv() - extract vdev stats from event
824  * @param wmi_handle: wmi handle
825  * @param evt_buf: pointer to event buffer
826  * @param index: Index into vdev stats
827  * @param vdev_stats: Pointer to hold vdev stats
828  *
829  * Return: QDF_STATUS_SUCCESS for success or error code
830  */
831 static QDF_STATUS extract_vdev_stats_tlv(wmi_unified_t wmi_handle,
832 	void *evt_buf, uint32_t index, wmi_host_vdev_stats *vdev_stats)
833 {
834 	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
835 	wmi_stats_event_fixed_param *ev_param;
836 	uint8_t *data;
837 
838 	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
839 	ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
840 	data = (uint8_t *) param_buf->data;
841 
842 	if (index < ev_param->num_vdev_stats) {
843 		wmi_vdev_stats *ev = (wmi_vdev_stats *) ((data) +
844 				((ev_param->num_pdev_stats) *
845 				sizeof(wmi_pdev_stats)) +
846 				(index * sizeof(wmi_vdev_stats)));
847 
848 		vdev_stats->vdev_id = ev->vdev_id;
849 		vdev_stats->vdev_snr.bcn_snr = ev->vdev_snr.bcn_snr;
850 		vdev_stats->vdev_snr.dat_snr = ev->vdev_snr.dat_snr;
851 
852 		OS_MEMCPY(vdev_stats->tx_frm_cnt, ev->tx_frm_cnt,
853 			sizeof(ev->tx_frm_cnt));
854 		vdev_stats->rx_frm_cnt = ev->rx_frm_cnt;
855 		OS_MEMCPY(vdev_stats->multiple_retry_cnt,
856 				ev->multiple_retry_cnt,
857 				sizeof(ev->multiple_retry_cnt));
858 		OS_MEMCPY(vdev_stats->fail_cnt, ev->fail_cnt,
859 				sizeof(ev->fail_cnt));
860 		vdev_stats->rts_fail_cnt = ev->rts_fail_cnt;
861 		vdev_stats->rts_succ_cnt = ev->rts_succ_cnt;
862 		vdev_stats->rx_err_cnt = ev->rx_err_cnt;
863 		vdev_stats->rx_discard_cnt = ev->rx_discard_cnt;
864 		vdev_stats->ack_fail_cnt = ev->ack_fail_cnt;
865 		OS_MEMCPY(vdev_stats->tx_rate_history, ev->tx_rate_history,
866 			sizeof(ev->tx_rate_history));
867 		OS_MEMCPY(vdev_stats->bcn_rssi_history, ev->bcn_rssi_history,
868 			sizeof(ev->bcn_rssi_history));
869 
870 	}
871 
872 	return QDF_STATUS_SUCCESS;
873 }
874 
875 /**
876  * extract_peer_stats_tlv() - extract peer stats from event
877  * @param wmi_handle: wmi handle
878  * @param evt_buf: pointer to event buffer
879  * @param index: Index into peer stats
880  * @param peer_stats: Pointer to hold peer stats
881  *
882  * Return: QDF_STATUS_SUCCESS for success or error code
883  */
884 static QDF_STATUS
885 extract_peer_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index,
886 		       wmi_host_peer_stats *peer_stats)
887 {
888 	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
889 	wmi_stats_event_fixed_param *ev_param;
890 	uint8_t *data;
891 
892 	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
893 	ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
894 	data = (uint8_t *) param_buf->data;
895 
896 	if (index < ev_param->num_peer_stats) {
897 		wmi_peer_stats *ev = (wmi_peer_stats *) ((data) +
898 			((ev_param->num_pdev_stats) * sizeof(wmi_pdev_stats)) +
899 			((ev_param->num_vdev_stats) * sizeof(wmi_vdev_stats)) +
900 			(index * sizeof(wmi_peer_stats)));
901 
902 		OS_MEMSET(peer_stats, 0, sizeof(wmi_host_peer_stats));
903 
904 		OS_MEMCPY(&(peer_stats->peer_macaddr),
905 			&(ev->peer_macaddr), sizeof(wmi_mac_addr));
906 
907 		peer_stats->peer_rssi = ev->peer_rssi;
908 		peer_stats->peer_tx_rate = ev->peer_tx_rate;
909 		peer_stats->peer_rx_rate = ev->peer_rx_rate;
910 	}
911 
912 	return QDF_STATUS_SUCCESS;
913 }
914 
915 /**
916  * extract_peer_extd_stats_tlv() - extract extended peer stats from event
917  * @param wmi_handle: wmi handle
918  * @param evt_buf: pointer to event buffer
919  * @param index: Index into extended peer stats
920  * @param peer_extd_stats: Pointer to hold extended peer stats
921  *
922  * Return: QDF_STATUS_SUCCESS for success or error code
923  */
924 static QDF_STATUS
925 extract_peer_extd_stats_tlv(wmi_unified_t wmi_handle,
926 			    void *evt_buf, uint32_t index,
927 			    wmi_host_peer_extd_stats *peer_extd_stats)
928 {
929 	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
930 	wmi_stats_event_fixed_param *ev_param;
931 	uint8_t *data;
932 
933 	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf;
934 	ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param;
935 	data = (uint8_t *)param_buf->data;
936 	if (!data)
937 		return QDF_STATUS_E_FAILURE;
938 
939 	if (index < ev_param->num_peer_extd_stats) {
940 		wmi_peer_extd_stats *ev = (wmi_peer_extd_stats *) (data +
941 			(ev_param->num_pdev_stats * sizeof(wmi_pdev_stats)) +
942 			(ev_param->num_vdev_stats * sizeof(wmi_vdev_stats)) +
943 			(ev_param->num_peer_stats * sizeof(wmi_peer_stats)) +
944 			(ev_param->num_bcnflt_stats *
945 			sizeof(wmi_bcnfilter_stats_t)) +
946 			(ev_param->num_chan_stats * sizeof(wmi_chan_stats)) +
947 			(ev_param->num_mib_stats * sizeof(wmi_mib_stats)) +
948 			(ev_param->num_bcn_stats * sizeof(wmi_bcn_stats)) +
949 			(index * sizeof(wmi_peer_extd_stats)));
950 
951 		qdf_mem_zero(peer_extd_stats, sizeof(wmi_host_peer_extd_stats));
952 		qdf_mem_copy(&peer_extd_stats->peer_macaddr, &ev->peer_macaddr,
953 			     sizeof(wmi_mac_addr));
954 
955 		peer_extd_stats->rx_mc_bc_cnt = ev->rx_mc_bc_cnt;
956 	}
957 
958 	return QDF_STATUS_SUCCESS;
959 
960 }
961 
962 /**
963  * extract_pmf_bcn_protect_stats_tlv() - extract pmf bcn stats from event
964  * @wmi_handle: wmi handle
965  * @evt_buf: pointer to event buffer
966  * @pmf_bcn_stats: Pointer to hold pmf bcn protect stats
967  *
968  * Return: QDF_STATUS_SUCCESS for success or error code
969  */
970 
971 static QDF_STATUS
972 extract_pmf_bcn_protect_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf,
973 				  wmi_host_pmf_bcn_protect_stats *pmf_bcn_stats)
974 {
975 	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
976 	wmi_stats_event_fixed_param *ev_param;
977 
978 	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf;
979 	if (!param_buf)
980 		return QDF_STATUS_E_FAILURE;
981 
982 	ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param;
983 
984 	if ((ev_param->stats_id & WMI_REQUEST_PMF_BCN_PROTECT_STAT) &&
985 	    param_buf->pmf_bcn_protect_stats) {
986 		pmf_bcn_stats->igtk_mic_fail_cnt =
987 			param_buf->pmf_bcn_protect_stats->igtk_mic_fail_cnt;
988 		pmf_bcn_stats->igtk_replay_cnt =
989 			param_buf->pmf_bcn_protect_stats->igtk_replay_cnt;
990 		pmf_bcn_stats->bcn_mic_fail_cnt =
991 			param_buf->pmf_bcn_protect_stats->bcn_mic_fail_cnt;
992 		pmf_bcn_stats->bcn_replay_cnt =
993 			param_buf->pmf_bcn_protect_stats->bcn_replay_cnt;
994 	}
995 
996 	return QDF_STATUS_SUCCESS;
997 }
998 
999 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
1000 static void wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops *ops)
1001 {
1002 	ops->send_infra_cp_stats_request_cmd =
1003 					send_infra_cp_stats_request_cmd_tlv;
1004 }
1005 #else
1006 static void wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops *ops)
1007 {
1008 }
1009 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
1010 
1011 #ifdef WLAN_FEATURE_SON
1012 /**
1013  * extract_inst_rssi_stats_resp_tlv() - extract inst rssi stats from event
1014  * @wmi_handle: wmi handle
1015  * @evt_buf: pointer to event buffer
1016  * @inst_rssi_resp: Pointer to hold inst rssi response
1017  *
1018  * @Return: QDF_STATUS_SUCCESS for success or error code
1019  */
1020 static QDF_STATUS
1021 extract_inst_rssi_stats_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf,
1022 			struct wmi_host_inst_rssi_stats_resp *inst_rssi_resp)
1023 {
1024 	WMI_INST_RSSI_STATS_EVENTID_param_tlvs *param_buf;
1025 	wmi_inst_rssi_stats_resp_fixed_param *event;
1026 
1027 	param_buf = (WMI_INST_RSSI_STATS_EVENTID_param_tlvs *)evt_buf;
1028 	event = (wmi_inst_rssi_stats_resp_fixed_param *)param_buf->fixed_param;
1029 
1030 	inst_rssi_resp->inst_rssi = event->iRSSI;
1031 	WMI_CHAR_ARRAY_TO_MAC_ADDR(inst_rssi_resp->peer_macaddr.bytes,
1032 				   &event->peer_macaddr);
1033 	inst_rssi_resp->vdev_id = event->vdev_id;
1034 
1035 	return QDF_STATUS_SUCCESS;
1036 }
1037 
1038 static void
1039 wmi_inst_rssi_stats_ops_attach_tlv(struct wmi_ops *ops)
1040 {
1041 	ops->extract_inst_rssi_stats_resp = extract_inst_rssi_stats_resp_tlv;
1042 }
1043 #else
1044 static void
1045 wmi_inst_rssi_stats_ops_attach_tlv(struct wmi_ops *ops)
1046 {
1047 }
1048 #endif
1049 
1050 void wmi_cp_stats_attach_tlv(wmi_unified_t wmi_handle)
1051 {
1052 	struct wmi_ops *ops = wmi_handle->ops;
1053 
1054 	ops->send_stats_request_cmd = send_stats_request_cmd_tlv;
1055 #ifdef WLAN_FEATURE_BIG_DATA_STATS
1056 	ops->send_big_data_stats_request_cmd =
1057 				send_big_data_stats_request_cmd_tlv;
1058 #endif
1059 	ops->extract_all_stats_count = extract_all_stats_counts_tlv;
1060 	ops->extract_pdev_stats = extract_pdev_stats_tlv;
1061 	ops->extract_vdev_stats = extract_vdev_stats_tlv;
1062 	ops->extract_peer_stats = extract_peer_stats_tlv;
1063 	ops->extract_peer_extd_stats = extract_peer_extd_stats_tlv;
1064 	wmi_infra_cp_stats_ops_attach_tlv(ops);
1065 	ops->extract_pmf_bcn_protect_stats = extract_pmf_bcn_protect_stats_tlv,
1066 	wmi_inst_rssi_stats_ops_attach_tlv(ops);
1067 
1068 	wmi_mc_cp_stats_attach_tlv(wmi_handle);
1069 }
1070