xref: /wlan-dirver/qca-wifi-host-cmn/umac/cp_stats/core/src/wlan_cp_stats_obj_mgr_handler.c (revision 3b7d2086205cc4b82a36a180614a8914e54e8fed)
1 /*
2  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-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: wlan_cp_stats_om_handler.c
22  *
23  * This file provide definitions to APIs invoked on receiving common object
24  * respective create/destroy event notifications, which further
25  * (de)allocate cp specific objects and (de)attach to specific
26  * common object
27  */
28 #include "wlan_cp_stats_obj_mgr_handler.h"
29 #include "wlan_cp_stats_defs.h"
30 #include "wlan_cp_stats_ol_api.h"
31 #include <wlan_cp_stats_ucfg_api.h>
32 #include "wlan_cp_stats_utils_api.h"
33 #include <target_if_cp_stats.h>
34 #include <wlan_twt_public_structs.h>
35 
36 QDF_STATUS
37 wlan_cp_stats_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
38 {
39 	WLAN_DEV_TYPE dev_type;
40 	struct cp_stats_context *csc = NULL;
41 	struct psoc_cp_stats *psoc_cs = NULL;
42 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
43 
44 	if (!psoc) {
45 		cp_stats_err("PSOC is NULL");
46 		status = QDF_STATUS_E_INVAL;
47 		goto wlan_cp_stats_psoc_obj_create_handler_return;
48 	}
49 
50 	csc = qdf_mem_malloc(sizeof(*csc));
51 	if (!csc) {
52 		status = QDF_STATUS_E_NOMEM;
53 		goto wlan_cp_stats_psoc_obj_create_handler_return;
54 	}
55 
56 	csc->psoc_obj = psoc;
57 	dev_type = wlan_objmgr_psoc_get_dev_type(csc->psoc_obj);
58 	if (dev_type == WLAN_DEV_INVALID) {
59 		cp_stats_err("Failed to init cp stats ctx, bad device type");
60 		status = QDF_STATUS_E_INVAL;
61 		goto wlan_cp_stats_psoc_obj_create_handler_return;
62 	} else if (WLAN_DEV_OL == dev_type) {
63 		csc->cp_stats_ctx_init = wlan_cp_stats_ctx_init_ol;
64 		csc->cp_stats_ctx_deinit = wlan_cp_stats_ctx_deinit_ol;
65 	}
66 
67 	if (QDF_STATUS_SUCCESS != csc->cp_stats_ctx_init(csc)) {
68 		cp_stats_err("Failed to init global ctx call back handlers");
69 		goto wlan_cp_stats_psoc_obj_create_handler_return;
70 	}
71 
72 	psoc_cs = qdf_mem_malloc(sizeof(*psoc_cs));
73 	if (!psoc_cs) {
74 		status = QDF_STATUS_E_NOMEM;
75 		goto wlan_cp_stats_psoc_obj_create_handler_return;
76 	}
77 
78 	psoc_cs->psoc_obj = psoc;
79 	csc->psoc_cs = psoc_cs;
80 	if (csc->cp_stats_psoc_obj_init) {
81 		if (QDF_STATUS_SUCCESS !=
82 				csc->cp_stats_psoc_obj_init(psoc_cs)) {
83 			cp_stats_err("Failed to initialize psoc handlers");
84 			goto wlan_cp_stats_psoc_obj_create_handler_return;
85 		}
86 	}
87 
88 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
89 						       WLAN_UMAC_COMP_CP_STATS,
90 						       csc,
91 						       QDF_STATUS_SUCCESS);
92 
93 wlan_cp_stats_psoc_obj_create_handler_return:
94 	if (QDF_IS_STATUS_ERROR(status)) {
95 		if (csc) {
96 			if (csc->cp_stats_psoc_obj_deinit && psoc_cs)
97 				csc->cp_stats_psoc_obj_deinit(psoc_cs);
98 
99 			if (csc->psoc_cs) {
100 				qdf_mem_free(csc->psoc_cs);
101 				csc->psoc_cs = NULL;
102 			}
103 
104 			if (csc->cp_stats_ctx_deinit)
105 				csc->cp_stats_ctx_deinit(csc);
106 
107 			qdf_mem_free(csc);
108 			csc = NULL;
109 		}
110 		return status;
111 	}
112 
113 	cp_stats_debug("cp stats context attach at psoc");
114 	return status;
115 }
116 
117 QDF_STATUS
118 wlan_cp_stats_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, void *arg)
119 {
120 	struct cp_stats_context *csc;
121 
122 	if (!psoc) {
123 		cp_stats_err("PSOC is NULL");
124 		return QDF_STATUS_E_NOMEM;
125 	}
126 	csc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
127 						    WLAN_UMAC_COMP_CP_STATS);
128 	if (!csc) {
129 		cp_stats_err("cp_stats context is NULL!");
130 		return QDF_STATUS_E_INVAL;
131 	}
132 
133 	wlan_objmgr_psoc_component_obj_detach(psoc,
134 					      WLAN_UMAC_COMP_CP_STATS, csc);
135 	if (csc->cp_stats_psoc_obj_deinit)
136 		csc->cp_stats_psoc_obj_deinit(csc->psoc_cs);
137 	qdf_mem_free(csc->psoc_cs);
138 	if (csc->cp_stats_ctx_deinit)
139 		csc->cp_stats_ctx_deinit(csc);
140 	qdf_mem_free(csc);
141 
142 	cp_stats_debug("cp stats context detached at psoc");
143 	return QDF_STATUS_SUCCESS;
144 }
145 
146 QDF_STATUS
147 wlan_cp_stats_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
148 {
149 	struct cp_stats_context *csc = NULL;
150 	struct pdev_cp_stats *pdev_cs = NULL;
151 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
152 
153 	if (!pdev) {
154 		cp_stats_err("PDEV is NULL");
155 		status = QDF_STATUS_E_INVAL;
156 		goto wlan_cp_stats_pdev_obj_create_handler_return;
157 	}
158 
159 	pdev_cs = qdf_mem_malloc(sizeof(*pdev_cs));
160 	if (!pdev_cs) {
161 		status = QDF_STATUS_E_NOMEM;
162 		goto wlan_cp_stats_pdev_obj_create_handler_return;
163 	}
164 	csc = wlan_cp_stats_ctx_get_from_pdev(pdev);
165 	if (!csc) {
166 		cp_stats_err("cp_stats context is NULL!");
167 		status = QDF_STATUS_E_INVAL;
168 		goto wlan_cp_stats_pdev_obj_create_handler_return;
169 	}
170 	pdev_cs->pdev_obj = pdev;
171 	if (csc->cp_stats_pdev_obj_init) {
172 		if (QDF_STATUS_SUCCESS !=
173 				csc->cp_stats_pdev_obj_init(pdev_cs)) {
174 			cp_stats_err("Failed to initialize pdev handlers");
175 			goto wlan_cp_stats_pdev_obj_create_handler_return;
176 		}
177 	}
178 
179 	status = wlan_objmgr_pdev_component_obj_attach(pdev,
180 						       WLAN_UMAC_COMP_CP_STATS,
181 						       pdev_cs,
182 						       QDF_STATUS_SUCCESS);
183 
184 	cp_stats_debug("pdev cp stats object attached");
185 wlan_cp_stats_pdev_obj_create_handler_return:
186 	if (QDF_IS_STATUS_ERROR(status)) {
187 		if (csc) {
188 			if (csc->cp_stats_pdev_obj_deinit)
189 				csc->cp_stats_pdev_obj_deinit(pdev_cs);
190 		}
191 
192 		if (pdev_cs)
193 			qdf_mem_free(pdev_cs);
194 	}
195 
196 	return status;
197 }
198 
199 QDF_STATUS
200 wlan_cp_stats_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg)
201 {
202 	struct pdev_cp_stats *pdev_cs;
203 	struct cp_stats_context *csc;
204 
205 	if (!pdev) {
206 		cp_stats_err("pdev is NULL");
207 		return QDF_STATUS_E_INVAL;
208 	}
209 
210 	pdev_cs = wlan_objmgr_pdev_get_comp_private_obj(pdev,
211 						WLAN_UMAC_COMP_CP_STATS);
212 	if (!pdev_cs) {
213 		cp_stats_err("pdev is NULL");
214 		return QDF_STATUS_E_INVAL;
215 	}
216 	csc = wlan_cp_stats_ctx_get_from_pdev(pdev);
217 	if (!csc) {
218 		cp_stats_err("cp_stats context is NULL!");
219 		return QDF_STATUS_E_INVAL;
220 	}
221 
222 	if (csc->cp_stats_pdev_obj_deinit)
223 		csc->cp_stats_pdev_obj_deinit(pdev_cs);
224 
225 	wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_CP_STATS,
226 					      pdev_cs);
227 
228 	qdf_mem_free(pdev_cs);
229 	cp_stats_debug("pdev cp stats object detached");
230 	return QDF_STATUS_SUCCESS;
231 }
232 
233 QDF_STATUS
234 wlan_cp_stats_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, void *arg)
235 {
236 	struct cp_stats_context *csc = NULL;
237 	struct vdev_cp_stats *vdev_cs = NULL;
238 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
239 
240 	if (!vdev) {
241 		cp_stats_err("vdev is NULL");
242 		status = QDF_STATUS_E_INVAL;
243 		goto wlan_cp_stats_vdev_obj_create_handler_return;
244 	}
245 
246 	vdev_cs = qdf_mem_malloc(sizeof(*vdev_cs));
247 	if (!vdev_cs) {
248 		status = QDF_STATUS_E_NOMEM;
249 		goto wlan_cp_stats_vdev_obj_create_handler_return;
250 	}
251 	csc = wlan_cp_stats_ctx_get_from_vdev(vdev);
252 	if (!csc) {
253 		cp_stats_err("cp_stats context is NULL!");
254 		status = QDF_STATUS_E_INVAL;
255 		goto wlan_cp_stats_vdev_obj_create_handler_return;
256 	}
257 	vdev_cs->vdev_obj = vdev;
258 	if (csc->cp_stats_vdev_obj_init) {
259 		if (QDF_STATUS_SUCCESS !=
260 				csc->cp_stats_vdev_obj_init(vdev_cs)) {
261 			cp_stats_err("Failed to initialize vdev handlers");
262 			goto wlan_cp_stats_vdev_obj_create_handler_return;
263 		}
264 	}
265 
266 	status = wlan_objmgr_vdev_component_obj_attach(vdev,
267 						       WLAN_UMAC_COMP_CP_STATS,
268 						       vdev_cs,
269 						       QDF_STATUS_SUCCESS);
270 
271 wlan_cp_stats_vdev_obj_create_handler_return:
272 	if (QDF_IS_STATUS_ERROR(status)) {
273 		if (csc) {
274 			if (csc->cp_stats_vdev_obj_deinit)
275 				csc->cp_stats_vdev_obj_deinit(vdev_cs);
276 		}
277 
278 		if (vdev_cs)
279 			qdf_mem_free(vdev_cs);
280 	}
281 
282 	cp_stats_debug("vdev cp stats object attach");
283 	return status;
284 }
285 
286 QDF_STATUS
287 wlan_cp_stats_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev, void *arg)
288 {
289 	struct vdev_cp_stats *vdev_cs;
290 	struct cp_stats_context *csc;
291 
292 	if (!vdev) {
293 		cp_stats_err("vdev is NULL");
294 		return QDF_STATUS_E_INVAL;
295 	}
296 
297 	vdev_cs = wlan_objmgr_vdev_get_comp_private_obj(vdev,
298 						WLAN_UMAC_COMP_CP_STATS);
299 	if (!vdev_cs) {
300 		cp_stats_err("vdev is NULL");
301 		return QDF_STATUS_E_INVAL;
302 	}
303 	csc = wlan_cp_stats_ctx_get_from_vdev(vdev);
304 	if (!csc) {
305 		cp_stats_err("cp_stats context is NULL!");
306 		return QDF_STATUS_E_INVAL;
307 	}
308 
309 	if (csc->cp_stats_vdev_obj_deinit)
310 		csc->cp_stats_vdev_obj_deinit(vdev_cs);
311 
312 	wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_CP_STATS,
313 					      vdev_cs);
314 
315 	qdf_mem_free(vdev_cs);
316 	cp_stats_debug("vdev cp stats object detach");
317 	return QDF_STATUS_SUCCESS;
318 }
319 
320 QDF_STATUS
321 wlan_cp_stats_peer_obj_create_handler(struct wlan_objmgr_peer *peer, void *arg)
322 {
323 	struct cp_stats_context *csc = NULL;
324 	struct peer_cp_stats *peer_cs = NULL;
325 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
326 
327 	if (!peer) {
328 		cp_stats_err("peer is NULL");
329 		status = QDF_STATUS_E_INVAL;
330 		goto wlan_cp_stats_peer_obj_create_handler_return;
331 	}
332 
333 	peer_cs = qdf_mem_malloc(sizeof(*peer_cs));
334 	if (!peer_cs) {
335 		status = QDF_STATUS_E_NOMEM;
336 		goto wlan_cp_stats_peer_obj_create_handler_return;
337 	}
338 	csc = wlan_cp_stats_ctx_get_from_peer(peer);
339 	if (!csc) {
340 		cp_stats_err("cp_stats context is NULL!");
341 		status = QDF_STATUS_E_INVAL;
342 		goto wlan_cp_stats_peer_obj_create_handler_return;
343 	}
344 	peer_cs->peer_obj = peer;
345 	if (csc->cp_stats_peer_obj_init) {
346 		if (QDF_STATUS_SUCCESS !=
347 				csc->cp_stats_peer_obj_init(peer_cs)) {
348 			cp_stats_err("Failed to initialize peer handlers");
349 			goto wlan_cp_stats_peer_obj_create_handler_return;
350 		}
351 	}
352 
353 	status = wlan_objmgr_peer_component_obj_attach(peer,
354 						       WLAN_UMAC_COMP_CP_STATS,
355 						       peer_cs,
356 						       QDF_STATUS_SUCCESS);
357 
358 wlan_cp_stats_peer_obj_create_handler_return:
359 	if (QDF_IS_STATUS_ERROR(status)) {
360 		if (csc) {
361 			if (csc->cp_stats_peer_obj_deinit)
362 				csc->cp_stats_peer_obj_deinit(peer_cs);
363 		}
364 
365 		if (peer_cs)
366 			qdf_mem_free(peer_cs);
367 	}
368 
369 	cp_stats_debug("peer cp stats object attach");
370 	return status;
371 }
372 
373 QDF_STATUS
374 wlan_cp_stats_peer_obj_destroy_handler(struct wlan_objmgr_peer *peer, void *arg)
375 {
376 	struct peer_cp_stats *peer_cs;
377 	struct cp_stats_context *csc;
378 
379 	if (!peer) {
380 		cp_stats_err("peer is NULL");
381 		return QDF_STATUS_E_INVAL;
382 	}
383 
384 	peer_cs = wlan_objmgr_peer_get_comp_private_obj(peer,
385 						WLAN_UMAC_COMP_CP_STATS);
386 	if (!peer_cs) {
387 		cp_stats_err("peer is NULL");
388 		return QDF_STATUS_E_INVAL;
389 	}
390 	csc = wlan_cp_stats_ctx_get_from_peer(peer);
391 	if (!csc) {
392 		cp_stats_err("cp_stats context is NULL!");
393 		return QDF_STATUS_E_INVAL;
394 	}
395 
396 	if (csc->cp_stats_peer_obj_deinit)
397 		csc->cp_stats_peer_obj_deinit(peer_cs);
398 
399 	wlan_objmgr_peer_component_obj_detach(peer, WLAN_UMAC_COMP_CP_STATS,
400 					      peer_cs);
401 
402 	qdf_mem_free(peer_cs);
403 	cp_stats_debug("peer cp stats object detached");
404 	return QDF_STATUS_SUCCESS;
405 }
406 
407 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
408 QDF_STATUS
409 wlan_cp_stats_infra_cp_register_resp_cb(struct wlan_objmgr_psoc *psoc,
410 					struct infra_cp_stats_cmd_info *req)
411 {
412 	struct psoc_cp_stats *psoc_cp_stats_priv;
413 
414 	psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc);
415 	if (!psoc_cp_stats_priv) {
416 		cp_stats_err("psoc cp stats object is null");
417 		return QDF_STATUS_E_NULL_VALUE;
418 	}
419 
420 	wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
421 	psoc_cp_stats_priv->get_infra_cp_stats = req->infra_cp_stats_resp_cb;
422 	psoc_cp_stats_priv->infra_cp_stats_req_context = req->request_cookie;
423 	wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
424 
425 	return QDF_STATUS_SUCCESS;
426 }
427 
428 QDF_STATUS
429 wlan_cp_stats_infra_cp_deregister_resp_cb(struct wlan_objmgr_psoc *psoc)
430 {
431 	struct psoc_cp_stats *psoc_cp_stats_priv;
432 
433 	psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc);
434 	if (!psoc_cp_stats_priv) {
435 		cp_stats_err("psoc cp stats object is null");
436 		return QDF_STATUS_E_NULL_VALUE;
437 	}
438 
439 	wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
440 	if (psoc_cp_stats_priv->get_infra_cp_stats)
441 		psoc_cp_stats_priv->get_infra_cp_stats = NULL;
442 	wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
443 
444 	return QDF_STATUS_SUCCESS;
445 }
446 
447 QDF_STATUS
448 wlan_cp_stats_infra_cp_get_context(struct wlan_objmgr_psoc *psoc,
449 				   get_infra_cp_stats_cb *resp_cb,
450 				   void **context)
451 {
452 	struct psoc_cp_stats *psoc_cp_stats_priv;
453 
454 	psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc);
455 	if (!psoc_cp_stats_priv) {
456 		cp_stats_err("psoc cp stats object is null");
457 		return QDF_STATUS_E_NULL_VALUE;
458 	}
459 
460 	wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
461 	if (psoc_cp_stats_priv->get_infra_cp_stats)
462 		*resp_cb = psoc_cp_stats_priv->get_infra_cp_stats;
463 	if (psoc_cp_stats_priv->infra_cp_stats_req_context)
464 		*context = psoc_cp_stats_priv->infra_cp_stats_req_context;
465 	wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
466 
467 	return QDF_STATUS_SUCCESS;
468 }
469 
470 QDF_STATUS
471 wlan_cp_stats_send_infra_cp_req(struct wlan_objmgr_psoc *psoc,
472 				struct infra_cp_stats_cmd_info *req)
473 {
474 	struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
475 
476 	tx_ops = target_if_cp_stats_get_tx_ops(psoc);
477 	if (!tx_ops) {
478 		cp_stats_err("could not get tx_ops");
479 		return QDF_STATUS_E_NULL_VALUE;
480 	}
481 
482 	if (!tx_ops->send_req_infra_cp_stats) {
483 		cp_stats_err("could not get send_req_infra_twt_stats");
484 		return QDF_STATUS_E_NULL_VALUE;
485 	}
486 	return tx_ops->send_req_infra_cp_stats(psoc, req);
487 }
488 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
489 
490 #ifdef WLAN_CONFIG_TELEMETRY_AGENT
491 QDF_STATUS
492 wlan_cp_stats_send_telemetry_cp_req(struct wlan_objmgr_pdev *pdev,
493 				    struct infra_cp_stats_cmd_info *req)
494 {
495 	struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
496 
497 	tx_ops = target_if_cp_stats_get_tx_ops(wlan_pdev_get_psoc(pdev));
498 	if (!tx_ops) {
499 		cp_stats_err("could not get tx_ops");
500 		return QDF_STATUS_E_NULL_VALUE;
501 	}
502 
503 	if (!tx_ops->send_req_telemetry_cp_stats) {
504 		cp_stats_err("could not get send_req_infra_twt_stats");
505 		return QDF_STATUS_E_NULL_VALUE;
506 	}
507 	return tx_ops->send_req_telemetry_cp_stats(pdev, req);
508 }
509 #endif
510 
511 #if defined(WLAN_SUPPORT_TWT) && defined (WLAN_TWT_CONV_SUPPORTED)
512 /**
513  * wlan_cp_stats_twt_get_peer_session_param() - Obtains twt session parameters
514  * of a peer if twt session is valid
515  * @peer_cp_stat_prv: pointer to peer specific stats
516  * @params: Pointer to copy twt session parameters
517  * @num_twt_session: Pointer holding total number of valid twt sessions
518  *
519  * Return: QDF_STATUS success if valid twt session parameters are obtained
520  * else other qdf error values
521  */
522 static QDF_STATUS
523 wlan_cp_stats_twt_get_peer_session_param(struct peer_cp_stats *peer_cp_stat_prv,
524 					 struct twt_session_stats_info *params,
525 					 int *num_twt_session)
526 {
527 	struct twt_session_stats_info *twt_params;
528 	QDF_STATUS qdf_status = QDF_STATUS_E_INVAL;
529 	uint32_t event_type;
530 	int i;
531 
532 	if (!peer_cp_stat_prv || !params)
533 		return qdf_status;
534 
535 	for (i = 0; i < WLAN_MAX_TWT_SESSIONS_PER_PEER; i++) {
536 		twt_params = &peer_cp_stat_prv->twt_param[i];
537 		event_type = peer_cp_stat_prv->twt_param[i].event_type;
538 
539 		/* Check twt session is established */
540 
541 		if (event_type == HOST_TWT_SESSION_SETUP ||
542 		    event_type == HOST_TWT_SESSION_UPDATE) {
543 			qdf_mem_copy(&params[*num_twt_session], twt_params,
544 				     sizeof(*twt_params));
545 			qdf_status = QDF_STATUS_SUCCESS;
546 			*num_twt_session += 1;
547 		}
548 	}
549 
550 	return qdf_status;
551 }
552 
553 /**
554  * wlan_cp_stats_twt_get_all_peer_session_params()- Retrieves twt session
555  * parameters of all peers with valid twt session
556  * @psoc_obj: psoc object
557  * @vdev_id: vdev_id
558  * @params: array of pointer to store peer twt session parameters
559  *
560  * Return: total number of valid twt sessions
561  */
562 static int
563 wlan_cp_stats_twt_get_all_peer_session_params(
564 					struct wlan_objmgr_psoc *psoc_obj,
565 					uint8_t vdev_id,
566 					struct twt_session_stats_info *params)
567 {
568 	qdf_list_t *peer_list;
569 	struct wlan_objmgr_peer *peer, *peer_next;
570 	struct wlan_objmgr_vdev *vdev;
571 	struct peer_cp_stats *cp_stats_peer_obj, *peer_cp_stat_prv;
572 	int num_twt_session = 0;
573 	enum QDF_OPMODE opmode;
574 	uint16_t sap_num_peer;
575 
576 	if (!psoc_obj) {
577 		cp_stats_err("psoc is NULL");
578 		return num_twt_session;
579 	}
580 
581 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc_obj, vdev_id,
582 						    WLAN_CP_STATS_ID);
583 	if (!vdev) {
584 		cp_stats_err("vdev is NULL, vdev_id: %d", vdev_id);
585 		return num_twt_session;
586 	}
587 
588 	sap_num_peer = wlan_vdev_get_peer_count(vdev);
589 	opmode = wlan_vdev_mlme_get_opmode(vdev);
590 
591 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
592 	if (!peer_list) {
593 		wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
594 		cp_stats_err("Peer list for vdev obj is NULL");
595 		return num_twt_session;
596 	}
597 
598 	peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list,
599 						    WLAN_CP_STATS_ID);
600 	while (peer) {
601 		cp_stats_peer_obj = wlan_objmgr_peer_get_comp_private_obj(
602 						peer, WLAN_UMAC_COMP_CP_STATS);
603 
604 		peer_cp_stat_prv = wlan_cp_stats_get_peer_stats_obj(peer);
605 		if (peer_cp_stat_prv) {
606 			wlan_cp_stats_peer_obj_lock(peer_cp_stat_prv);
607 			wlan_cp_stats_twt_get_peer_session_param(
608 							peer_cp_stat_prv,
609 							params,
610 							&num_twt_session);
611 			wlan_cp_stats_peer_obj_unlock(peer_cp_stat_prv);
612 		}
613 
614 		if (opmode == QDF_STA_MODE &&
615 		    num_twt_session >= WLAN_MAX_TWT_SESSIONS_PER_PEER) {
616 			wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
617 			goto done;
618 		}
619 
620 		if (opmode == QDF_SAP_MODE &&
621 		    num_twt_session >= (sap_num_peer * WLAN_MAX_TWT_SESSIONS_PER_PEER)) {
622 			wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
623 			goto done;
624 		}
625 
626 		peer_next = wlan_peer_get_next_active_peer_of_vdev(
627 						vdev, peer_list, peer,
628 						WLAN_CP_STATS_ID);
629 		wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
630 		peer = peer_next;
631 	}
632 done:
633 	if (!num_twt_session)
634 		cp_stats_err("Unable to find a peer with twt session established");
635 
636 	wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
637 	return num_twt_session;
638 }
639 
640 /**
641  * wlan_cp_stats_twt_get_peer_session_param_by_dlg_id() - Finds a Peer twt
642  * session with dialog id matching with input dialog id. If a match is found
643  * copies the twt session parameters
644  * @peer_cp_stats_priv: pointer to peer specific stats
645  * @input_dialog_id: input dialog id
646  * @dest_param: Pointer to copy twt session parameters when a peer with
647  * given dialog id is found
648  * @num_twt_session: Pointer holding total number of valid twt session
649  *
650  * Return: Success if stats are copied for a peer with given dialog,
651  * else failure
652  */
653 static QDF_STATUS
654 wlan_cp_stats_twt_get_peer_session_param_by_dlg_id(
655 				struct peer_cp_stats *peer_cp_stats_priv,
656 				uint32_t input_dialog_id,
657 				struct twt_session_stats_info *dest_param,
658 				int *num_twt_session)
659 {
660 	struct twt_session_stats_info *src_param;
661 	uint32_t event_type;
662 	int i = 0;
663 	QDF_STATUS qdf_status = QDF_STATUS_E_INVAL;
664 
665 	if (!peer_cp_stats_priv || !dest_param)
666 		return qdf_status;
667 
668 	for (i = 0; i < WLAN_MAX_TWT_SESSIONS_PER_PEER; i++) {
669 		event_type = peer_cp_stats_priv->twt_param[i].event_type;
670 		src_param = &peer_cp_stats_priv->twt_param[i];
671 		if (!event_type ||
672 		    (src_param->dialog_id != input_dialog_id &&
673 		    input_dialog_id != TWT_ALL_SESSIONS_DIALOG_ID))
674 			continue;
675 
676 		if (event_type == HOST_TWT_SESSION_SETUP ||
677 		    event_type == HOST_TWT_SESSION_UPDATE) {
678 			qdf_mem_copy(&dest_param[*num_twt_session], src_param,
679 				     sizeof(*src_param));
680 			qdf_status = QDF_STATUS_SUCCESS;
681 			*num_twt_session += 1;
682 			if (*num_twt_session >= WLAN_MAX_TWT_SESSIONS_PER_PEER)
683 				break;
684 		}
685 	}
686 
687 	return qdf_status;
688 }
689 
690 /**
691  * wlan_cp_stats_twt_get_single_peer_session_params()- Extracts twt session
692  * parameters corresponding to a peer given by dialog_id
693  * @psoc_obj: psoc object
694  * @mac_addr: mac addr of peer
695  * @dialog_id: dialog id of peer for which twt session params to be retrieved
696  * @params: pointer to store peer twt session parameters
697  *
698  * Return: total number of valid twt session
699  */
700 static int
701 wlan_cp_stats_twt_get_single_peer_session_params(
702 					struct wlan_objmgr_psoc *psoc_obj,
703 					uint8_t *mac_addr, uint32_t dialog_id,
704 					struct twt_session_stats_info *params)
705 {
706 	struct wlan_objmgr_peer *peer;
707 	struct peer_cp_stats *peer_cp_stats_priv;
708 	QDF_STATUS qdf_status = QDF_STATUS_E_INVAL;
709 	int num_twt_session = 0;
710 
711 	if (!psoc_obj || !params)
712 		return num_twt_session;
713 
714 	peer = wlan_objmgr_get_peer_by_mac(psoc_obj, mac_addr,
715 					   WLAN_CP_STATS_ID);
716 	if (!peer)
717 		return num_twt_session;
718 	peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
719 
720 	if (!peer_cp_stats_priv) {
721 		wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
722 		return num_twt_session;
723 	}
724 
725 	wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
726 
727 	qdf_status = wlan_cp_stats_twt_get_peer_session_param_by_dlg_id(
728 							peer_cp_stats_priv,
729 							dialog_id,
730 							params,
731 							&num_twt_session);
732 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
733 		cp_stats_debug("No TWT session for " QDF_MAC_ADDR_FMT " dialog_id %d",
734 			QDF_MAC_ADDR_REF(mac_addr), dialog_id);
735 	}
736 
737 	wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
738 	wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
739 
740 	return num_twt_session;
741 }
742 
743 int
744 wlan_cp_stats_twt_get_peer_session_params(struct wlan_objmgr_psoc *psoc,
745 					  struct twt_session_stats_info *params)
746 {
747 	uint8_t *mac_addr;
748 	uint32_t dialog_id;
749 	uint8_t vdev_id;
750 	int num_twt_session = 0;
751 
752 	if (!psoc || !params)
753 		return num_twt_session;
754 
755 	mac_addr = params[0].peer_mac.bytes;
756 	dialog_id = params[0].dialog_id;
757 	vdev_id = params[0].vdev_id;
758 
759 	/*
760 	 * Currently for STA case, twt_get_params nl is sending only dialog_id
761 	 * and mac_addr is being filled by driver in STA peer case.
762 	 * For SAP case, twt_get_params nl is sending dialog_id and
763 	 * peer mac_addr. When twt_get_params add mac_addr and dialog_id of
764 	 * STA/SAP, we need handle unicast/multicast macaddr in
765 	 * wlan_cp_stats_twt_get_peer_session_params.
766 	 */
767 	if (!QDF_IS_ADDR_BROADCAST(mac_addr))
768 		num_twt_session =
769 			wlan_cp_stats_twt_get_single_peer_session_params(
770 								psoc, mac_addr,
771 								dialog_id,
772 								params);
773 	else
774 		num_twt_session = wlan_cp_stats_twt_get_all_peer_session_params(
775 								psoc, vdev_id,
776 								params);
777 	return num_twt_session;
778 }
779 #endif /* WLAN_SUPPORT_TWT */
780 
781