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_get_context(struct wlan_objmgr_psoc *psoc, 430 get_infra_cp_stats_cb *resp_cb, 431 void **context) 432 { 433 struct psoc_cp_stats *psoc_cp_stats_priv; 434 435 psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc); 436 if (!psoc_cp_stats_priv) { 437 cp_stats_err("psoc cp stats object is null"); 438 return QDF_STATUS_E_NULL_VALUE; 439 } 440 441 wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); 442 *resp_cb = psoc_cp_stats_priv->get_infra_cp_stats; 443 *context = psoc_cp_stats_priv->infra_cp_stats_req_context; 444 wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv); 445 446 return QDF_STATUS_SUCCESS; 447 } 448 449 QDF_STATUS 450 wlan_cp_stats_send_infra_cp_req(struct wlan_objmgr_psoc *psoc, 451 struct infra_cp_stats_cmd_info *req) 452 { 453 struct wlan_lmac_if_cp_stats_tx_ops *tx_ops; 454 455 tx_ops = target_if_cp_stats_get_tx_ops(psoc); 456 if (!tx_ops) { 457 cp_stats_err("could not get tx_ops"); 458 return QDF_STATUS_E_NULL_VALUE; 459 } 460 461 if (!tx_ops->send_req_infra_cp_stats) { 462 cp_stats_err("could not get send_req_infra_twt_stats"); 463 return QDF_STATUS_E_NULL_VALUE; 464 } 465 return tx_ops->send_req_infra_cp_stats(psoc, req); 466 } 467 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */ 468 469 #ifdef WLAN_TELEMETRY_STATS_SUPPORT 470 QDF_STATUS 471 wlan_cp_stats_send_telemetry_cp_req(struct wlan_objmgr_pdev *pdev, 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(wlan_pdev_get_psoc(pdev)); 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_telemetry_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_telemetry_cp_stats(pdev, req); 487 } 488 #endif 489 490 #if defined(WLAN_SUPPORT_TWT) && defined (WLAN_TWT_CONV_SUPPORTED) 491 /** 492 * wlan_cp_stats_twt_get_peer_session_param() - Obtains twt session parameters 493 * of a peer if twt session is valid 494 * @peer_cp_stat_prv: pointer to peer specific stats 495 * @params: Pointer to copy twt session parameters 496 * @num_twt_session: Pointer holding total number of valid twt sessions 497 * 498 * Return: QDF_STATUS success if valid twt session parameters are obtained 499 * else other qdf error values 500 */ 501 static QDF_STATUS 502 wlan_cp_stats_twt_get_peer_session_param(struct peer_cp_stats *peer_cp_stat_prv, 503 struct twt_session_stats_info *params, 504 int *num_twt_session) 505 { 506 struct twt_session_stats_info *twt_params; 507 QDF_STATUS qdf_status = QDF_STATUS_E_INVAL; 508 uint32_t event_type; 509 int i; 510 511 if (!peer_cp_stat_prv || !params) 512 return qdf_status; 513 514 for (i = 0; i < WLAN_MAX_TWT_SESSIONS_PER_PEER; i++) { 515 twt_params = &peer_cp_stat_prv->twt_param[i]; 516 event_type = peer_cp_stat_prv->twt_param[i].event_type; 517 518 /* Check twt session is established */ 519 520 if (event_type == HOST_TWT_SESSION_SETUP || 521 event_type == HOST_TWT_SESSION_UPDATE) { 522 qdf_mem_copy(¶ms[*num_twt_session], twt_params, 523 sizeof(*twt_params)); 524 qdf_status = QDF_STATUS_SUCCESS; 525 *num_twt_session += 1; 526 } 527 } 528 529 return qdf_status; 530 } 531 532 /** 533 * wlan_cp_stats_twt_get_all_peer_session_params()- Retrieves twt session 534 * parameters of all peers with valid twt session 535 * @psoc_obj: psoc object 536 * @vdev_id: vdev_id 537 * @params: array of pointer to store peer twt session parameters 538 * 539 * Return: total number of valid twt sessions 540 */ 541 static int 542 wlan_cp_stats_twt_get_all_peer_session_params( 543 struct wlan_objmgr_psoc *psoc_obj, 544 uint8_t vdev_id, 545 struct twt_session_stats_info *params) 546 { 547 qdf_list_t *peer_list; 548 struct wlan_objmgr_peer *peer, *peer_next; 549 struct wlan_objmgr_vdev *vdev; 550 struct peer_cp_stats *cp_stats_peer_obj, *peer_cp_stat_prv; 551 int num_twt_session = 0; 552 enum QDF_OPMODE opmode; 553 uint16_t sap_num_peer; 554 555 if (!psoc_obj) { 556 cp_stats_err("psoc is NULL"); 557 return num_twt_session; 558 } 559 560 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc_obj, vdev_id, 561 WLAN_CP_STATS_ID); 562 if (!vdev) { 563 cp_stats_err("vdev is NULL, vdev_id: %d", vdev_id); 564 return num_twt_session; 565 } 566 567 sap_num_peer = wlan_vdev_get_peer_count(vdev); 568 opmode = wlan_vdev_mlme_get_opmode(vdev); 569 570 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 571 if (!peer_list) { 572 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); 573 cp_stats_err("Peer list for vdev obj is NULL"); 574 return num_twt_session; 575 } 576 577 peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list, 578 WLAN_CP_STATS_ID); 579 while (peer) { 580 cp_stats_peer_obj = wlan_objmgr_peer_get_comp_private_obj( 581 peer, WLAN_UMAC_COMP_CP_STATS); 582 583 peer_cp_stat_prv = wlan_cp_stats_get_peer_stats_obj(peer); 584 if (peer_cp_stat_prv) { 585 wlan_cp_stats_peer_obj_lock(peer_cp_stat_prv); 586 wlan_cp_stats_twt_get_peer_session_param( 587 peer_cp_stat_prv, 588 params, 589 &num_twt_session); 590 wlan_cp_stats_peer_obj_unlock(peer_cp_stat_prv); 591 } 592 593 if (opmode == QDF_STA_MODE && 594 num_twt_session >= WLAN_MAX_TWT_SESSIONS_PER_PEER) { 595 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 596 goto done; 597 } 598 599 if (opmode == QDF_SAP_MODE && 600 num_twt_session >= (sap_num_peer * WLAN_MAX_TWT_SESSIONS_PER_PEER)) { 601 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 602 goto done; 603 } 604 605 peer_next = wlan_peer_get_next_active_peer_of_vdev( 606 vdev, peer_list, peer, 607 WLAN_CP_STATS_ID); 608 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 609 peer = peer_next; 610 } 611 done: 612 if (!num_twt_session) 613 cp_stats_err("Unable to find a peer with twt session established"); 614 615 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); 616 return num_twt_session; 617 } 618 619 /** 620 * wlan_cp_stats_twt_get_peer_session_param_by_dlg_id() - Finds a Peer twt 621 * session with dialog id matching with input dialog id. If a match is found 622 * copies the twt session parameters 623 * @peer_cp_stats_priv: pointer to peer specific stats 624 * @input_dialog_id: input dialog id 625 * @dest_param: Pointer to copy twt session parameters when a peer with 626 * given dialog id is found 627 * @num_twt_session: Pointer holding total number of valid twt session 628 * 629 * Return: Success if stats are copied for a peer with given dialog, 630 * else failure 631 */ 632 static QDF_STATUS 633 wlan_cp_stats_twt_get_peer_session_param_by_dlg_id( 634 struct peer_cp_stats *peer_cp_stats_priv, 635 uint32_t input_dialog_id, 636 struct twt_session_stats_info *dest_param, 637 int *num_twt_session) 638 { 639 struct twt_session_stats_info *src_param; 640 uint32_t event_type; 641 int i = 0; 642 QDF_STATUS qdf_status = QDF_STATUS_E_INVAL; 643 644 if (!peer_cp_stats_priv || !dest_param) 645 return qdf_status; 646 647 for (i = 0; i < WLAN_MAX_TWT_SESSIONS_PER_PEER; i++) { 648 event_type = peer_cp_stats_priv->twt_param[i].event_type; 649 src_param = &peer_cp_stats_priv->twt_param[i]; 650 if (!event_type || 651 (src_param->dialog_id != input_dialog_id && 652 input_dialog_id != TWT_ALL_SESSIONS_DIALOG_ID)) 653 continue; 654 655 if (event_type == HOST_TWT_SESSION_SETUP || 656 event_type == HOST_TWT_SESSION_UPDATE) { 657 qdf_mem_copy(&dest_param[*num_twt_session], src_param, 658 sizeof(*src_param)); 659 qdf_status = QDF_STATUS_SUCCESS; 660 *num_twt_session += 1; 661 if (*num_twt_session >= WLAN_MAX_TWT_SESSIONS_PER_PEER) 662 break; 663 } 664 } 665 666 return qdf_status; 667 } 668 669 /** 670 * wlan_cp_stats_twt_get_single_peer_session_params()- Extracts twt session 671 * parameters corresponding to a peer given by dialog_id 672 * @psoc_obj: psoc object 673 * @mac_addr: mac addr of peer 674 * @dialog_id: dialog id of peer for which twt session params to be retrieved 675 * @params: pointer to store peer twt session parameters 676 * 677 * Return: total number of valid twt session 678 */ 679 static int 680 wlan_cp_stats_twt_get_single_peer_session_params( 681 struct wlan_objmgr_psoc *psoc_obj, 682 uint8_t *mac_addr, uint32_t dialog_id, 683 struct twt_session_stats_info *params) 684 { 685 struct wlan_objmgr_peer *peer; 686 struct peer_cp_stats *peer_cp_stats_priv; 687 QDF_STATUS qdf_status = QDF_STATUS_E_INVAL; 688 int num_twt_session = 0; 689 690 if (!psoc_obj || !params) 691 return num_twt_session; 692 693 peer = wlan_objmgr_get_peer_by_mac(psoc_obj, mac_addr, 694 WLAN_CP_STATS_ID); 695 if (!peer) 696 return num_twt_session; 697 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer); 698 699 if (!peer_cp_stats_priv) { 700 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 701 return num_twt_session; 702 } 703 704 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv); 705 706 qdf_status = wlan_cp_stats_twt_get_peer_session_param_by_dlg_id( 707 peer_cp_stats_priv, 708 dialog_id, 709 params, 710 &num_twt_session); 711 if (QDF_IS_STATUS_ERROR(qdf_status)) { 712 cp_stats_debug("No TWT session for " QDF_MAC_ADDR_FMT " dialog_id %d", 713 QDF_MAC_ADDR_REF(mac_addr), dialog_id); 714 } 715 716 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); 717 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 718 719 return num_twt_session; 720 } 721 722 int 723 wlan_cp_stats_twt_get_peer_session_params(struct wlan_objmgr_psoc *psoc, 724 struct twt_session_stats_info *params) 725 { 726 uint8_t *mac_addr; 727 uint32_t dialog_id; 728 uint8_t vdev_id; 729 int num_twt_session = 0; 730 731 if (!psoc || !params) 732 return num_twt_session; 733 734 mac_addr = params[0].peer_mac.bytes; 735 dialog_id = params[0].dialog_id; 736 vdev_id = params[0].vdev_id; 737 738 /* 739 * Currently for STA case, twt_get_params nl is sending only dialog_id 740 * and mac_addr is being filled by driver in STA peer case. 741 * For SAP case, twt_get_params nl is sending dialog_id and 742 * peer mac_addr. When twt_get_params add mac_addr and dialog_id of 743 * STA/SAP, we need handle unicast/multicast macaddr in 744 * wlan_cp_stats_twt_get_peer_session_params. 745 */ 746 if (!QDF_IS_ADDR_BROADCAST(mac_addr)) 747 num_twt_session = 748 wlan_cp_stats_twt_get_single_peer_session_params( 749 psoc, mac_addr, 750 dialog_id, 751 params); 752 else 753 num_twt_session = wlan_cp_stats_twt_get_all_peer_session_params( 754 psoc, vdev_id, 755 params); 756 return num_twt_session; 757 } 758 #endif /* WLAN_SUPPORT_TWT */ 759 760