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