1 /*
2  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: target_if_cp_stats.c
22  *
23  * This file provide definition for APIs registered through lmac Tx Ops
24  */
25 
26 #include <qdf_mem.h>
27 #include <qdf_status.h>
28 #include <target_if_cp_stats.h>
29 #include <wmi_unified_priv.h>
30 #include <wmi_unified_param.h>
31 #include <target_if.h>
32 #include <wlan_tgt_def_config.h>
33 #include <wmi_unified_api.h>
34 #include <wlan_osif_priv.h>
35 #include <wlan_cp_stats_utils_api.h>
36 #include <wlan_cp_stats_mc_tgt_api.h>
37 #include "../../../umac/cmn_services/utils/inc/wlan_utility.h"
38 #include <cdp_txrx_cmn_struct.h>
39 #include <cdp_txrx_ops.h>
40 #include <cdp_txrx_stats_struct.h>
41 #include <cdp_txrx_host_stats.h>
42 #include <cdp_txrx_ctrl.h>
43 #include <cds_api.h>
44 #ifdef WLAN_FEATURE_SON
45 #include "son_api.h"
46 #endif
47 
48 #if defined(WLAN_SUPPORT_TWT) && defined(WLAN_TWT_CONV_SUPPORTED)
49 static QDF_STATUS
target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc * psoc)50 target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc *psoc)
51 {
52 	return QDF_STATUS_SUCCESS;
53 }
54 
55 static QDF_STATUS
target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc * psoc)56 target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc *psoc)
57 {
58 	return QDF_STATUS_SUCCESS;
59 }
60 #elif defined(WLAN_SUPPORT_TWT) && !defined(WLAN_TWT_CONV_SUPPORTED)
61 
62 #include <wmi.h>
63 #include <wlan_cp_stats_mc_ucfg_api.h>
64 
65 /**
66  * target_if_twt_fill_peer_twt_session_params() - Fills peer twt session
67  * parameter obtained from firmware into mc_cp_stats of peer
68  * @mc_cp_stats: Pointer to Peer mc_cp stats
69  * @twt_params: twt session parameters to be copied
70  *
71  * Return: None
72  */
target_if_twt_fill_peer_twt_session_params(struct peer_mc_cp_stats * mc_cp_stats,struct wmi_host_twt_session_stats_info * twt_params)73 static void target_if_twt_fill_peer_twt_session_params
74 (
75 	struct peer_mc_cp_stats *mc_cp_stats,
76 	struct wmi_host_twt_session_stats_info *twt_params
77 )
78 {
79 	uint32_t event_type;
80 	int i = 0;
81 
82 	if (!mc_cp_stats || !twt_params)
83 		return;
84 
85 	if ((twt_params->event_type == HOST_TWT_SESSION_UPDATE) ||
86 	    (twt_params->event_type == HOST_TWT_SESSION_TEARDOWN)) {
87 		/* Update for a existing session, find by dialog_id */
88 		for (i = 0; i < TWT_PEER_MAX_SESSIONS; i++) {
89 			if (mc_cp_stats->twt_param[i].dialog_id !=
90 			    twt_params->dialog_id)
91 				continue;
92 			qdf_mem_copy(&mc_cp_stats->twt_param[i], twt_params,
93 				     sizeof(*twt_params));
94 			return;
95 		}
96 	} else if (twt_params->event_type == HOST_TWT_SESSION_SETUP) {
97 		/* New session, fill in any existing invalid session */
98 		for (i = 0; i < TWT_PEER_MAX_SESSIONS; i++) {
99 			event_type = mc_cp_stats->twt_param[i].event_type;
100 			if ((event_type != HOST_TWT_SESSION_SETUP) &&
101 			    (event_type != HOST_TWT_SESSION_UPDATE)) {
102 				qdf_mem_copy(&mc_cp_stats->twt_param[i],
103 					     twt_params,
104 					     sizeof(*twt_params));
105 				return;
106 			}
107 		}
108 	}
109 
110 	target_if_err("Unable to save twt session params with dialog id %d",
111 		      twt_params->dialog_id);
112 }
113 
114 /**
115  * target_if_obtain_mc_cp_stat_obj() - Retrieves peer mc cp stats object
116  * @peer_obj: peer object
117  *
118  * Return: mc cp stats object on success or NULL
119  */
120 static struct peer_mc_cp_stats *
target_if_obtain_mc_cp_stat_obj(struct wlan_objmgr_peer * peer_obj)121 target_if_obtain_mc_cp_stat_obj(struct wlan_objmgr_peer *peer_obj)
122 {
123 	struct peer_cp_stats *cp_stats_peer_obj;
124 	struct peer_mc_cp_stats *mc_cp_stats;
125 
126 	cp_stats_peer_obj = wlan_objmgr_peer_get_comp_private_obj
127 				(peer_obj, WLAN_UMAC_COMP_CP_STATS);
128 	if (!cp_stats_peer_obj) {
129 		target_if_err("cp peer stats obj err");
130 		return NULL;
131 	}
132 
133 	mc_cp_stats = cp_stats_peer_obj->peer_stats;
134 	if (!mc_cp_stats) {
135 		target_if_err("mc stats obj err");
136 		return NULL;
137 	}
138 	return mc_cp_stats;
139 }
140 
141 /**
142  * target_if_twt_session_params_event_handler() - Handles twt session stats
143  * event from firmware and store the per peer twt session parameters in
144  * mc_cp_stats
145  * @scn: scn handle
146  * @evt_buf: data buffer for event
147  * @evt_data_len: data length of event
148  *
149  * Return: 0 on success, else error values
150  */
target_if_twt_session_params_event_handler(ol_scn_t scn,uint8_t * evt_buf,uint32_t evt_data_len)151 static int target_if_twt_session_params_event_handler(ol_scn_t scn,
152 						      uint8_t *evt_buf,
153 						      uint32_t evt_data_len)
154 {
155 	struct wlan_objmgr_psoc *psoc_obj;
156 	struct wlan_objmgr_peer *peer_obj;
157 	struct wmi_unified *wmi_hdl;
158 	struct wmi_host_twt_session_stats_info twt_params;
159 	struct wmi_twt_session_stats_event_param params = {0};
160 	struct peer_mc_cp_stats *mc_cp_stats;
161 	struct peer_cp_stats *peer_cp_stats_priv;
162 	uint32_t expected_len;
163 	int i;
164 	QDF_STATUS status;
165 
166 	if (!scn || !evt_buf) {
167 		target_if_err("scn: 0x%pK, evt_buf: 0x%pK", scn, evt_buf);
168 		return -EINVAL;
169 	}
170 
171 	psoc_obj = target_if_get_psoc_from_scn_hdl(scn);
172 	if (!psoc_obj) {
173 		target_if_err("psoc object is null!");
174 		return -EINVAL;
175 	}
176 
177 	wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc_obj);
178 	if (!wmi_hdl) {
179 		target_if_err("wmi_handle is null!");
180 		return -EINVAL;
181 	}
182 
183 	status = wmi_extract_twt_session_stats_event(wmi_hdl, evt_buf, &params);
184 	if (QDF_IS_STATUS_ERROR(status)) {
185 		target_if_err("Could not extract twt session stats event");
186 		return qdf_status_to_os_return(status);
187 	}
188 
189 	if (params.num_sessions > TWT_PEER_MAX_SESSIONS) {
190 		target_if_err("no of twt sessions exceeded the max supported");
191 		return -EINVAL;
192 	}
193 
194 	expected_len = (sizeof(wmi_pdev_twt_session_stats_event_fixed_param) +
195 			WMI_TLV_HDR_SIZE + (params.num_sessions *
196 			sizeof(wmi_twt_session_stats_info)));
197 
198 	if (evt_data_len < expected_len) {
199 		target_if_err("Got invalid len of data from FW %d expected %d",
200 			      evt_data_len, expected_len);
201 		return -EINVAL;
202 	}
203 
204 	for (i = 0; i < params.num_sessions; i++) {
205 		status = wmi_extract_twt_session_stats_data(wmi_hdl, evt_buf,
206 							    &params,
207 							    &twt_params, i);
208 		if (QDF_IS_STATUS_ERROR(status)) {
209 			target_if_err("Unable to extract twt params for idx %d",
210 				      i);
211 			return -EINVAL;
212 		}
213 
214 		peer_obj = wlan_objmgr_get_peer_by_mac(psoc_obj,
215 						       twt_params.peer_mac,
216 						       WLAN_CP_STATS_ID);
217 		if (!peer_obj) {
218 			target_if_err("peer obj not found for "
219 				      QDF_MAC_ADDR_FMT,
220 				      QDF_MAC_ADDR_REF(twt_params.peer_mac));
221 			continue;
222 		}
223 
224 		peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer_obj);
225 		if (!peer_cp_stats_priv) {
226 			target_if_err("peer_cp_stats_priv is null");
227 			continue;
228 		}
229 
230 		mc_cp_stats = target_if_obtain_mc_cp_stat_obj(peer_obj);
231 		if (!mc_cp_stats) {
232 			target_if_err("Unable to retrieve mc cp stats obj for "
233 				      QDF_MAC_ADDR_FMT,
234 				      QDF_MAC_ADDR_REF(twt_params.peer_mac));
235 			wlan_objmgr_peer_release_ref(peer_obj,
236 						     WLAN_CP_STATS_ID);
237 			continue;
238 		}
239 
240 		wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
241 		target_if_twt_fill_peer_twt_session_params(mc_cp_stats,
242 							   &twt_params);
243 		wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
244 
245 		wlan_objmgr_peer_release_ref(peer_obj, WLAN_CP_STATS_ID);
246 	}
247 	return 0;
248 }
249 
250 /**
251  * target_if_twt_session_params_unregister_evt_hdlr() - Unregister the
252  * event handler registered for wmi event wmi_twt_session_stats_event_id
253  * @psoc: psoc object
254  *
255  * Return: QDF_STATUS_SUCCESS on success or QDF error values on failure
256  */
257 static QDF_STATUS
target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc * psoc)258 target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc *psoc)
259 {
260 	struct wmi_unified *wmi_handle;
261 
262 	if (!psoc) {
263 		target_if_err("psoc obj in null!");
264 		return QDF_STATUS_E_NULL_VALUE;
265 	}
266 
267 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
268 	if (!wmi_handle) {
269 		target_if_err("wmi_handle is null!");
270 		return QDF_STATUS_E_INVAL;
271 	}
272 
273 	wmi_unified_unregister_event_handler(wmi_handle,
274 					     wmi_twt_session_stats_event_id);
275 
276 	return QDF_STATUS_SUCCESS;
277 }
278 
279 /**
280  * target_if_twt_session_params_register_evt_hdlr() - Register a event
281  * handler with wmi layer for wmi event wmi_twt_session_stats_event_id
282  * @psoc: psoc object
283  *
284  * Return: QDF_STATUS_SUCCESS on success or QDF error values on failure
285  */
286 static QDF_STATUS
target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc * psoc)287 target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc *psoc)
288 {
289 	QDF_STATUS ret_val;
290 	struct wmi_unified *wmi_handle;
291 
292 	if (!psoc) {
293 		target_if_err("psoc obj in null!");
294 		return QDF_STATUS_E_NULL_VALUE;
295 	}
296 
297 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
298 	if (!wmi_handle) {
299 		target_if_err("wmi_handle is null!");
300 		return QDF_STATUS_E_INVAL;
301 	}
302 
303 	ret_val = wmi_unified_register_event_handler(
304 			wmi_handle,
305 			wmi_twt_session_stats_event_id,
306 			target_if_twt_session_params_event_handler,
307 			WMI_RX_WORK_CTX);
308 
309 	if (QDF_IS_STATUS_ERROR(ret_val))
310 		target_if_err("Failed to register twt session stats event cb");
311 
312 	return ret_val;
313 }
314 #else
315 static QDF_STATUS
target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc * psoc)316 target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc *psoc)
317 {
318 	return QDF_STATUS_SUCCESS;
319 }
320 
321 static QDF_STATUS
target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc * psoc)322 target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc *psoc)
323 {
324 	return QDF_STATUS_SUCCESS;
325 }
326 #endif /* WLAN_SUPPORT_TWT */
327 
328 #ifdef WLAN_FEATURE_MIB_STATS
target_if_cp_stats_free_mib_stats(struct stats_event * ev)329 static void target_if_cp_stats_free_mib_stats(struct stats_event *ev)
330 {
331 	qdf_mem_free(ev->mib_stats);
332 	ev->mib_stats = NULL;
333 }
334 #else
target_if_cp_stats_free_mib_stats(struct stats_event * ev)335 static void target_if_cp_stats_free_mib_stats(struct stats_event *ev)
336 {
337 }
338 #endif
339 
340 /**
341  * target_if_cp_stats_free_peer_stats_info_ext() - API to free peer stats
342  * info ext structure
343  * @ev: structure from where peer stats info ext needs to be freed
344  *
345  * Return: none
346  */
target_if_cp_stats_free_peer_stats_info_ext(struct stats_event * ev)347 static void target_if_cp_stats_free_peer_stats_info_ext(struct stats_event *ev)
348 {
349 	struct peer_stats_info_ext_event *peer_stats_info =
350 							ev->peer_stats_info_ext;
351 	uint16_t i;
352 
353 	for (i = 0; i < ev->num_peer_stats_info_ext; i++) {
354 		qdf_mem_free(peer_stats_info->tx_pkt_per_mcs);
355 		peer_stats_info->tx_pkt_per_mcs = NULL;
356 		qdf_mem_free(peer_stats_info->rx_pkt_per_mcs);
357 		peer_stats_info->rx_pkt_per_mcs = NULL;
358 		peer_stats_info++;
359 	}
360 
361 	qdf_mem_free(ev->peer_stats_info_ext);
362 	ev->peer_stats_info_ext = NULL;
363 	ev->num_peer_stats_info_ext = 0;
364 }
365 
target_if_cp_stats_free_stats_event(struct stats_event * ev)366 static void target_if_cp_stats_free_stats_event(struct stats_event *ev)
367 {
368 	qdf_mem_free(ev->pdev_stats);
369 	ev->pdev_stats = NULL;
370 	qdf_mem_free(ev->pdev_extd_stats);
371 	ev->pdev_extd_stats = NULL;
372 	qdf_mem_free(ev->peer_stats);
373 	ev->peer_stats = NULL;
374 	qdf_mem_free(ev->peer_adv_stats);
375 	ev->peer_adv_stats = NULL;
376 	qdf_mem_free(ev->peer_extended_stats);
377 	ev->peer_extended_stats = NULL;
378 	qdf_mem_free(ev->cca_stats);
379 	ev->cca_stats = NULL;
380 	qdf_mem_free(ev->vdev_summary_stats);
381 	ev->vdev_summary_stats = NULL;
382 	qdf_mem_free(ev->vdev_chain_rssi);
383 	ev->vdev_chain_rssi = NULL;
384 	target_if_cp_stats_free_mib_stats(ev);
385 	target_if_cp_stats_free_peer_stats_info_ext(ev);
386 	qdf_mem_free(ev->vdev_extd_stats);
387 	ev->vdev_extd_stats = NULL;
388 }
389 
target_if_cp_stats_extract_pdev_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)390 static QDF_STATUS target_if_cp_stats_extract_pdev_stats(
391 					struct wmi_unified *wmi_hdl,
392 					wmi_host_stats_event *stats_param,
393 					struct stats_event *ev,
394 					uint8_t *data)
395 {
396 	uint32_t i;
397 	QDF_STATUS status;
398 	wmi_host_pdev_stats *pdev_stats;
399 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
400 	cdp_config_param_type val;
401 
402 	ev->num_pdev_stats = stats_param->num_pdev_stats;
403 	if (!ev->num_pdev_stats)
404 		return QDF_STATUS_SUCCESS;
405 
406 	/*
407 	 * num_pdev_stats is validated within function wmi_extract_stats_param
408 	 * which is called to populated wmi_host_stats_event stats_param
409 	 */
410 	ev->pdev_stats = qdf_mem_malloc(sizeof(*ev->pdev_stats) *
411 						ev->num_pdev_stats);
412 	if (!ev->pdev_stats)
413 		return QDF_STATUS_E_NOMEM;
414 
415 	pdev_stats = qdf_mem_malloc(sizeof(*pdev_stats));
416 
417 	if (!pdev_stats) {
418 		cp_stats_err("malloc failed for pdev_stats");
419 		return QDF_STATUS_E_NOMEM;
420 	}
421 
422 	for (i = 0; i < ev->num_pdev_stats; i++) {
423 		status = wmi_extract_pdev_stats(wmi_hdl, data, i, pdev_stats);
424 		if (QDF_IS_STATUS_ERROR(status)) {
425 			cp_stats_err("wmi_extract_pdev_stats failed");
426 			qdf_mem_free(pdev_stats);
427 			return status;
428 		}
429 
430 		/*
431 		 * It's 0.5 db unit from halphy. so correct the value here
432 		 */
433 		ev->pdev_stats[i].max_pwr = pdev_stats->chan_tx_pwr >> 1;
434 
435 		ev->pdev_stats[i].pdev_id = pdev_stats->pdev_id;
436 		ev->pdev_stats[i].rx_clear_count = pdev_stats->rx_clear_count;
437 		ev->pdev_stats[i].tx_frame_count = pdev_stats->tx_frame_count;
438 		ev->pdev_stats[i].cycle_count = pdev_stats->cycle_count;
439 
440 		val.cdp_pdev_param_chn_noise_flr = pdev_stats->chan_nf;
441 		cdp_txrx_set_pdev_param(soc, 0, CDP_CHAN_NOISE_FLOOR, val);
442 	}
443 	qdf_mem_free(pdev_stats);
444 
445 	return QDF_STATUS_SUCCESS;
446 }
447 
target_if_cp_stats_extract_pmf_bcn_protect_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)448 static QDF_STATUS target_if_cp_stats_extract_pmf_bcn_protect_stats(
449 					struct wmi_unified *wmi_hdl,
450 					wmi_host_stats_event *stats_param,
451 					struct stats_event *ev, uint8_t *data)
452 {
453 	QDF_STATUS status;
454 	wmi_host_pmf_bcn_protect_stats pmf_bcn_stats = {0};
455 
456 	if (!(stats_param->stats_id & WMI_HOST_REQUEST_PMF_BCN_PROTECT_STAT))
457 		return QDF_STATUS_SUCCESS;
458 
459 	qdf_mem_zero(&ev->bcn_protect_stats, sizeof(ev->bcn_protect_stats));
460 	status = wmi_extract_pmf_bcn_protect_stats(wmi_hdl, data,
461 						   &pmf_bcn_stats);
462 	if (QDF_IS_STATUS_ERROR(status)) {
463 		cp_stats_err("wmi_extract_pmf_bcn_protect_stats failed");
464 		return status;
465 	}
466 
467 	ev->bcn_protect_stats.pmf_bcn_stats_valid = true;
468 	ev->bcn_protect_stats.igtk_mic_fail_cnt =
469 			pmf_bcn_stats.igtk_mic_fail_cnt;
470 	ev->bcn_protect_stats.igtk_replay_cnt =
471 			pmf_bcn_stats.igtk_replay_cnt;
472 	ev->bcn_protect_stats.bcn_mic_fail_cnt =
473 			pmf_bcn_stats.bcn_mic_fail_cnt;
474 	ev->bcn_protect_stats.bcn_replay_cnt =
475 			pmf_bcn_stats.bcn_replay_cnt;
476 
477 	return QDF_STATUS_SUCCESS;
478 }
479 
480 static QDF_STATUS
target_if_cp_stats_extract_pdev_extd_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)481 target_if_cp_stats_extract_pdev_extd_stats(struct wmi_unified *wmi_hdl,
482 					   wmi_host_stats_event *stats_param,
483 					   struct stats_event *ev,
484 					   uint8_t *data)
485 {
486 	uint32_t i;
487 	QDF_STATUS status;
488 	wmi_host_pdev_ext_stats *pdev_extd_stats;
489 
490 	if (!(stats_param->stats_id & WMI_REQUEST_PDEV_EXTD_STAT))
491 		return QDF_STATUS_SUCCESS;
492 
493 	ev->pdev_extd_stats = qdf_mem_malloc(sizeof(*ev->pdev_extd_stats) *
494 					     WLAN_UMAC_MAX_RP_PID);
495 	if (!ev->pdev_extd_stats)
496 		return QDF_STATUS_E_NOMEM;
497 
498 	pdev_extd_stats = qdf_mem_malloc(sizeof(*pdev_extd_stats));
499 	if (!pdev_extd_stats)
500 		return QDF_STATUS_E_NOMEM;
501 
502 	ev->num_pdev_extd_stats = 0;
503 	for (i = 0; i < stats_param->num_pdev_ext_stats; i++) {
504 		qdf_mem_set(pdev_extd_stats, sizeof(*pdev_extd_stats), 0);
505 
506 		status = wmi_extract_pdev_ext_stats(wmi_hdl, data, i,
507 						    pdev_extd_stats);
508 		if (QDF_IS_STATUS_ERROR(status)) {
509 			qdf_mem_free(pdev_extd_stats);
510 			cp_stats_err("wmi_extract_pdev_ext_stats failed");
511 			return status;
512 		}
513 
514 		ev->num_pdev_extd_stats++;
515 		ev->pdev_extd_stats[i].pdev_id =
516 			pdev_extd_stats->pdev_id;
517 		ev->pdev_extd_stats[i].my_rx_count =
518 			pdev_extd_stats->my_rx_count;
519 		ev->pdev_extd_stats[i].rx_matched_11ax_msdu_cnt =
520 			pdev_extd_stats->rx_matched_11ax_msdu_cnt;
521 		ev->pdev_extd_stats[i].rx_other_11ax_msdu_cnt =
522 			pdev_extd_stats->rx_other_11ax_msdu_cnt;
523 	}
524 
525 	qdf_mem_free(pdev_extd_stats);
526 	return QDF_STATUS_SUCCESS;
527 }
528 
target_if_cp_stats_extract_peer_extd_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)529 static void target_if_cp_stats_extract_peer_extd_stats(
530 	struct wmi_unified *wmi_hdl,
531 	wmi_host_stats_event *stats_param,
532 	struct stats_event *ev,
533 	uint8_t *data)
534 
535 {
536 	QDF_STATUS status;
537 	uint32_t i;
538 	wmi_host_peer_extd_stats peer_extd_stats;
539 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
540 	struct cdp_peer_stats *peer_stats;
541 
542 	if (!stats_param->num_peer_extd_stats)
543 		return;
544 
545 	ev->peer_extended_stats =
546 			qdf_mem_malloc(sizeof(*ev->peer_extended_stats) *
547 				       stats_param->num_peer_extd_stats);
548 	if (!ev->peer_extended_stats)
549 		return;
550 
551 	ev->num_peer_extd_stats = stats_param->num_peer_extd_stats;
552 
553 	for (i = 0; i < ev->num_peer_extd_stats; i++) {
554 		status = wmi_extract_peer_extd_stats(wmi_hdl, data, i,
555 						     &peer_extd_stats);
556 		if (QDF_IS_STATUS_ERROR(status)) {
557 			cp_stats_err("wmi_extract_peer_extd_stats failed");
558 			continue;
559 		}
560 		WMI_MAC_ADDR_TO_CHAR_ARRAY(
561 			     &peer_extd_stats.peer_macaddr,
562 			ev->peer_extended_stats[i].peer_macaddr);
563 		ev->peer_extended_stats[i].rx_mc_bc_cnt =
564 						peer_extd_stats.rx_mc_bc_cnt;
565 
566 		peer_stats = qdf_mem_malloc(sizeof(*peer_stats));
567 		if (!peer_stats)
568 			continue;
569 
570 		status = cdp_host_get_peer_stats(soc, VDEV_ALL,
571 					ev->peer_extended_stats[i].peer_macaddr,
572 					peer_stats);
573 		if (status == QDF_STATUS_SUCCESS)
574 			ev->peer_extended_stats[i].rx_mc_bc_cnt =
575 				peer_stats->rx.multicast.num +
576 				peer_stats->rx.bcast.num;
577 
578 		qdf_mem_free(peer_stats);
579 	}
580 }
581 
target_if_cp_stats_extract_peer_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)582 static QDF_STATUS target_if_cp_stats_extract_peer_stats(
583 					struct wmi_unified *wmi_hdl,
584 					wmi_host_stats_event *stats_param,
585 					struct stats_event *ev,
586 					uint8_t *data)
587 {
588 	uint32_t i;
589 	QDF_STATUS status;
590 	wmi_host_peer_stats peer_stats;
591 	bool db2dbm_enabled;
592 	struct wmi_host_peer_adv_stats *peer_adv_stats;
593 
594 	/* Extract peer_stats */
595 	if (!stats_param->num_peer_stats)
596 		goto adv_stats;
597 
598 	ev->peer_stats = qdf_mem_malloc(sizeof(*ev->peer_stats) *
599 						stats_param->num_peer_stats);
600 	if (!ev->peer_stats)
601 		return QDF_STATUS_E_NOMEM;
602 	ev->num_peer_stats = stats_param->num_peer_stats;
603 
604 	db2dbm_enabled = wmi_service_enabled(wmi_hdl,
605 					     wmi_service_hw_db2dbm_support);
606 	for (i = 0; i < ev->num_peer_stats; i++) {
607 		status = wmi_extract_peer_stats(wmi_hdl, data, i, &peer_stats);
608 		if (QDF_IS_STATUS_ERROR(status)) {
609 			cp_stats_err("wmi_extract_peer_stats failed");
610 			continue;
611 		}
612 		WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats.peer_macaddr,
613 					   ev->peer_stats[i].peer_macaddr);
614 		ev->peer_stats[i].tx_rate = peer_stats.peer_tx_rate;
615 		ev->peer_stats[i].rx_rate = peer_stats.peer_rx_rate;
616 		if (db2dbm_enabled)
617 			ev->peer_stats[i].peer_rssi = peer_stats.peer_rssi;
618 		else
619 			ev->peer_stats[i].peer_rssi = peer_stats.peer_rssi +
620 							TGT_NOISE_FLOOR_DBM;
621 	}
622 
623 adv_stats:
624 	target_if_cp_stats_extract_peer_extd_stats(wmi_hdl, stats_param, ev,
625 						   data);
626 
627 	/* Extract peer_adv_stats */
628 	ev->num_peer_adv_stats = stats_param->num_peer_adv_stats;
629 	if (!ev->num_peer_adv_stats)
630 		return QDF_STATUS_SUCCESS;
631 
632 	ev->peer_adv_stats = qdf_mem_malloc(sizeof(*ev->peer_adv_stats) *
633 					    ev->num_peer_adv_stats);
634 	if (!ev->peer_adv_stats)
635 		return QDF_STATUS_E_NOMEM;
636 
637 	peer_adv_stats = qdf_mem_malloc(sizeof(*peer_adv_stats) *
638 					ev->num_peer_adv_stats);
639 	if (!peer_adv_stats) {
640 		qdf_mem_free(ev->peer_adv_stats);
641 		return QDF_STATUS_E_NOMEM;
642 	}
643 
644 	status = wmi_extract_peer_adv_stats(wmi_hdl, data, peer_adv_stats);
645 	if (QDF_IS_STATUS_ERROR(status)) {
646 		cp_stats_err("wmi_extract_peer_stats failed");
647 		qdf_mem_free(peer_adv_stats);
648 		qdf_mem_free(ev->peer_adv_stats);
649 		ev->peer_adv_stats = NULL;
650 		return QDF_STATUS_SUCCESS;
651 	}
652 
653 	for (i = 0; i < ev->num_peer_adv_stats; i++) {
654 		qdf_mem_copy(&ev->peer_adv_stats[i].peer_macaddr,
655 			     &peer_adv_stats[i].peer_macaddr,
656 			     QDF_MAC_ADDR_SIZE);
657 		ev->peer_adv_stats[i].fcs_count = peer_adv_stats[i].fcs_count;
658 		ev->peer_adv_stats[i].rx_bytes = peer_adv_stats[i].rx_bytes;
659 		ev->peer_adv_stats[i].rx_count = peer_adv_stats[i].rx_count;
660 	}
661 	qdf_mem_free(peer_adv_stats);
662 	return QDF_STATUS_SUCCESS;
663 }
664 
target_if_cp_stats_extract_cca_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)665 static QDF_STATUS target_if_cp_stats_extract_cca_stats(
666 					struct wmi_unified *wmi_hdl,
667 					wmi_host_stats_event *stats_param,
668 					struct stats_event *ev, uint8_t *data)
669 {
670 	QDF_STATUS status;
671 	struct wmi_host_congestion_stats stats = {0};
672 
673 	status = wmi_extract_cca_stats(wmi_hdl, data, &stats);
674 	if (QDF_IS_STATUS_ERROR(status))
675 		return QDF_STATUS_SUCCESS;
676 
677 	ev->cca_stats = qdf_mem_malloc(sizeof(*ev->cca_stats));
678 	if (!ev->cca_stats)
679 		return QDF_STATUS_E_NOMEM;
680 
681 	ev->cca_stats->vdev_id = stats.vdev_id;
682 	ev->cca_stats->congestion = stats.congestion;
683 
684 	return QDF_STATUS_SUCCESS;
685 }
686 
687 #ifdef WLAN_FEATURE_MIB_STATS
target_if_cp_stats_extract_mib_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)688 static QDF_STATUS target_if_cp_stats_extract_mib_stats(
689 					struct wmi_unified *wmi_hdl,
690 					wmi_host_stats_event *stats_param,
691 					struct stats_event *ev, uint8_t *data)
692 {
693 	QDF_STATUS status;
694 
695 	if (!stats_param->num_mib_stats)
696 		return QDF_STATUS_SUCCESS;
697 
698 	if (stats_param->num_mib_stats != MAX_MIB_STATS ||
699 	    (stats_param->num_mib_extd_stats &&
700 	    stats_param->num_mib_extd_stats != MAX_MIB_STATS)) {
701 		cp_stats_err("number of mib stats wrong, num_mib_stats %d, num_mib_extd_stats %d",
702 			     stats_param->num_mib_stats,
703 			     stats_param->num_mib_extd_stats);
704 		return QDF_STATUS_E_INVAL;
705 	}
706 
707 	ev->num_mib_stats = stats_param->num_mib_stats;
708 
709 	ev->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats));
710 	if (!ev->mib_stats)
711 		return QDF_STATUS_E_NOMEM;
712 
713 	status = wmi_extract_mib_stats(wmi_hdl, data, ev->mib_stats);
714 	if (QDF_IS_STATUS_ERROR(status)) {
715 		cp_stats_err("wmi_extract_mib_stats failed");
716 		return status;
717 	}
718 
719 	return QDF_STATUS_SUCCESS;
720 }
721 #else
target_if_cp_stats_extract_mib_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)722 static QDF_STATUS target_if_cp_stats_extract_mib_stats(
723 					struct wmi_unified *wmi_hdl,
724 					wmi_host_stats_event *stats_param,
725 					struct stats_event *ev, uint8_t *data)
726 {
727 	return QDF_STATUS_SUCCESS;
728 }
729 #endif
730 
target_if_cp_stats_extract_vdev_summary_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)731 static QDF_STATUS target_if_cp_stats_extract_vdev_summary_stats(
732 					struct wmi_unified *wmi_hdl,
733 					wmi_host_stats_event *stats_param,
734 					struct stats_event *ev, uint8_t *data)
735 {
736 	uint32_t i, j;
737 	QDF_STATUS status;
738 	int32_t bcn_snr, dat_snr;
739 	wmi_host_vdev_stats *vdev_stats;
740 	bool db2dbm_enabled;
741 
742 	ev->num_summary_stats = stats_param->num_vdev_stats;
743 	if (!ev->num_summary_stats)
744 		return QDF_STATUS_SUCCESS;
745 
746 	ev->vdev_summary_stats = qdf_mem_malloc(sizeof(*ev->vdev_summary_stats)
747 					* ev->num_summary_stats);
748 
749 	if (!ev->vdev_summary_stats)
750 		return QDF_STATUS_E_NOMEM;
751 
752 	db2dbm_enabled = wmi_service_enabled(wmi_hdl,
753 					     wmi_service_hw_db2dbm_support);
754 
755 	vdev_stats = qdf_mem_malloc(sizeof(*vdev_stats));
756 	if (!vdev_stats) {
757 		cp_stats_err("malloc failed for vdev stats");
758 		return QDF_STATUS_E_NOMEM;
759 	}
760 
761 	for (i = 0; i < ev->num_summary_stats; i++) {
762 		status = wmi_extract_vdev_stats(wmi_hdl, data, i, vdev_stats);
763 		if (QDF_IS_STATUS_ERROR(status))
764 			continue;
765 
766 		bcn_snr = vdev_stats->vdev_snr.bcn_snr;
767 		dat_snr = vdev_stats->vdev_snr.dat_snr;
768 		ev->vdev_summary_stats[i].vdev_id = vdev_stats->vdev_id;
769 		/*bcn_snr parameter can come as RSSi/SNR from the FW depending
770 		  on whether FW supports the RSSI reporting or not */
771 		if (!db2dbm_enabled) {
772 			cp_stats_debug("vdev %d SNR bcn: %d data: %d",
773 					ev->vdev_summary_stats[i].vdev_id,
774 					bcn_snr, dat_snr);
775 		} else {
776 			cp_stats_debug("vdev %d RSSI bcn: %d data: %d",
777 					ev->vdev_summary_stats[i].vdev_id,
778 					bcn_snr, dat_snr);
779 		}
780 		for (j = 0; j < 4; j++) {
781 			ev->vdev_summary_stats[i].stats.tx_frm_cnt[j] =
782 					vdev_stats->tx_frm_cnt[j];
783 			ev->vdev_summary_stats[i].stats.fail_cnt[j] =
784 					vdev_stats->fail_cnt[j];
785 			ev->vdev_summary_stats[i].stats.multiple_retry_cnt[j] =
786 					vdev_stats->multiple_retry_cnt[j];
787 		}
788 
789 		ev->vdev_summary_stats[i].stats.rx_frm_cnt =
790 						vdev_stats->rx_frm_cnt;
791 		ev->vdev_summary_stats[i].stats.rx_error_cnt =
792 						vdev_stats->rx_err_cnt;
793 		ev->vdev_summary_stats[i].stats.rx_discard_cnt =
794 						vdev_stats->rx_discard_cnt;
795 		ev->vdev_summary_stats[i].stats.ack_fail_cnt =
796 						vdev_stats->ack_fail_cnt;
797 		ev->vdev_summary_stats[i].stats.rts_succ_cnt =
798 						vdev_stats->rts_succ_cnt;
799 		ev->vdev_summary_stats[i].stats.rts_fail_cnt =
800 						vdev_stats->rts_fail_cnt;
801 		/* Update SNR and RSSI in SummaryStats */
802 		wlan_util_stats_get_rssi(db2dbm_enabled, bcn_snr, dat_snr,
803 					 &ev->vdev_summary_stats[i].stats.rssi);
804 		ev->vdev_summary_stats[i].stats.snr =
805 				ev->vdev_summary_stats[i].stats.rssi -
806 				TGT_NOISE_FLOOR_DBM;
807 	}
808 	qdf_mem_free(vdev_stats);
809 
810 	return QDF_STATUS_SUCCESS;
811 }
812 
813 
target_if_cp_stats_extract_vdev_chain_rssi_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)814 static QDF_STATUS target_if_cp_stats_extract_vdev_chain_rssi_stats(
815 					struct wmi_unified *wmi_hdl,
816 					wmi_host_stats_event *stats_param,
817 					struct stats_event *ev, uint8_t *data)
818 {
819 	uint32_t i, j;
820 	QDF_STATUS status;
821 	int32_t bcn_snr, dat_snr;
822 	struct wmi_host_per_chain_rssi_stats rssi_stats;
823 	bool db2dbm_enabled;
824 
825 	ev->num_chain_rssi_stats = stats_param->num_rssi_stats;
826 	if (!ev->num_chain_rssi_stats)
827 		return QDF_STATUS_SUCCESS;
828 
829 	ev->vdev_chain_rssi = qdf_mem_malloc(sizeof(*ev->vdev_chain_rssi) *
830 						ev->num_chain_rssi_stats);
831 	if (!ev->vdev_chain_rssi)
832 		return QDF_STATUS_E_NOMEM;
833 
834 	db2dbm_enabled = wmi_service_enabled(wmi_hdl,
835 					     wmi_service_hw_db2dbm_support);
836 	for (i = 0; i < ev->num_chain_rssi_stats; i++) {
837 		status = wmi_extract_per_chain_rssi_stats(wmi_hdl, data, i,
838 							  &rssi_stats);
839 		if (QDF_IS_STATUS_ERROR(status))
840 			continue;
841 		ev->vdev_chain_rssi[i].vdev_id = rssi_stats.vdev_id;
842 
843 		for (j = 0; j < MAX_NUM_CHAINS; j++) {
844 			dat_snr = rssi_stats.rssi_avg_data[j];
845 			bcn_snr = rssi_stats.rssi_avg_beacon[j];
846 			cp_stats_nofl_debug("Chain %d SNR bcn: %d data: %d", j,
847 					    bcn_snr, dat_snr);
848 			/*
849 			 * Get the absolute rssi value from the current rssi
850 			 * value the snr value is hardcoded into 0 in the
851 			 * qcacld-new/CORE stack
852 			 */
853 			wlan_util_stats_get_rssi(db2dbm_enabled, bcn_snr,
854 						 dat_snr,
855 						 &ev->vdev_chain_rssi[i].
856 						 chain_rssi[j]);
857 		}
858 	}
859 
860 	return QDF_STATUS_SUCCESS;
861 }
862 
863 static QDF_STATUS
target_if_cp_stats_extract_vdev_extd_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)864 target_if_cp_stats_extract_vdev_extd_stats(struct wmi_unified *wmi_hdl,
865 					   wmi_host_stats_event *stats_param,
866 					   struct stats_event *ev,
867 					   uint8_t *data)
868 {
869 	uint8_t i;
870 	QDF_STATUS status;
871 	struct wmi_host_vdev_prb_fils_stats *stats;
872 
873 	ev->num_vdev_extd_stats = stats_param->num_vdev_extd_stats;
874 	if (!ev->num_vdev_extd_stats)
875 		return QDF_STATUS_SUCCESS;
876 
877 	if (ev->num_vdev_extd_stats > WLAN_MAX_VDEVS) {
878 		cp_stats_err("num_vdev_extd_stats is invalid: %u",
879 			     ev->num_vdev_extd_stats);
880 		return QDF_STATUS_E_INVAL;
881 	}
882 
883 	ev->vdev_extd_stats = qdf_mem_malloc(sizeof(*ev->vdev_extd_stats) *
884 					     ev->num_vdev_extd_stats);
885 	if (!ev->vdev_extd_stats)
886 		return QDF_STATUS_E_NOMEM;
887 
888 	stats = qdf_mem_malloc(sizeof(*stats) * ev->num_vdev_extd_stats);
889 
890 	if (!stats) {
891 		cp_stats_err("malloc failed for vdev extended stats");
892 		status = QDF_STATUS_E_NOMEM;
893 		goto end;
894 	}
895 
896 	for (i = 0 ; i < ev->num_vdev_extd_stats; i++) {
897 		status = wmi_extract_vdev_prb_fils_stats(wmi_hdl, data,
898 							 i, stats);
899 		if (QDF_IS_STATUS_ERROR(status)) {
900 			cp_stats_err("wmi_extract_vdev_extd_stats failed");
901 			qdf_mem_free(stats);
902 			goto end;
903 		}
904 		ev->vdev_extd_stats[i].vdev_id = stats[0].vdev_id;
905 		ev->vdev_extd_stats[i].is_mlo_vdev_active =
906 						stats[0].is_mlo_vdev_active;
907 		ev->vdev_extd_stats[i].vdev_tx_power = stats[i].vdev_tx_power;
908 	}
909 
910 	qdf_mem_free(stats);
911 	return status;
912 
913 end:
914 	qdf_mem_free(ev->vdev_extd_stats);
915 	ev->vdev_extd_stats = NULL;
916 	return status;
917 }
918 
target_if_cp_stats_extract_event(struct wmi_unified * wmi_hdl,struct stats_event * ev,uint8_t * data)919 static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
920 						   struct stats_event *ev,
921 						   uint8_t *data)
922 {
923 	QDF_STATUS status;
924 	static uint8_t mac_seq = 0;
925 	wmi_host_stats_event stats_param = {0};
926 
927 	status = wmi_extract_stats_param(wmi_hdl, data, &stats_param);
928 	if (QDF_IS_STATUS_ERROR(status)) {
929 		cp_stats_err("stats param extract failed: %d", status);
930 		return status;
931 	}
932 	cp_stats_nofl_debug("num: pdev: %d, pdev_extd: %d, vdev: %d, vdev_extd: %d, "
933 			    "peer: %d, peer_extd: %d rssi: %d, mib %d, mib_extd %d, "
934 			    "bcnflt: %d, channel: %d, bcn: %d, peer_extd2: %d, "
935 			    "last_event: %x, stats id: %d",
936 			    stats_param.num_pdev_stats,
937 			    stats_param.num_pdev_ext_stats,
938 			    stats_param.num_vdev_stats,
939 			    stats_param.num_vdev_extd_stats,
940 			    stats_param.num_peer_stats,
941 			    stats_param.num_peer_extd_stats,
942 			    stats_param.num_rssi_stats,
943 			    stats_param.num_mib_stats,
944 			    stats_param.num_mib_extd_stats,
945 			    stats_param.num_bcnflt_stats,
946 			    stats_param.num_chan_stats,
947 			    stats_param.num_bcn_stats,
948 			    stats_param.num_peer_adv_stats,
949 			    stats_param.last_event,
950 			    stats_param.stats_id);
951 
952 	ev->last_event = stats_param.last_event;
953 	ev->mac_seq_num = mac_seq;
954 	if (IS_MSB_SET(ev->last_event) && IS_LSB_SET(ev->last_event))
955 		mac_seq = 0;
956 	else
957 		mac_seq++;
958 
959 	status = target_if_cp_stats_extract_pdev_stats(wmi_hdl, &stats_param,
960 						       ev, data);
961 	if (QDF_IS_STATUS_ERROR(status))
962 		return status;
963 
964 	status = target_if_cp_stats_extract_peer_stats(wmi_hdl, &stats_param,
965 						       ev, data);
966 	if (QDF_IS_STATUS_ERROR(status))
967 		return status;
968 
969 	status = target_if_cp_stats_extract_cca_stats(wmi_hdl, &stats_param,
970 						      ev, data);
971 	if (QDF_IS_STATUS_ERROR(status))
972 		return status;
973 
974 	status = target_if_cp_stats_extract_vdev_summary_stats(wmi_hdl,
975 							       &stats_param,
976 							       ev, data);
977 	if (QDF_IS_STATUS_ERROR(status))
978 		return status;
979 
980 	status = target_if_cp_stats_extract_vdev_chain_rssi_stats(wmi_hdl,
981 								  &stats_param,
982 								  ev, data);
983 	if (QDF_IS_STATUS_ERROR(status))
984 		return status;
985 
986 	status = target_if_cp_stats_extract_mib_stats(wmi_hdl,
987 						      &stats_param,
988 						      ev, data);
989 	if (QDF_IS_STATUS_ERROR(status))
990 		return status;
991 
992 	status = target_if_cp_stats_extract_pmf_bcn_protect_stats(wmi_hdl,
993 								  &stats_param,
994 								  ev, data);
995 	if (QDF_IS_STATUS_ERROR(status))
996 		return status;
997 
998 	status = target_if_cp_stats_extract_pdev_extd_stats(wmi_hdl,
999 							    &stats_param,
1000 							    ev, data);
1001 	if (QDF_IS_STATUS_ERROR(status))
1002 		return status;
1003 
1004 	status = target_if_cp_stats_extract_vdev_extd_stats(wmi_hdl,
1005 							    &stats_param,
1006 							    ev, data);
1007 	return status;
1008 }
1009 
target_if_mc_cp_get_mac_id(struct vdev_mlme_obj * vdev_mlme)1010 uint8_t target_if_mc_cp_get_mac_id(struct vdev_mlme_obj *vdev_mlme)
1011 {
1012 	uint8_t mac_id = 0;
1013 
1014 	if (wlan_reg_is_24ghz_ch_freq(vdev_mlme->vdev->vdev_mlme.des_chan->ch_freq))
1015 		mac_id = TGT_MAC_ID_24G;
1016 	else
1017 		mac_id = TGT_MAC_ID_5G;
1018 
1019 	return mac_id;
1020 }
1021 
1022 /**
1023  * target_if_mc_cp_stats_stats_event_handler() - function to handle stats event
1024  * from firmware.
1025  * @scn: scn handle
1026  * @data: data buffer for event
1027  * @datalen: data length
1028  *
1029  * Return: status of operation.
1030  */
target_if_mc_cp_stats_stats_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)1031 static int target_if_mc_cp_stats_stats_event_handler(ol_scn_t scn,
1032 						     uint8_t *data,
1033 						     uint32_t datalen)
1034 {
1035 	QDF_STATUS status;
1036 	struct stats_event *ev;
1037 	struct wlan_objmgr_psoc *psoc;
1038 	struct wmi_unified *wmi_handle;
1039 	struct wlan_lmac_if_cp_stats_rx_ops *rx_ops;
1040 
1041 	if (!scn || !data) {
1042 		cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
1043 		return -EINVAL;
1044 	}
1045 	psoc = target_if_get_psoc_from_scn_hdl(scn);
1046 	if (!psoc) {
1047 		cp_stats_err("null psoc");
1048 		return -EINVAL;
1049 	}
1050 
1051 	rx_ops = target_if_cp_stats_get_rx_ops(psoc);
1052 	if (!rx_ops || !rx_ops->process_stats_event) {
1053 		cp_stats_err("callback not registered");
1054 		return -EINVAL;
1055 	}
1056 
1057 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1058 	if (!wmi_handle) {
1059 		cp_stats_err("wmi_handle is null");
1060 		return -EINVAL;
1061 	}
1062 
1063 	ev = qdf_mem_malloc(sizeof(*ev));
1064 	if (!ev) {
1065 		cp_stats_err("");
1066 		return -EINVAL;
1067 	}
1068 
1069 	status = target_if_cp_stats_extract_event(wmi_handle, ev, data);
1070 	if (QDF_IS_STATUS_ERROR(status)) {
1071 		cp_stats_err("extract event failed");
1072 		goto end;
1073 	}
1074 
1075 	status = rx_ops->process_stats_event(psoc, ev);
1076 
1077 end:
1078 	target_if_cp_stats_free_stats_event(ev);
1079 	qdf_mem_free(ev);
1080 
1081 	return qdf_status_to_os_return(status);
1082 }
1083 
1084 #ifdef WLAN_FEATURE_BIG_DATA_STATS
target_if_mc_cp_stats_big_data_stats_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)1085 static int target_if_mc_cp_stats_big_data_stats_event_handler(ol_scn_t scn,
1086 							      uint8_t *data,
1087 							      uint32_t datalen)
1088 {
1089 	QDF_STATUS status;
1090 	struct big_data_stats_event ev = {0};
1091 	struct wlan_objmgr_psoc *psoc;
1092 	struct wmi_unified *wmi_handle;
1093 	struct wlan_lmac_if_cp_stats_rx_ops *rx_ops;
1094 
1095 	if (!scn || !data) {
1096 		cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
1097 		return -EINVAL;
1098 	}
1099 	psoc = target_if_get_psoc_from_scn_hdl(scn);
1100 	if (!psoc) {
1101 		cp_stats_err("null psoc");
1102 		return -EINVAL;
1103 	}
1104 
1105 	rx_ops = target_if_cp_stats_get_rx_ops(psoc);
1106 	if (!rx_ops || !rx_ops->process_big_data_stats_event) {
1107 		cp_stats_err("callback not registered");
1108 		return -EINVAL;
1109 	}
1110 
1111 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1112 	if (!wmi_handle) {
1113 		cp_stats_err("wmi_handle is null");
1114 		return -EINVAL;
1115 	}
1116 
1117 	status = wmi_extract_big_data_stats_param(wmi_handle, data, &ev);
1118 	if (QDF_IS_STATUS_ERROR(status)) {
1119 		cp_stats_err("extract event failed");
1120 		goto end;
1121 	}
1122 
1123 	status = rx_ops->process_big_data_stats_event(psoc, &ev);
1124 
1125 end:
1126 	return qdf_status_to_os_return(status);
1127 }
1128 
1129 /**
1130  * target_if_cp_stats_send_big_data_stats_req() - API to send request to wmi
1131  * @psoc: pointer to psoc object
1132  * @req: pointer to object containing stats request parameters
1133  *
1134  * Return: status of operation.
1135  */
target_if_cp_stats_send_big_data_stats_req(struct wlan_objmgr_psoc * psoc,struct request_info * req)1136 static QDF_STATUS target_if_cp_stats_send_big_data_stats_req(
1137 				struct wlan_objmgr_psoc *psoc,
1138 				struct request_info *req)
1139 
1140 {
1141 	struct wmi_unified *wmi_handle;
1142 	struct stats_request_params param = {0};
1143 
1144 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1145 	if (!wmi_handle) {
1146 		cp_stats_err("wmi_handle is null.");
1147 		return QDF_STATUS_E_NULL_VALUE;
1148 	}
1149 	param.vdev_id = req->vdev_id;
1150 
1151 	return wmi_unified_big_data_stats_request_send(wmi_handle,
1152 						       &param);
1153 }
1154 #endif
1155 
1156 static QDF_STATUS
target_if_cp_stats_extract_peer_stats_event(struct wmi_unified * wmi_hdl,struct stats_event * ev,uint8_t * data)1157 target_if_cp_stats_extract_peer_stats_event(struct wmi_unified *wmi_hdl,
1158 					    struct stats_event *ev,
1159 					    uint8_t *data)
1160 {
1161 	QDF_STATUS status;
1162 	wmi_host_stats_event stats_param = {0};
1163 	struct peer_stats_info_ext_event *peer_stats_info;
1164 	wmi_host_peer_stats_info stats_info;
1165 	uint32_t peer_stats_info_size;
1166 	int i, j;
1167 	uint32_t tx_rate_count_idx = 0, rx_rate_count_idx = 0;
1168 
1169 	status = wmi_extract_peer_stats_param(wmi_hdl, data, &stats_param);
1170 	if (QDF_IS_STATUS_ERROR(status)) {
1171 		cp_stats_err("peer stats param extract failed: %d", status);
1172 		return status;
1173 	}
1174 
1175 	if (stats_param.num_peer_stats_info_ext == 0) {
1176 		cp_stats_err("num_peer_stats_info_ext is 0");
1177 		return status;
1178 	}
1179 
1180 	ev->num_peer_stats_info_ext = stats_param.num_peer_stats_info_ext;
1181 	peer_stats_info_size = sizeof(*ev->peer_stats_info_ext) *
1182 			       ev->num_peer_stats_info_ext;
1183 	ev->peer_stats_info_ext = qdf_mem_malloc(peer_stats_info_size);
1184 	if (!ev->peer_stats_info_ext) {
1185 		ev->num_peer_stats_info_ext = 0;
1186 		return QDF_STATUS_E_NOMEM;
1187 	}
1188 
1189 	peer_stats_info = ev->peer_stats_info_ext;
1190 	for (i = 0; i < ev->num_peer_stats_info_ext; i++) {
1191 		status = wmi_extract_peer_stats_info(wmi_hdl, data,
1192 						     i, &stats_info);
1193 		if (QDF_IS_STATUS_ERROR(status)) {
1194 			cp_stats_err("peer stats info extract failed: %d",
1195 				     status);
1196 			target_if_cp_stats_free_peer_stats_info_ext(ev);
1197 			return status;
1198 		}
1199 		qdf_mem_copy(&peer_stats_info->peer_macaddr,
1200 			     &stats_info.peer_macaddr,
1201 			     sizeof(peer_stats_info->peer_macaddr));
1202 		peer_stats_info->tx_packets = stats_info.tx_packets;
1203 		peer_stats_info->tx_bytes = stats_info.tx_bytes;
1204 		peer_stats_info->rx_packets = stats_info.rx_packets;
1205 		peer_stats_info->rx_bytes = stats_info.rx_bytes;
1206 		peer_stats_info->tx_retries = stats_info.tx_retries;
1207 		peer_stats_info->tx_failed = stats_info.tx_failed;
1208 		peer_stats_info->tx_succeed = stats_info.tx_succeed;
1209 		peer_stats_info->rssi = stats_info.peer_rssi;
1210 		peer_stats_info->tx_rate = stats_info.last_tx_bitrate_kbps;
1211 		peer_stats_info->tx_rate_code = stats_info.last_tx_rate_code;
1212 		peer_stats_info->rx_rate = stats_info.last_rx_bitrate_kbps;
1213 		peer_stats_info->rx_rate_code = stats_info.last_rx_rate_code;
1214 		for (j = 0; j < WMI_MAX_CHAINS; j++)
1215 			peer_stats_info->peer_rssi_per_chain[j] =
1216 					      stats_info.peer_rssi_per_chain[j];
1217 
1218 		if (stats_info.num_tx_rate_counts) {
1219 			peer_stats_info->num_tx_rate_counts =
1220 						stats_info.num_tx_rate_counts;
1221 			status = wmi_extract_peer_tx_pkt_per_mcs(
1222 							wmi_hdl, data,
1223 							tx_rate_count_idx,
1224 							&stats_info);
1225 			if (QDF_IS_STATUS_ERROR(status)) {
1226 				wmi_err("tx rate count extract failed");
1227 				target_if_cp_stats_free_peer_stats_info_ext(ev);
1228 				return status;
1229 			}
1230 			tx_rate_count_idx +=
1231 					peer_stats_info->num_tx_rate_counts;
1232 
1233 			peer_stats_info->tx_pkt_per_mcs =
1234 						stats_info.tx_pkt_per_mcs;
1235 			stats_info.tx_pkt_per_mcs = NULL;
1236 		}
1237 		if (stats_info.num_rx_rate_counts) {
1238 			peer_stats_info->num_rx_rate_counts =
1239 						stats_info.num_rx_rate_counts;
1240 			status = wmi_extract_peer_rx_pkt_per_mcs(
1241 							wmi_hdl, data,
1242 							rx_rate_count_idx,
1243 							&stats_info);
1244 			if (QDF_IS_STATUS_ERROR(status)) {
1245 				wmi_err("rx rate count extract failed");
1246 				target_if_cp_stats_free_peer_stats_info_ext(ev);
1247 				return status;
1248 			}
1249 			rx_rate_count_idx +=
1250 					peer_stats_info->num_rx_rate_counts;
1251 
1252 			peer_stats_info->rx_pkt_per_mcs =
1253 						stats_info.rx_pkt_per_mcs;
1254 			stats_info.rx_pkt_per_mcs = NULL;
1255 		}
1256 		peer_stats_info++;
1257 	}
1258 
1259 	return QDF_STATUS_SUCCESS;
1260 }
1261 
1262 /**
1263  * target_if_mc_cp_stats_peer_stats_info_event_handler() - function to handle
1264  * peer stats info event from firmware.
1265  * @scn: scn handle
1266  * @data: data buffer for event
1267  * @datalen: data length
1268  *
1269  * Return: status of operation.
1270  */
target_if_mc_cp_stats_peer_stats_info_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)1271 static int target_if_mc_cp_stats_peer_stats_info_event_handler(ol_scn_t scn,
1272 							       uint8_t *data,
1273 							       uint32_t datalen)
1274 {
1275 	QDF_STATUS status;
1276 	struct stats_event ev = {0};
1277 	struct wlan_objmgr_psoc *psoc;
1278 	struct wmi_unified *wmi_handle;
1279 	struct wlan_lmac_if_cp_stats_rx_ops *rx_ops;
1280 
1281 	if (!scn || !data) {
1282 		cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
1283 		return -EINVAL;
1284 	}
1285 	psoc = target_if_get_psoc_from_scn_hdl(scn);
1286 	if (!psoc) {
1287 		cp_stats_err("null psoc");
1288 		return -EINVAL;
1289 	}
1290 
1291 	rx_ops = target_if_cp_stats_get_rx_ops(psoc);
1292 	if (!rx_ops || !rx_ops->process_stats_event) {
1293 		cp_stats_err("callback not registered");
1294 		return -EINVAL;
1295 	}
1296 
1297 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1298 	if (!wmi_handle) {
1299 		cp_stats_err("wmi_handle is null");
1300 		return -EINVAL;
1301 	}
1302 
1303 	status = target_if_cp_stats_extract_peer_stats_event(wmi_handle,
1304 							     &ev, data);
1305 	if (QDF_IS_STATUS_ERROR(status)) {
1306 		cp_stats_err("extract event failed");
1307 		goto end;
1308 	}
1309 
1310 	status = rx_ops->process_stats_event(psoc, &ev);
1311 
1312 end:
1313 	target_if_cp_stats_free_stats_event(&ev);
1314 
1315 	return qdf_status_to_os_return(status);
1316 }
1317 
target_if_cp_stats_inc_wake_lock_stats(uint32_t reason,struct wake_lock_stats * stats,uint32_t * unspecified_wake_count)1318 static void target_if_cp_stats_inc_wake_lock_stats(uint32_t reason,
1319 					struct wake_lock_stats *stats,
1320 					uint32_t *unspecified_wake_count)
1321 {
1322 	switch (reason) {
1323 	case WOW_REASON_UNSPECIFIED:
1324 		(*unspecified_wake_count)++;
1325 		break;
1326 
1327 	case WOW_REASON_ASSOC_REQ_RECV:
1328 		stats->mgmt_assoc++;
1329 		break;
1330 
1331 	case WOW_REASON_DISASSOC_RECVD:
1332 		stats->mgmt_disassoc++;
1333 		break;
1334 
1335 	case WOW_REASON_ASSOC_RES_RECV:
1336 		stats->mgmt_assoc_resp++;
1337 		break;
1338 
1339 	case WOW_REASON_REASSOC_REQ_RECV:
1340 		stats->mgmt_reassoc++;
1341 		break;
1342 
1343 	case WOW_REASON_REASSOC_RES_RECV:
1344 		stats->mgmt_reassoc_resp++;
1345 		break;
1346 
1347 	case WOW_REASON_AUTH_REQ_RECV:
1348 		stats->mgmt_auth++;
1349 		break;
1350 
1351 	case WOW_REASON_DEAUTH_RECVD:
1352 		stats->mgmt_deauth++;
1353 		break;
1354 
1355 	case WOW_REASON_ACTION_FRAME_RECV:
1356 		stats->mgmt_action++;
1357 		break;
1358 
1359 	case WOW_REASON_NLOD:
1360 		stats->pno_match_wake_up_count++;
1361 		break;
1362 
1363 	case WOW_REASON_NLO_SCAN_COMPLETE:
1364 		stats->pno_complete_wake_up_count++;
1365 		break;
1366 
1367 	case WOW_REASON_LOW_RSSI:
1368 		stats->low_rssi_wake_up_count++;
1369 		break;
1370 
1371 	case WOW_REASON_EXTSCAN:
1372 		stats->gscan_wake_up_count++;
1373 		break;
1374 
1375 	case WOW_REASON_RSSI_BREACH_EVENT:
1376 		stats->rssi_breach_wake_up_count++;
1377 		break;
1378 
1379 	case WOW_REASON_OEM_RESPONSE_EVENT:
1380 		stats->oem_response_wake_up_count++;
1381 		break;
1382 
1383 	case WOW_REASON_11D_SCAN:
1384 		stats->scan_11d++;
1385 		break;
1386 
1387 	case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
1388 		stats->pwr_save_fail_detected++;
1389 		break;
1390 
1391 	case WOW_REASON_LOCAL_DATA_UC_DROP:
1392 		stats->uc_drop_wake_up_count++;
1393 		break;
1394 
1395 	case WOW_REASON_FATAL_EVENT_WAKE:
1396 		stats->fatal_event_wake_up_count++;
1397 		break;
1398 
1399 	default:
1400 		break;
1401 	}
1402 }
1403 
1404 #ifdef WLAN_FEATURE_BIG_DATA_STATS
1405 static QDF_STATUS
target_if_register_big_data_event_handler(struct wmi_unified * wmi_handle)1406 target_if_register_big_data_event_handler(struct wmi_unified *wmi_handle)
1407 {
1408 	return wmi_unified_register_event_handler(
1409 			    wmi_handle, wmi_vdev_send_big_data_p2_eventid,
1410 			    target_if_mc_cp_stats_big_data_stats_event_handler,
1411 			    WMI_RX_WORK_CTX);
1412 }
1413 
1414 static void
target_if_unregister_big_data_event_handler(struct wmi_unified * wmi_handle)1415 target_if_unregister_big_data_event_handler(struct wmi_unified *wmi_handle)
1416 {
1417 	wmi_unified_unregister_event_handler(wmi_handle,
1418 					     wmi_vdev_send_big_data_p2_eventid);
1419 }
1420 
1421 static QDF_STATUS
target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops * cp_stats_tx_ops)1422 target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops
1423 					 *cp_stats_tx_ops)
1424 {
1425 	cp_stats_tx_ops->send_req_big_data_stats =
1426 			target_if_cp_stats_send_big_data_stats_req;
1427 	return QDF_STATUS_SUCCESS;
1428 }
1429 
1430 static void
target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops * cp_stats_tx_ops)1431 target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops
1432 					   *cp_stats_tx_ops)
1433 {
1434 	cp_stats_tx_ops->send_req_big_data_stats = NULL;
1435 }
1436 #else
1437 static QDF_STATUS
target_if_register_big_data_event_handler(struct wmi_unified * wmi_handle)1438 target_if_register_big_data_event_handler(struct wmi_unified *wmi_handle)
1439 {
1440 	return QDF_STATUS_SUCCESS;
1441 }
1442 
1443 static void
target_if_unregister_big_data_event_handler(struct wmi_unified * wmi_handle)1444 target_if_unregister_big_data_event_handler(struct wmi_unified *wmi_handle)
1445 {}
1446 
1447 static QDF_STATUS
target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops * cp_stats_tx_ops)1448 target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops
1449 					 *cp_stats_tx_ops)
1450 {
1451 	return QDF_STATUS_SUCCESS;
1452 }
1453 
1454 static void
target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops * cp_stats_tx_ops)1455 target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops
1456 					   *cp_stats_tx_ops)
1457 {}
1458 #endif
1459 
1460 #ifdef WLAN_FEATURE_SON
1461 static int
target_if_mc_cp_stats_inst_rssi_stats_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)1462 target_if_mc_cp_stats_inst_rssi_stats_event_handler(ol_scn_t scn,
1463 						    uint8_t *data,
1464 						    uint32_t datalen)
1465 {
1466 	QDF_STATUS status;
1467 	struct wlan_objmgr_peer *peer;
1468 	struct wlan_objmgr_psoc *psoc;
1469 	struct wmi_unified *wmi_handle;
1470 	struct wmi_host_inst_rssi_stats_resp ev = {0};
1471 
1472 	if (!scn || !data) {
1473 		cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
1474 		return -EINVAL;
1475 	}
1476 
1477 	psoc = target_if_get_psoc_from_scn_hdl(scn);
1478 	if (!psoc) {
1479 		cp_stats_err("null psoc");
1480 		return -EINVAL;
1481 	}
1482 
1483 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1484 	if (!wmi_handle) {
1485 		cp_stats_err("wmi_handle is null");
1486 		return -EINVAL;
1487 	}
1488 
1489 	status = wmi_extract_inst_rssi_stats_resp(wmi_handle, data, &ev);
1490 	if (QDF_IS_STATUS_ERROR(status)) {
1491 		cp_stats_err("extract event failed");
1492 		return qdf_status_to_os_return(status);
1493 	}
1494 
1495 	peer = wlan_objmgr_get_peer_by_mac(psoc, ev.peer_macaddr.bytes,
1496 					   WLAN_CP_STATS_ID);
1497 	if (!peer) {
1498 		cp_stats_err("null peer");
1499 		return -EINVAL;
1500 	}
1501 
1502 	wlan_son_deliver_inst_rssi(wlan_peer_get_vdev(peer),
1503 				   peer,
1504 				   ev.inst_rssi);
1505 
1506 	wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
1507 
1508 	return 0;
1509 }
1510 
1511 static QDF_STATUS
target_if_register_inst_rssi_event_handler(struct wmi_unified * wmi_handle)1512 target_if_register_inst_rssi_event_handler(struct wmi_unified *wmi_handle)
1513 {
1514 	return wmi_unified_register_event_handler(wmi_handle,
1515 			wmi_inst_rssi_stats_event_id,
1516 			target_if_mc_cp_stats_inst_rssi_stats_event_handler,
1517 			WMI_RX_SERIALIZER_CTX);
1518 }
1519 
1520 static void
target_if_unregister_inst_rssi_event_handler(struct wmi_unified * wmi_handle)1521 target_if_unregister_inst_rssi_event_handler(struct wmi_unified *wmi_handle)
1522 {
1523 	wmi_unified_unregister_event_handler(wmi_handle,
1524 					     wmi_inst_rssi_stats_event_id);
1525 }
1526 #else
1527 static QDF_STATUS
target_if_register_inst_rssi_event_handler(struct wmi_unified * wmi_handle)1528 target_if_register_inst_rssi_event_handler(struct wmi_unified *wmi_handle)
1529 {
1530 	return QDF_STATUS_SUCCESS;
1531 }
1532 
1533 static void
target_if_unregister_inst_rssi_event_handler(struct wmi_unified * wmi_handle)1534 target_if_unregister_inst_rssi_event_handler(struct wmi_unified *wmi_handle)
1535 {
1536 }
1537 #endif
1538 
1539 static QDF_STATUS
target_if_mc_cp_stats_register_event_handler(struct wlan_objmgr_psoc * psoc)1540 target_if_mc_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc)
1541 {
1542 	QDF_STATUS ret_val;
1543 	struct wmi_unified *wmi_handle;
1544 
1545 	if (!psoc) {
1546 		cp_stats_err("PSOC is NULL!");
1547 		return QDF_STATUS_E_NULL_VALUE;
1548 	}
1549 
1550 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1551 	if (!wmi_handle) {
1552 		cp_stats_err("wmi_handle is null");
1553 		return QDF_STATUS_E_INVAL;
1554 	}
1555 
1556 	ret_val = wmi_unified_register_event_handler(
1557 			wmi_handle,
1558 			wmi_update_stats_event_id,
1559 			target_if_mc_cp_stats_stats_event_handler,
1560 			WMI_RX_WORK_CTX);
1561 	if (QDF_IS_STATUS_ERROR(ret_val))
1562 		cp_stats_err("Failed to register stats event cb");
1563 
1564 	ret_val = wmi_unified_register_event_handler(wmi_handle,
1565 			    wmi_peer_stats_info_event_id,
1566 			    target_if_mc_cp_stats_peer_stats_info_event_handler,
1567 			    WMI_RX_WORK_CTX);
1568 	if (QDF_IS_STATUS_ERROR(ret_val))
1569 		cp_stats_err("Failed to register peer stats info event cb");
1570 
1571 	ret_val = target_if_register_big_data_event_handler(wmi_handle);
1572 	if (QDF_IS_STATUS_ERROR(ret_val))
1573 		cp_stats_err("Failed to register big data stats info event cb");
1574 
1575 	ret_val = target_if_register_inst_rssi_event_handler(wmi_handle);
1576 	if (QDF_IS_STATUS_ERROR(ret_val))
1577 		cp_stats_err("Failed to register inst rssi stats event cb");
1578 
1579 	return ret_val;
1580 }
1581 
1582 static QDF_STATUS
target_if_mc_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc * psoc)1583 target_if_mc_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
1584 {
1585 	struct wmi_unified *wmi_handle;
1586 
1587 	if (!psoc) {
1588 		cp_stats_err("PSOC is NULL!");
1589 		return QDF_STATUS_E_INVAL;
1590 	}
1591 
1592 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1593 	if (!wmi_handle) {
1594 		cp_stats_err("wmi_handle is null");
1595 		return QDF_STATUS_E_INVAL;
1596 	}
1597 
1598 	target_if_unregister_inst_rssi_event_handler(wmi_handle);
1599 	target_if_unregister_big_data_event_handler(wmi_handle);
1600 
1601 	wmi_unified_unregister_event_handler(wmi_handle,
1602 					     wmi_peer_stats_info_event_id);
1603 	wmi_unified_unregister_event_handler(wmi_handle,
1604 					     wmi_update_stats_event_id);
1605 
1606 	return QDF_STATUS_SUCCESS;
1607 }
1608 
get_stats_id(enum stats_req_type type)1609 static uint32_t get_stats_id(enum stats_req_type type)
1610 {
1611 	switch (type) {
1612 	default:
1613 		break;
1614 	case TYPE_CONNECTION_TX_POWER:
1615 		return WMI_REQUEST_PDEV_STAT | WMI_REQUEST_VDEV_EXTD_STAT;
1616 	case TYPE_CONGESTION_STATS:
1617 		return WMI_REQUEST_PDEV_STAT | WMI_REQUEST_PDEV_EXTD_STAT;
1618 	case TYPE_PEER_STATS:
1619 		return WMI_REQUEST_PEER_STAT | WMI_REQUEST_PEER_EXTD_STAT;
1620 	case TYPE_STATION_STATS:
1621 		return (WMI_REQUEST_AP_STAT   |
1622 			WMI_REQUEST_PEER_STAT |
1623 			WMI_REQUEST_VDEV_STAT |
1624 			WMI_REQUEST_VDEV_EXTD_STAT |
1625 			WMI_REQUEST_PDEV_STAT |
1626 			WMI_REQUEST_PEER_EXTD2_STAT |
1627 			WMI_REQUEST_RSSI_PER_CHAIN_STAT |
1628 			WMI_REQUEST_PMF_BCN_PROTECT_STAT);
1629 	case TYPE_MIB_STATS:
1630 		return (WMI_REQUEST_MIB_STAT | WMI_REQUEST_MIB_EXTD_STAT);
1631 	}
1632 
1633 	return 0;
1634 }
1635 
1636 /**
1637  * target_if_cp_stats_send_stats_req() - API to send stats request to wmi
1638  * @psoc: pointer to psoc object
1639  * @type: Type of stats requested
1640  * @req: pointer to object containing stats request parameters
1641  *
1642  * Return: status of operation.
1643  */
target_if_cp_stats_send_stats_req(struct wlan_objmgr_psoc * psoc,enum stats_req_type type,struct request_info * req)1644 static QDF_STATUS target_if_cp_stats_send_stats_req(
1645 					struct wlan_objmgr_psoc *psoc,
1646 					enum stats_req_type type,
1647 					struct request_info *req)
1648 
1649 {
1650 	struct wmi_unified *wmi_handle;
1651 	struct stats_request_params param = {0};
1652 
1653 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1654 	if (!wmi_handle) {
1655 		cp_stats_err("wmi_handle is null.");
1656 		return QDF_STATUS_E_NULL_VALUE;
1657 	}
1658 
1659 	/* refer  (WMI_REQUEST_STATS_CMDID) */
1660 	param.stats_id = get_stats_id(type);
1661 	param.vdev_id = req->vdev_id;
1662 	param.pdev_id = req->pdev_id;
1663 
1664 	/* only very frequent periodic stats needs to go over QMI.
1665 	 * for that, wlan_hdd_qmi_get_sync_resume/wlan_hdd_qmi_put_suspend
1666 	 * needs to be called to cover the period between qmi send and
1667 	 * qmi response.
1668 	 */
1669 	if (TYPE_STATION_STATS == type)
1670 		param.is_qmi_send_support = true;
1671 
1672 	return wmi_unified_stats_request_send(wmi_handle, req->peer_mac_addr,
1673 					      &param);
1674 }
1675 
1676 /**
1677  * target_if_set_pdev_stats_update_period(): API to set pdev stats update
1678  * period to FW
1679  * @psoc: pointer to psoc object
1680  * @pdev_id: pdev id
1681  * @val: pdev stats update period, 0: disabled periodical stats report.
1682  *
1683  * Return: status of operation
1684  */
1685 static QDF_STATUS
target_if_set_pdev_stats_update_period(struct wlan_objmgr_psoc * psoc,uint8_t pdev_id,uint32_t val)1686 target_if_set_pdev_stats_update_period(struct wlan_objmgr_psoc *psoc,
1687 				       uint8_t pdev_id, uint32_t val)
1688 {
1689 	struct wmi_unified *wmi_handle;
1690 	struct pdev_params pdev_param = {0};
1691 
1692 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1693 
1694 	if (!wmi_handle) {
1695 		cp_stats_err("wmi_handle is null");
1696 		return QDF_STATUS_E_INVAL;
1697 	}
1698 
1699 	pdev_param.param_id = wmi_pdev_param_pdev_stats_update_period;
1700 	pdev_param.param_value = val;
1701 	return wmi_unified_pdev_param_send(wmi_handle,
1702 					   &pdev_param,
1703 					   pdev_id);
1704 }
1705 
1706 /**
1707  * target_if_mc_cp_stats_unregister_handlers() - Unregisters wmi event handlers
1708  * of control plane stats & twt session stats info
1709  * @psoc: PSOC object
1710  *
1711  * Return: QDF_STATUS_SUCCESS on success or QDF error values on failure
1712  */
1713 static QDF_STATUS
target_if_mc_cp_stats_unregister_handlers(struct wlan_objmgr_psoc * psoc)1714 target_if_mc_cp_stats_unregister_handlers(struct wlan_objmgr_psoc *psoc)
1715 {
1716 	QDF_STATUS qdf_status;
1717 
1718 	qdf_status = target_if_twt_session_params_unregister_evt_hdlr(psoc);
1719 	if (qdf_status == QDF_STATUS_SUCCESS)
1720 		qdf_status =
1721 			target_if_mc_cp_stats_unregister_event_handler(psoc);
1722 
1723 	return qdf_status;
1724 }
1725 
1726 /**
1727  * target_if_mc_cp_stats_register_handlers() - Registers wmi event handlers for
1728  * control plane stats & twt session stats info
1729  * @psoc: PSOC object
1730  *
1731  * Return: QDF_STATUS_SUCCESS on success or QDF error values on failure
1732  */
1733 static QDF_STATUS
target_if_mc_cp_stats_register_handlers(struct wlan_objmgr_psoc * psoc)1734 target_if_mc_cp_stats_register_handlers(struct wlan_objmgr_psoc *psoc)
1735 {
1736 	QDF_STATUS qdf_status;
1737 
1738 	qdf_status = target_if_mc_cp_stats_register_event_handler(psoc);
1739 	if (qdf_status != QDF_STATUS_SUCCESS)
1740 		return qdf_status;
1741 
1742 	qdf_status = target_if_twt_session_params_register_evt_hdlr(psoc);
1743 	if (qdf_status != QDF_STATUS_SUCCESS)
1744 		target_if_mc_cp_stats_unregister_event_handler(psoc);
1745 
1746 	return qdf_status;
1747 }
1748 
1749 /**
1750  * target_if_cp_stats_send_peer_stats_req() - API to send peer stats request
1751  * to wmi
1752  * @psoc: pointer to psoc object
1753  * @req: pointer to object containing peer stats request parameters
1754  *
1755  * Return: status of operation.
1756  */
1757 static QDF_STATUS
target_if_cp_stats_send_peer_stats_req(struct wlan_objmgr_psoc * psoc,struct request_info * req)1758 target_if_cp_stats_send_peer_stats_req(struct wlan_objmgr_psoc *psoc,
1759 				       struct request_info *req)
1760 
1761 {
1762 	struct wmi_unified *wmi_handle;
1763 	struct peer_stats_request_params param = {0};
1764 
1765 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1766 	if (!wmi_handle) {
1767 		cp_stats_err("wmi_handle is null.");
1768 		return QDF_STATUS_E_NULL_VALUE;
1769 	}
1770 	param.request_type = WMI_REQUEST_ONE_PEER_STATS_INFO;
1771 	param.vdev_id = req->vdev_id;
1772 	qdf_mem_copy(param.peer_mac_addr, req->peer_mac_addr,
1773 		     QDF_MAC_ADDR_SIZE);
1774 	param.reset_after_request = 0;
1775 
1776 	return wmi_unified_peer_stats_request_send(wmi_handle, &param);
1777 }
1778 
1779 static QDF_STATUS
target_if_mc_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)1780 target_if_mc_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
1781 {
1782 	struct wlan_lmac_if_cp_stats_tx_ops *cp_stats_tx_ops;
1783 
1784 	if (!tx_ops) {
1785 		cp_stats_err("lmac tx ops is NULL!");
1786 		return QDF_STATUS_E_INVAL;
1787 	}
1788 
1789 	cp_stats_tx_ops = &tx_ops->cp_stats_tx_ops;
1790 	if (!cp_stats_tx_ops) {
1791 		cp_stats_err("lmac tx ops is NULL!");
1792 		return QDF_STATUS_E_FAILURE;
1793 	}
1794 
1795 	cp_stats_tx_ops->inc_wake_lock_stats =
1796 		target_if_cp_stats_inc_wake_lock_stats;
1797 	cp_stats_tx_ops->send_req_stats = target_if_cp_stats_send_stats_req;
1798 	cp_stats_tx_ops->set_pdev_stats_update_period =
1799 			target_if_set_pdev_stats_update_period;
1800 	cp_stats_tx_ops->send_req_peer_stats =
1801 		target_if_cp_stats_send_peer_stats_req;
1802 
1803 	target_if_big_data_stats_register_tx_ops(cp_stats_tx_ops);
1804 
1805 	return QDF_STATUS_SUCCESS;
1806 }
1807 
1808 static QDF_STATUS
target_if_mc_cp_stats_unregister_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)1809 target_if_mc_cp_stats_unregister_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
1810 {
1811 	struct wlan_lmac_if_cp_stats_tx_ops *cp_stats_tx_ops;
1812 
1813 	if (!tx_ops) {
1814 		cp_stats_err("lmac tx ops is NULL!");
1815 		return QDF_STATUS_E_INVAL;
1816 	}
1817 
1818 	cp_stats_tx_ops = &tx_ops->cp_stats_tx_ops;
1819 	if (!cp_stats_tx_ops) {
1820 		cp_stats_err("lmac tx ops is NULL!");
1821 		return QDF_STATUS_E_FAILURE;
1822 	}
1823 
1824 	target_if_big_data_stats_unregister_tx_ops(cp_stats_tx_ops);
1825 	cp_stats_tx_ops->inc_wake_lock_stats = NULL;
1826 	cp_stats_tx_ops->send_req_stats = NULL;
1827 	cp_stats_tx_ops->set_pdev_stats_update_period = NULL;
1828 	cp_stats_tx_ops->send_req_peer_stats = NULL;
1829 
1830 	return QDF_STATUS_SUCCESS;
1831 }
1832 
1833 #ifdef WLAN_SUPPORT_LEGACY_CP_STATS_HANDLERS
1834 QDF_STATUS
target_if_cp_stats_register_legacy_event_handler(struct wlan_objmgr_psoc * psoc)1835 target_if_cp_stats_register_legacy_event_handler(struct wlan_objmgr_psoc *psoc)
1836 {
1837 	QDF_STATUS status;
1838 	struct wlan_lmac_if_tx_ops *tx_ops;
1839 
1840 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
1841 	if (!tx_ops) {
1842 		cp_stats_err("lmac tx ops is NULL!");
1843 		return QDF_STATUS_E_FAILURE;
1844 	}
1845 
1846 	status = target_if_mc_cp_stats_register_tx_ops(tx_ops);
1847 	if (QDF_IS_STATUS_ERROR(status))
1848 		return status;
1849 
1850 	return target_if_mc_cp_stats_register_handlers(psoc);
1851 }
1852 
1853 QDF_STATUS
target_if_cp_stats_unregister_legacy_event_handler(struct wlan_objmgr_psoc * psoc)1854 target_if_cp_stats_unregister_legacy_event_handler(
1855 						struct wlan_objmgr_psoc *psoc)
1856 {
1857 	QDF_STATUS status;
1858 	struct wlan_lmac_if_tx_ops *tx_ops;
1859 
1860 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
1861 	if (!tx_ops) {
1862 		cp_stats_err("lmac tx ops is NULL!");
1863 		return QDF_STATUS_E_FAILURE;
1864 	}
1865 
1866 	status = target_if_mc_cp_stats_unregister_tx_ops(tx_ops);
1867 	if (QDF_IS_STATUS_ERROR(status))
1868 		return status;
1869 
1870 	return target_if_mc_cp_stats_unregister_handlers(psoc);
1871 }
1872 #endif
1873