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(¶ms[*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