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