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