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