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