1 /* 2 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 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 * repective 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 dettached 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 dettached"); 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 dettach"); 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 dettached"); 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 #if defined(WLAN_SUPPORT_TWT) && defined (WLAN_TWT_CONV_SUPPORTED) 470 /** 471 * wlan_cp_stats_twt_get_peer_session_param() - Obtains twt session parameters 472 * of a peer if twt session is valid 473 * @mc_cp_stats: pointer to peer specific stats 474 * @param: Pointer to copy twt session parameters 475 * @num_twt_sessions Pointer holding total number of valid twt sessions 476 * 477 * Return: QDF_STATUS success if valid twt session parameters are obtained 478 * else other qdf error values 479 */ 480 static QDF_STATUS 481 wlan_cp_stats_twt_get_peer_session_param(struct peer_cp_stats *peer_cp_stat_prv, 482 struct twt_session_stats_info *params, 483 int *num_twt_session) 484 { 485 struct twt_session_stats_info *twt_params; 486 QDF_STATUS qdf_status = QDF_STATUS_E_INVAL; 487 uint32_t event_type; 488 int i; 489 490 if (!peer_cp_stat_prv || !params) 491 return qdf_status; 492 493 for (i = 0; i < WLAN_MAX_TWT_SESSIONS_PER_PEER; i++) { 494 twt_params = &peer_cp_stat_prv->twt_param[i]; 495 event_type = peer_cp_stat_prv->twt_param[i].event_type; 496 497 /* Check twt session is established */ 498 499 if (event_type == HOST_TWT_SESSION_SETUP || 500 event_type == HOST_TWT_SESSION_UPDATE) { 501 qdf_mem_copy(¶ms[*num_twt_session], twt_params, 502 sizeof(*twt_params)); 503 qdf_status = QDF_STATUS_SUCCESS; 504 *num_twt_session += 1; 505 } 506 } 507 508 return qdf_status; 509 } 510 511 /** 512 * wlan_cp_stats_twt_get_all_peer_session_params()- Retrieves twt session 513 * parameters of all peers with valid twt session 514 * @psoc_obj: psoc object 515 * @vdvev_id: vdev_id 516 * @params: array of pointer to store peer twt session parameters 517 * 518 * Return: total number of valid twt sessions 519 */ 520 static int 521 wlan_cp_stats_twt_get_all_peer_session_params( 522 struct wlan_objmgr_psoc *psoc_obj, 523 uint8_t vdev_id, 524 struct twt_session_stats_info *params) 525 { 526 qdf_list_t *peer_list; 527 struct wlan_objmgr_peer *peer, *peer_next; 528 struct wlan_objmgr_vdev *vdev; 529 struct peer_cp_stats *cp_stats_peer_obj, *peer_cp_stat_prv; 530 int num_twt_session = 0; 531 enum QDF_OPMODE opmode; 532 uint16_t sap_num_peer; 533 534 if (!psoc_obj) { 535 cp_stats_err("psoc is NULL"); 536 return num_twt_session; 537 } 538 539 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc_obj, vdev_id, 540 WLAN_CP_STATS_ID); 541 if (!vdev) { 542 cp_stats_err("vdev is NULL, vdev_id: %d", vdev_id); 543 return num_twt_session; 544 } 545 546 sap_num_peer = wlan_vdev_get_peer_count(vdev); 547 opmode = wlan_vdev_mlme_get_opmode(vdev); 548 549 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 550 if (!peer_list) { 551 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); 552 cp_stats_err("Peer list for vdev obj is NULL"); 553 return num_twt_session; 554 } 555 556 peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list, 557 WLAN_CP_STATS_ID); 558 while (peer) { 559 cp_stats_peer_obj = wlan_objmgr_peer_get_comp_private_obj( 560 peer, WLAN_UMAC_COMP_CP_STATS); 561 562 peer_cp_stat_prv = wlan_cp_stats_get_peer_stats_obj(peer); 563 if (peer_cp_stat_prv) { 564 wlan_cp_stats_peer_obj_lock(peer_cp_stat_prv); 565 wlan_cp_stats_twt_get_peer_session_param( 566 peer_cp_stat_prv, 567 params, 568 &num_twt_session); 569 wlan_cp_stats_peer_obj_unlock(peer_cp_stat_prv); 570 } 571 572 if (opmode == QDF_STA_MODE && 573 num_twt_session >= WLAN_MAX_TWT_SESSIONS_PER_PEER) { 574 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 575 goto done; 576 } 577 578 if (opmode == QDF_SAP_MODE && 579 num_twt_session >= (sap_num_peer * WLAN_MAX_TWT_SESSIONS_PER_PEER)) { 580 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 581 goto done; 582 } 583 584 peer_next = wlan_peer_get_next_active_peer_of_vdev( 585 vdev, peer_list, peer, 586 WLAN_CP_STATS_ID); 587 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 588 peer = peer_next; 589 } 590 done: 591 if (!num_twt_session) 592 cp_stats_err("Unable to find a peer with twt session established"); 593 594 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); 595 return num_twt_session; 596 } 597 598 /** 599 * wlan_cp_stats_twt_get_peer_session_param_by_dlg_id() - Finds a Peer twt 600 * session with dialog id matching with input dialog id. If a match is found 601 * copies the twt session parameters 602 * @peer_cp_stats_priv: pointer to peer specific stats 603 * @input_dialog_id: input dialog id 604 * @dest_param: Pointer to copy twt session parameters when a peer with 605 * given dialog id is found 606 * @num_twt_session: Pointer holding total number of valid twt session 607 * 608 * Return: Success if stats are copied for a peer with given dialog, 609 * else failure 610 */ 611 static QDF_STATUS 612 wlan_cp_stats_twt_get_peer_session_param_by_dlg_id( 613 struct peer_cp_stats *peer_cp_stats_priv, 614 uint32_t input_dialog_id, 615 struct twt_session_stats_info *dest_param, 616 int *num_twt_session) 617 { 618 struct twt_session_stats_info *src_param; 619 uint32_t event_type; 620 int i = 0; 621 QDF_STATUS qdf_status = QDF_STATUS_E_INVAL; 622 623 if (!peer_cp_stats_priv || !dest_param) 624 return qdf_status; 625 626 for (i = 0; i < WLAN_MAX_TWT_SESSIONS_PER_PEER; i++) { 627 event_type = peer_cp_stats_priv->twt_param[i].event_type; 628 src_param = &peer_cp_stats_priv->twt_param[i]; 629 if (!event_type || 630 (src_param->dialog_id != input_dialog_id && 631 input_dialog_id != TWT_ALL_SESSIONS_DIALOG_ID)) 632 continue; 633 634 if (event_type == HOST_TWT_SESSION_SETUP || 635 event_type == HOST_TWT_SESSION_UPDATE) { 636 qdf_mem_copy(&dest_param[*num_twt_session], src_param, 637 sizeof(*src_param)); 638 qdf_status = QDF_STATUS_SUCCESS; 639 *num_twt_session += 1; 640 if (*num_twt_session >= WLAN_MAX_TWT_SESSIONS_PER_PEER) 641 break; 642 } 643 } 644 645 return qdf_status; 646 } 647 648 /** 649 * wlan_cp_stats_twt_get_single_peer_session_params()- Extracts twt session 650 * parameters corresponding to a peer given by dialog_id 651 * @psoc_obj: psoc object 652 * @mac_addr: mac addr of peer 653 * @dialog_id: dialog id of peer for which twt session params to be retrieved 654 * @params: pointer to store peer twt session parameters 655 * 656 * Return: total number of valid twt session 657 */ 658 static int 659 wlan_cp_stats_twt_get_single_peer_session_params( 660 struct wlan_objmgr_psoc *psoc_obj, 661 uint8_t *mac_addr, uint32_t dialog_id, 662 struct twt_session_stats_info *params) 663 { 664 struct wlan_objmgr_peer *peer; 665 struct peer_cp_stats *peer_cp_stats_priv; 666 QDF_STATUS qdf_status = QDF_STATUS_E_INVAL; 667 int num_twt_session = 0; 668 669 if (!psoc_obj || !params) 670 return num_twt_session; 671 672 peer = wlan_objmgr_get_peer_by_mac(psoc_obj, mac_addr, 673 WLAN_CP_STATS_ID); 674 if (!peer) 675 return num_twt_session; 676 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer); 677 678 if (!peer_cp_stats_priv) { 679 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 680 return num_twt_session; 681 } 682 683 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv); 684 685 qdf_status = wlan_cp_stats_twt_get_peer_session_param_by_dlg_id( 686 peer_cp_stats_priv, 687 dialog_id, 688 params, 689 &num_twt_session); 690 if (QDF_IS_STATUS_ERROR(qdf_status)) { 691 cp_stats_debug("No TWT session for " QDF_MAC_ADDR_FMT " dialog_id %d", 692 QDF_MAC_ADDR_REF(mac_addr), dialog_id); 693 } 694 695 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); 696 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); 697 698 return num_twt_session; 699 } 700 701 int 702 wlan_cp_stats_twt_get_peer_session_params(struct wlan_objmgr_psoc *psoc, 703 struct twt_session_stats_info *params) 704 { 705 uint8_t *mac_addr; 706 uint32_t dialog_id; 707 uint8_t vdev_id; 708 int num_twt_session = 0; 709 710 if (!psoc || !params) 711 return num_twt_session; 712 713 mac_addr = params[0].peer_mac.bytes; 714 dialog_id = params[0].dialog_id; 715 vdev_id = params[0].vdev_id; 716 717 /* 718 * Currently for STA case, twt_get_params nl is sending only dialog_id 719 * and mac_addr is being filled by driver in STA peer case. 720 * For SAP case, twt_get_params nl is sending dialog_id and 721 * peer mac_addr. When twt_get_params add mac_addr and dialog_id of 722 * STA/SAP, we need handle unicast/multicast macaddr in 723 * wlan_cp_stats_twt_get_peer_session_params. 724 */ 725 if (!QDF_IS_ADDR_BROADCAST(mac_addr)) 726 num_twt_session = 727 wlan_cp_stats_twt_get_single_peer_session_params( 728 psoc, mac_addr, 729 dialog_id, 730 params); 731 else 732 num_twt_session = wlan_cp_stats_twt_get_all_peer_session_params( 733 psoc, vdev_id, 734 params); 735 return num_twt_session; 736 } 737 #endif /* WLAN_SUPPORT_TWT */ 738 739