xref: /wlan-dirver/qca-wifi-host-cmn/target_if/cp_stats/src/target_if_cp_stats.c (revision 6b801c30d6a98fe9c4a8d7f8032538a9de770395)
1 /*
2  * Copyright (c) 2018, 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_objmgr_peer_obj.h>
37 #ifdef WLAN_FEATURE_MIB_STATS
38 #include <wlan_cp_stats_mc_defs.h>
39 #endif
40 #include "cp_stats/core/src/wlan_cp_stats_defs.h"
41 #include "cdp_txrx_cmn_struct.h"
42 #include "cdp_txrx_ctrl.h"
43 #include "cp_stats/core/src/wlan_cp_stats_comp_handler.h"
44 
45 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
46 #ifdef WLAN_SUPPORT_TWT
47 /**
48  * target_if_infra_cp_stats_twt_event_free() - Free event buffer
49  * @ev: pointer to infra cp stats event structure
50  *
51  * Return: None
52  */
53 static
54 void target_if_infra_cp_stats_twt_event_free(struct infra_cp_stats_event *ev)
55 {
56 	qdf_mem_free(ev->twt_infra_cp_stats);
57 	ev->twt_infra_cp_stats = NULL;
58 }
59 
60 /**
61  * target_if_infra_cp_stats_twt_event_alloc() - Allocate event buffer for TWT
62  * parameters
63  * @ev: pointer to infra cp stats event structure
64  *
65  * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes on
66  * failure
67  */
68 static QDF_STATUS
69 target_if_infra_cp_stats_twt_event_alloc(struct infra_cp_stats_event *ev)
70 {
71 	ev->twt_infra_cp_stats =
72 			qdf_mem_malloc(sizeof(*ev->twt_infra_cp_stats) *
73 			INFRA_CP_STATS_MAX_RESP_TWT_DIALOG_ID);
74 	if (!ev->twt_infra_cp_stats) {
75 		cp_stats_err("mem alloc failed for ev.twt_infra_cp_stats");
76 		return QDF_STATUS_E_NOMEM;
77 	}
78 
79 	return QDF_STATUS_SUCCESS;
80 }
81 
82 #else
83 static inline
84 void target_if_infra_cp_stats_twt_event_free(struct infra_cp_stats_event *ev)
85 {
86 }
87 
88 static inline QDF_STATUS
89 target_if_infra_cp_stats_twt_event_alloc(struct infra_cp_stats_event *ev)
90 {
91 	return QDF_STATUS_SUCCESS;
92 }
93 
94 static inline
95 void target_if_infra_cp_stats_free_stats_event(struct infra_cp_stats_event *ev)
96 {
97 }
98 #endif /* WLAN_SUPPORT_TWT */
99 
100 static
101 void target_if_infra_cp_stats_rrm_sta_stats_event_free(
102 					struct infra_cp_stats_event *ev)
103 {
104 	qdf_mem_free(ev->sta_stats);
105 	ev->sta_stats = NULL;
106 }
107 
108 static QDF_STATUS
109 target_if_infra_cp_stats_rrm_sta_stats_event_alloc(
110 			struct infra_cp_stats_event *ev)
111 {
112 	ev->sta_stats =
113 	qdf_mem_malloc(sizeof(*ev->sta_stats));
114 	if (!ev->sta_stats) {
115 		return QDF_STATUS_E_NOMEM;
116 	}
117 
118 	return QDF_STATUS_SUCCESS;
119 }
120 #ifdef CONFIG_WLAN_BMISS
121 
122 /**
123  * target_if_infra_cp_stats_bmiss_event_free() - Free event buffer
124  * @ev: pointer to infra cp stats event structure
125  *
126  * Return: None
127  */
128 static
129 void target_if_infra_cp_stats_bmiss_event_free(struct infra_cp_stats_event *ev)
130 {
131 	qdf_mem_free(ev->bmiss_infra_cp_stats);
132 	ev->bmiss_infra_cp_stats = NULL;
133 }
134 
135 /**
136  * target_if_infra_cp_stats_bmiss_event_alloc() - Allocate buffer for bmiss
137  * parameters
138  * @ev: pointer to infra cp stats event structure
139  *
140  * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes on
141  * failure
142  */
143 static QDF_STATUS
144 target_if_infra_cp_stats_bmiss_event_alloc(struct infra_cp_stats_event *ev)
145 {
146 	ev->bmiss_infra_cp_stats =
147 	qdf_mem_malloc(sizeof(*ev->bmiss_infra_cp_stats));
148 	if (!ev->bmiss_infra_cp_stats) {
149 		cp_stats_err("mem alloc failed for ev.bmiss_infra_cp_stats");
150 		return QDF_STATUS_E_NOMEM;
151 	}
152 
153 	return QDF_STATUS_SUCCESS;
154 }
155 #else
156 
157 static inline
158 void target_if_infra_cp_stats_bmiss_event_free(struct infra_cp_stats_event *ev)
159 {
160 }
161 
162 static inline QDF_STATUS
163 target_if_infra_cp_stats_bmiss_event_alloc(struct infra_cp_stats_event *ev)
164 {
165 	return QDF_STATUS_SUCCESS;
166 }
167 #endif /* CONFIG_WLAN_BMISS */
168 
169 /**
170  * target_if_infra_cp_stats_event_free() - Free event buffer
171  * @ev: pointer to infra cp stats event structure
172  *
173  * Return : None
174  */
175 static
176 void target_if_infra_cp_stats_event_free(struct infra_cp_stats_event *ev)
177 {
178 	target_if_infra_cp_stats_twt_event_free(ev);
179 	target_if_infra_cp_stats_bmiss_event_free(ev);
180 	target_if_infra_cp_stats_rrm_sta_stats_event_free(ev);
181 }
182 
183 /**
184  * target_if_infra_cp_stats_event_alloc() - Allocate buffer for event
185  * parameters
186  * @ev: pointer to infra cp stats event structure
187  *
188  * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes on
189  * failure
190  */
191 static QDF_STATUS
192 target_if_infra_cp_stats_event_alloc(struct infra_cp_stats_event *ev)
193 {
194 	QDF_STATUS status;
195 
196 	status = target_if_infra_cp_stats_twt_event_alloc(ev);
197 	if (QDF_IS_STATUS_ERROR(status))
198 		return QDF_STATUS_E_NOMEM;
199 
200 	status = target_if_infra_cp_stats_bmiss_event_alloc(ev);
201 	if (QDF_IS_STATUS_ERROR(status))
202 		return QDF_STATUS_E_NOMEM;
203 
204 	status = target_if_infra_cp_stats_rrm_sta_stats_event_alloc(ev);
205 	if (QDF_IS_STATUS_ERROR(status))
206 		return QDF_STATUS_E_NOMEM;
207 
208 	return QDF_STATUS_SUCCESS;
209 }
210 
211 /**
212  * target_if_extract_infra_cp_stats_event() - Extract data from stats event
213  * @wmi_hdl: WMI Handle
214  * @data: pointer to event data buffer from firmware
215  * @data_len: length of the data buffer
216  * @ev: pointer of output structure to be filled with extracted values
217  *
218  * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes
219  * on failure
220  */
221 static QDF_STATUS
222 target_if_extract_infra_cp_stats_event(struct wmi_unified *wmi_hdl,
223 				       uint8_t *data, uint32_t data_len,
224 				       struct infra_cp_stats_event *ev)
225 {
226 	QDF_STATUS status;
227 	uint32_t more_flag = 0;
228 
229 	status = wmi_unified_extract_cp_stats_more_pending(wmi_hdl, data,
230 							   &more_flag);
231 
232 	status = wmi_unified_extract_infra_cp_stats(wmi_hdl, data,
233 						    data_len, ev);
234 
235 	cp_stats_debug("request_id %d", ev->request_id);
236 
237 	return QDF_STATUS_SUCCESS;
238 }
239 
240 /**
241  * target_if_infra_cp_stats_event_handler() - Handle
242  * wmi_pdev_cp_fwstats_eventid
243  * @scn: opaque scn handle
244  * @data: event buffer received from fw
245  * @datalen: length of event buffer
246  *
247  * Return: 0 for success or non zero error codes for failure
248  */
249 static
250 int target_if_infra_cp_stats_event_handler(ol_scn_t scn, uint8_t *data,
251 					   uint32_t datalen)
252 {
253 	QDF_STATUS status;
254 	struct infra_cp_stats_event ev = {0};
255 	struct wlan_objmgr_psoc *psoc;
256 	struct wmi_unified *wmi_handle;
257 	struct wlan_lmac_if_cp_stats_rx_ops *rx_ops;
258 
259 	cp_stats_debug("Enter");
260 
261 	if (!scn || !data) {
262 		cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
263 		return -EINVAL;
264 	}
265 
266 	psoc = target_if_get_psoc_from_scn_hdl(scn);
267 	if (!psoc) {
268 		cp_stats_err("null psoc");
269 		return -EINVAL;
270 	}
271 
272 	rx_ops = target_if_cp_stats_get_rx_ops(psoc);
273 	if (!rx_ops || !rx_ops->process_stats_event) {
274 		cp_stats_err("callback not registered");
275 		return -EINVAL;
276 	}
277 
278 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
279 	if (!wmi_handle) {
280 		cp_stats_err("wmi_handle is null");
281 		return -EINVAL;
282 	}
283 	status = target_if_infra_cp_stats_event_alloc(&ev);
284 	if (QDF_IS_STATUS_ERROR(status)) {
285 		cp_stats_err("Alloc event mem failed");
286 		goto end;
287 	}
288 
289 	status = target_if_extract_infra_cp_stats_event(wmi_handle, data,
290 							datalen, &ev);
291 	if (QDF_IS_STATUS_ERROR(status)) {
292 		cp_stats_err("extract event failed");
293 		goto end;
294 	}
295 
296 	status = rx_ops->process_infra_stats_event(psoc, &ev);
297 
298 end:
299 	target_if_infra_cp_stats_event_free(&ev);
300 	return qdf_status_to_os_return(status);
301 }
302 #else
303 static
304 int target_if_infra_cp_stats_event_handler(ol_scn_t scn, uint8_t *data,
305 					   uint32_t datalen)
306 {
307 	return 0;
308 }
309 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
310 
311 #if defined(WLAN_SUPPORT_TWT) && defined(WLAN_TWT_CONV_SUPPORTED)
312 static int
313 target_if_twt_session_params_event_handler(ol_scn_t scn,
314 					   uint8_t *evt_buf,
315 					   uint32_t evt_data_len)
316 {
317 	struct wlan_objmgr_psoc *psoc;
318 	struct wlan_objmgr_peer *peer_obj;
319 	struct wmi_unified *wmi_hdl;
320 	struct twt_session_stats_info twt_params;
321 	struct twt_session_stats_event_param params = {0};
322 	struct peer_cp_stats *peer_cp_stats;
323 	int i;
324 	QDF_STATUS status;
325 	uint32_t ev;
326 	cdp_config_param_type val = {0};
327 	ol_txrx_soc_handle soc_txrx_handle;
328 	struct wlan_lmac_if_rx_ops *rx_ops;
329 
330 	TARGET_IF_ENTER();
331 
332 	if (!scn || !evt_buf) {
333 		target_if_err("scn: 0x%pK, evt_buf: 0x%pK", scn, evt_buf);
334 		return -EINVAL;
335 	}
336 
337 	psoc = target_if_get_psoc_from_scn_hdl(scn);
338 	if (!psoc) {
339 		target_if_err("psoc object is null!");
340 		return -EINVAL;
341 	}
342 
343 	soc_txrx_handle = wlan_psoc_get_dp_handle(psoc);
344 	if (!soc_txrx_handle)
345 		return -EINVAL;
346 
347 	wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc);
348 	if (!wmi_hdl) {
349 		target_if_err("wmi_handle is null!");
350 		return -EINVAL;
351 	}
352 
353 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
354 	if (!rx_ops) {
355 		target_if_err("No valid twt session stats rx ops");
356 		return -EINVAL;
357 	}
358 
359 	status = wmi_extract_twt_session_stats_event(wmi_hdl, evt_buf, &params);
360 	if (QDF_IS_STATUS_ERROR(status)) {
361 		target_if_err("Could not extract twt session stats event");
362 		return qdf_status_to_os_return(status);
363 	}
364 
365 	if (params.num_sessions > WLAN_MAX_TWT_SESSIONS_PER_PEER) {
366 		target_if_err("Number of twt sessions exceeded, num:%d max:%d",
367 			      params.num_sessions, WLAN_MAX_TWT_SESSIONS_PER_PEER);
368 		return -EINVAL;
369 	}
370 
371 	for (i = 0; i < params.num_sessions; i++) {
372 		status = wmi_extract_twt_session_stats_data(wmi_hdl, evt_buf,
373 							    &params,
374 							    &twt_params, i);
375 
376 		if (QDF_IS_STATUS_ERROR(status)) {
377 			target_if_err("Unable to extract twt params for idx %d",
378 				      i);
379 			return -EINVAL;
380 		}
381 		peer_obj = wlan_objmgr_get_peer_by_mac(psoc,
382 						twt_params.peer_mac.bytes,
383 						WLAN_CP_STATS_ID);
384 		if (!peer_obj) {
385 			target_if_err("peer obj not found for "QDF_MAC_ADDR_FMT,
386 				      QDF_MAC_ADDR_REF(twt_params.peer_mac.bytes));
387 			continue;
388 		}
389 
390 		ev = twt_params.event_type;
391 		if (ev == HOST_TWT_SESSION_SETUP)
392 			val.cdp_peer_param_in_twt = 1;
393 		else if (ev == HOST_TWT_SESSION_TEARDOWN)
394 			val.cdp_peer_param_in_twt = 0;
395 
396 		cdp_txrx_set_peer_param(soc_txrx_handle, twt_params.vdev_id,
397 					twt_params.peer_mac.bytes,
398 					CDP_CONFIG_IN_TWT, val);
399 
400 		peer_cp_stats = wlan_cp_stats_get_peer_stats_obj(peer_obj);
401 		if (!peer_cp_stats) {
402 			target_if_err("peer_cp_stats is null");
403 			continue;
404 		}
405 
406 		wlan_cp_stats_peer_obj_lock(peer_cp_stats);
407 
408 		rx_ops->cp_stats_rx_ops.twt_get_session_param_resp(psoc,
409 								 &twt_params);
410 
411 		wlan_cp_stats_peer_obj_unlock(peer_cp_stats);
412 		wlan_objmgr_peer_release_ref(peer_obj, WLAN_CP_STATS_ID);
413 	}
414 	return 0;
415 }
416 
417 static QDF_STATUS
418 target_if_cp_stats_register_twt_session_event(struct wmi_unified *wmi_handle)
419 {
420 	QDF_STATUS ret_val;
421 
422 	ret_val = wmi_unified_register_event_handler(wmi_handle,
423 				wmi_twt_session_stats_event_id,
424 				target_if_twt_session_params_event_handler,
425 				WMI_RX_WORK_CTX);
426 
427 	return ret_val;
428 }
429 
430 static void
431 target_if_cp_stats_unregister_twt_session_event(struct wmi_unified *wmi_handle)
432 {
433 	wmi_unified_unregister_event_handler(wmi_handle,
434 					     wmi_twt_session_stats_event_id);
435 }
436 #else
437 static QDF_STATUS
438 target_if_cp_stats_register_twt_session_event(struct wmi_unified *wmi_handle)
439 {
440 	return QDF_STATUS_SUCCESS;
441 }
442 
443 static void
444 target_if_cp_stats_unregister_twt_session_event(struct wmi_unified *wmi_handle)
445 {
446 }
447 #endif /*  WLAN_SUPPORT_TWT && WLAN_TWT_CONV_SUPPORTED*/
448 
449 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
450 static QDF_STATUS
451 target_if_cp_stats_infra_register_event_handler(struct wlan_objmgr_psoc *psoc,
452 						struct wmi_unified *wmi_handle)
453 {
454 	QDF_STATUS ret_val;
455 
456 	if (!psoc) {
457 		cp_stats_err("PSOC is NULL!");
458 		return QDF_STATUS_E_INVAL;
459 	}
460 
461 	if (!wmi_handle) {
462 		cp_stats_err("wmi_handle is null");
463 		return QDF_STATUS_E_INVAL;
464 	}
465 
466 	ret_val = wmi_unified_register_event_handler(wmi_handle,
467 						     wmi_pdev_cp_fwstats_eventid,
468 						     target_if_infra_cp_stats_event_handler,
469 						     WMI_RX_WORK_CTX);
470 	if (QDF_IS_STATUS_ERROR(ret_val)) {
471 		cp_stats_err("Failed to register for pdev_cp_fwstats_event");
472 		return ret_val;
473 	}
474 
475 	return QDF_STATUS_SUCCESS;
476 }
477 #else
478 static QDF_STATUS
479 target_if_cp_stats_infra_register_event_handler(struct wlan_objmgr_psoc *psoc,
480 						struct wmi_unified *wmi_handle)
481 {
482 	return QDF_STATUS_SUCCESS;
483 }
484 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
485 
486 static QDF_STATUS
487 target_if_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc)
488 {
489 	struct wmi_unified *wmi_handle;
490 	QDF_STATUS ret_val;
491 
492 	if (!psoc) {
493 		cp_stats_err("PSOC is NULL!");
494 		return QDF_STATUS_E_INVAL;
495 	}
496 
497 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
498 	if (!wmi_handle) {
499 		cp_stats_err("wmi_handle is null");
500 		return QDF_STATUS_E_INVAL;
501 	}
502 
503 	ret_val = target_if_cp_stats_infra_register_event_handler(psoc,
504 								  wmi_handle);
505 	if (QDF_IS_STATUS_ERROR(ret_val)) {
506 		cp_stats_err("Failed to register for pdev_cp_fwstats_event");
507 		return ret_val;
508 	}
509 
510 	ret_val = target_if_cp_stats_register_twt_session_event(wmi_handle);
511 	if (QDF_IS_STATUS_ERROR(ret_val)) {
512 		cp_stats_err("Failed to register twt session stats event");
513 		return ret_val;
514 	}
515 
516 	return QDF_STATUS_SUCCESS;
517 }
518 
519 static QDF_STATUS
520 target_if_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
521 {
522 	struct wmi_unified *wmi_handle;
523 
524 	if (!psoc) {
525 		cp_stats_err("PSOC is NULL!");
526 		return QDF_STATUS_E_INVAL;
527 	}
528 
529 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
530 	if (!wmi_handle) {
531 		cp_stats_err("wmi_handle is null");
532 		return QDF_STATUS_E_INVAL;
533 	}
534 
535 	wmi_unified_unregister_event_handler(wmi_handle,
536 					     wmi_pdev_cp_fwstats_eventid);
537 	target_if_cp_stats_unregister_twt_session_event(wmi_handle);
538 	return QDF_STATUS_SUCCESS;
539 }
540 
541 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
542 /**
543  * target_if_infra_cp_stats_req() - API to send stats request to wmi
544  * @psoc: pointer to psoc object
545  * @req: pointer to object containing stats request parameters
546  *
547  * Return: QDF_STATUS_SUCCESS on success, else other qdf error values
548  */
549 static
550 QDF_STATUS target_if_infra_cp_stats_req(struct wlan_objmgr_psoc *psoc,
551 					struct infra_cp_stats_cmd_info *req)
552 
553 {
554 	struct wmi_unified *wmi_handle;
555 
556 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
557 	if (!wmi_handle) {
558 		cp_stats_err("wmi_handle is null.");
559 		return QDF_STATUS_E_NULL_VALUE;
560 	}
561 
562 	return wmi_unified_infra_cp_stats_request_send(wmi_handle, req);
563 }
564 
565 static void target_if_register_infra_cp_stats_txops(
566 				struct wlan_lmac_if_cp_stats_tx_ops *tx_ops)
567 {
568 	tx_ops->send_req_infra_cp_stats = target_if_infra_cp_stats_req;
569 }
570 #else
571 static void target_if_register_infra_cp_stats_txops(
572 				struct wlan_lmac_if_cp_stats_tx_ops *tx_ops)
573 {
574 }
575 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
576 
577 #ifdef WLAN_CONFIG_TELEMETRY_AGENT
578 /**
579  * target_if_telemetry_cp_stats_req() - API to send stats request to wmi
580  * @pdev: pointer to pdev object
581  * @req: pointer to object containing stats request parameters
582  *
583  * Return: QDF_STATUS_SUCCESS on success, else other qdf error values
584  */
585 static
586 QDF_STATUS target_if_telemetry_cp_stats_req(struct wlan_objmgr_pdev *pdev,
587 					    struct infra_cp_stats_cmd_info *req)
588 {
589 	struct wmi_unified *wmi_handle;
590 
591 	wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
592 	if (!wmi_handle) {
593 		cp_stats_err("wmi_handle is null.");
594 		return QDF_STATUS_E_NULL_VALUE;
595 	}
596 	return wmi_unified_infra_cp_stats_request_send(wmi_handle, req);
597 }
598 
599 static void target_if_register_telemetry_cp_stats_txops(
600 				struct wlan_lmac_if_cp_stats_tx_ops *tx_ops)
601 {
602 	tx_ops->send_req_telemetry_cp_stats = target_if_telemetry_cp_stats_req;
603 }
604 #else
605 static void target_if_register_telemetry_cp_stats_txops(
606 				struct wlan_lmac_if_cp_stats_tx_ops *tx_ops)
607 { }
608 #endif
609 #ifdef WLAN_CHIPSET_STATS
610 QDF_STATUS
611 target_if_cp_stats_is_service_cstats_enabled(struct wlan_objmgr_psoc *psoc,
612 					     bool *is_fw_support_cstats)
613 {
614 	struct wmi_unified *wmi_handle;
615 
616 	if (!psoc) {
617 		cp_stats_err("psoc is NULL!");
618 		return QDF_STATUS_E_INVAL;
619 	}
620 
621 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
622 	if (!wmi_handle) {
623 		cp_stats_err("wmi_handle is null");
624 		return QDF_STATUS_E_NULL_VALUE;
625 	}
626 
627 	*is_fw_support_cstats =
628 		wmi_service_enabled(wmi_handle,
629 				    wmi_service_chipset_logging_support);
630 	return QDF_STATUS_SUCCESS;
631 }
632 
633 static QDF_STATUS
634 target_if_cp_stats_enable_cstats(struct wlan_objmgr_psoc *psoc,
635 				 uint32_t param_val, uint8_t mac_id)
636 {
637 	struct wmi_unified *wmi_handle;
638 	struct pdev_params params = {0};
639 
640 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
641 	if (!wmi_handle) {
642 		cp_stats_err("wmi_handle is null");
643 		return QDF_STATUS_E_NULL_VALUE;
644 	}
645 
646 	params.param_id = WMI_PDEV_PARAM_ENABLE_CHIPSET_LOGGING;
647 	params.param_value = param_val;
648 
649 	return wmi_unified_pdev_param_send(wmi_handle, &params, mac_id);
650 }
651 
652 /**
653  * target_if_register_cstats_enable_txops() - Register cstats enable in txops
654  *
655  * @ops: pointer to wlan_lmac_if_cp_stats_tx_ops
656  *
657  * Return: void
658  */
659 static void
660 target_if_register_cstats_enable_txops(struct wlan_lmac_if_cp_stats_tx_ops *ops)
661 {
662 	ops->send_cstats_enable = target_if_cp_stats_enable_cstats;
663 }
664 #else
665 static void
666 target_if_register_cstats_enable_txops(struct wlan_lmac_if_cp_stats_tx_ops *ops)
667 {
668 }
669 #endif
670 
671 QDF_STATUS
672 target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
673 {
674 	struct wlan_lmac_if_cp_stats_tx_ops *cp_stats_tx_ops;
675 
676 	if (!tx_ops) {
677 		cp_stats_err("lmac tx ops is NULL!");
678 		return QDF_STATUS_E_INVAL;
679 	}
680 
681 	cp_stats_tx_ops = &tx_ops->cp_stats_tx_ops;
682 	if (!cp_stats_tx_ops) {
683 		cp_stats_err("lmac tx ops is NULL!");
684 		return QDF_STATUS_E_FAILURE;
685 	}
686 
687 	target_if_register_cstats_enable_txops(cp_stats_tx_ops);
688 
689 	target_if_register_infra_cp_stats_txops(cp_stats_tx_ops);
690 	target_if_register_telemetry_cp_stats_txops(cp_stats_tx_ops);
691 
692 	cp_stats_tx_ops->cp_stats_attach =
693 		target_if_cp_stats_register_event_handler;
694 	cp_stats_tx_ops->cp_stats_detach =
695 		target_if_cp_stats_unregister_event_handler;
696 	cp_stats_tx_ops->cp_stats_legacy_attach =
697 		target_if_cp_stats_register_legacy_event_handler;
698 	cp_stats_tx_ops->cp_stats_legacy_detach =
699 		target_if_cp_stats_unregister_legacy_event_handler;
700 	return QDF_STATUS_SUCCESS;
701 }
702 
703