1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 17 */ 18 /** 19 * DOC: Public APIs to perform operations on Global objects 20 */ 21 #include <wlan_objmgr_cmn.h> 22 #include <wlan_objmgr_global_obj.h> 23 #include <wlan_objmgr_psoc_obj.h> 24 #include <wlan_objmgr_pdev_obj.h> 25 #include <wlan_objmgr_vdev_obj.h> 26 #include <wlan_objmgr_peer_obj.h> 27 #include <wlan_objmgr_debug.h> 28 #include <qdf_mem.h> 29 #include <qdf_module.h> 30 #include "wlan_objmgr_global_obj_i.h" 31 #include "wlan_objmgr_psoc_obj_i.h" 32 #include "wlan_objmgr_pdev_obj_i.h" 33 #include "wlan_objmgr_vdev_obj_i.h" 34 #include <wlan_utility.h> 35 #include <wlan_osif_priv.h> 36 37 38 /** 39 ** APIs to Create/Delete Global object APIs 40 */ 41 42 static QDF_STATUS wlan_objmgr_vdev_object_status( 43 struct wlan_objmgr_vdev *vdev) 44 { 45 uint8_t id; 46 QDF_STATUS status = QDF_STATUS_SUCCESS; 47 48 wlan_vdev_obj_lock(vdev); 49 50 /* Iterate through all components to derive the object status */ 51 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 52 /* If component disabled, Ignore */ 53 if (vdev->obj_status[id] == QDF_STATUS_COMP_DISABLED) { 54 continue; 55 /* 56 * If component operates in Async, status is Partially created, 57 * break 58 */ 59 } else if (vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC) { 60 if (!vdev->vdev_comp_priv_obj[id]) { 61 status = QDF_STATUS_COMP_ASYNC; 62 break; 63 } 64 /* 65 * If component failed to allocate its object, treat it as 66 * failure, complete object need to be cleaned up 67 */ 68 } else if ((vdev->obj_status[id] == QDF_STATUS_E_NOMEM) || 69 (vdev->obj_status[id] == QDF_STATUS_E_FAILURE)) { 70 status = QDF_STATUS_E_FAILURE; 71 break; 72 } 73 } 74 wlan_vdev_obj_unlock(vdev); 75 76 return status; 77 } 78 79 static QDF_STATUS wlan_objmgr_vdev_obj_free(struct wlan_objmgr_vdev *vdev) 80 { 81 struct wlan_objmgr_pdev *pdev; 82 struct wlan_objmgr_psoc *psoc; 83 84 if (!vdev) { 85 obj_mgr_err("vdev is NULL"); 86 return QDF_STATUS_E_FAILURE; 87 } 88 /* if PDEV is NULL, return */ 89 pdev = wlan_vdev_get_pdev(vdev); 90 if (!pdev) { 91 obj_mgr_err("pdev is NULL for vdev-id: %d", 92 vdev->vdev_objmgr.vdev_id); 93 return QDF_STATUS_E_FAILURE; 94 } 95 psoc = wlan_pdev_get_psoc(pdev); 96 if (!psoc) { 97 obj_mgr_err("psoc is NULL in pdev"); 98 return QDF_STATUS_E_FAILURE; 99 } 100 101 /* Detach VDEV from PDEV VDEV's list */ 102 if (wlan_objmgr_pdev_vdev_detach(pdev, vdev) == 103 QDF_STATUS_E_FAILURE) 104 return QDF_STATUS_E_FAILURE; 105 106 /* Detach VDEV from PSOC VDEV's list */ 107 if (wlan_objmgr_psoc_vdev_detach(psoc, vdev) == 108 QDF_STATUS_E_FAILURE) 109 return QDF_STATUS_E_FAILURE; 110 111 wlan_objmgr_vdev_trace_del_ref_list(vdev); 112 wlan_objmgr_vdev_trace_deinit_lock(vdev); 113 qdf_spinlock_destroy(&vdev->vdev_lock); 114 115 wlan_destroy_vdev_mlo_lock(vdev); 116 117 qdf_mem_free(vdev->vdev_mlme.bss_chan); 118 qdf_mem_free(vdev->vdev_mlme.des_chan); 119 qdf_mem_free(vdev); 120 121 return QDF_STATUS_SUCCESS; 122 123 } 124 125 static struct vdev_osif_priv *wlan_objmgr_vdev_get_osif_priv( 126 struct wlan_objmgr_vdev *vdev) 127 { 128 struct vdev_osif_priv *osif_priv; 129 130 /* private data area immediately follows the struct wlan_objmgr_vdev */ 131 osif_priv = (struct vdev_osif_priv *)(vdev + 1); 132 133 return osif_priv; 134 } 135 136 struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( 137 struct wlan_objmgr_pdev *pdev, 138 struct wlan_vdev_create_params *params) 139 { 140 struct wlan_objmgr_vdev *vdev; 141 struct wlan_objmgr_psoc *psoc; 142 uint8_t id; 143 wlan_objmgr_vdev_create_handler handler; 144 wlan_objmgr_vdev_status_handler stat_handler; 145 void *arg; 146 QDF_STATUS obj_status; 147 148 if (!pdev) { 149 obj_mgr_err("pdev is NULL"); 150 return NULL; 151 } 152 psoc = wlan_pdev_get_psoc(pdev); 153 /* PSOC is NULL */ 154 if (!psoc) { 155 obj_mgr_err("psoc is NULL for pdev-id:%d", 156 pdev->pdev_objmgr.wlan_pdev_id); 157 return NULL; 158 } 159 /* Allocate vdev object memory */ 160 vdev = qdf_mem_malloc(sizeof(*vdev) + params->size_vdev_priv); 161 if (!vdev) 162 return NULL; 163 vdev->obj_state = WLAN_OBJ_STATE_ALLOCATED; 164 165 vdev->vdev_mlme.bss_chan = qdf_mem_malloc(sizeof(struct wlan_channel)); 166 if (!vdev->vdev_mlme.bss_chan) { 167 qdf_mem_free(vdev); 168 return NULL; 169 } 170 171 vdev->vdev_mlme.des_chan = qdf_mem_malloc(sizeof(struct wlan_channel)); 172 if (!vdev->vdev_mlme.des_chan) { 173 qdf_mem_free(vdev->vdev_mlme.bss_chan); 174 qdf_mem_free(vdev); 175 return NULL; 176 } 177 178 wlan_create_vdev_mlo_lock(vdev); 179 180 wlan_objmgr_vdev_trace_init_lock(vdev); 181 /* Initialize spinlock */ 182 qdf_spinlock_create(&vdev->vdev_lock); 183 /* Attach VDEV to PSOC VDEV's list */ 184 if (wlan_objmgr_psoc_vdev_attach(psoc, vdev) != 185 QDF_STATUS_SUCCESS) { 186 obj_mgr_err("psoc vdev attach failed for vdev-id:%d", 187 vdev->vdev_objmgr.vdev_id); 188 qdf_mem_free(vdev->vdev_mlme.bss_chan); 189 qdf_mem_free(vdev->vdev_mlme.des_chan); 190 wlan_destroy_vdev_mlo_lock(vdev); 191 qdf_spinlock_destroy(&vdev->vdev_lock); 192 wlan_objmgr_vdev_trace_deinit_lock(vdev); 193 qdf_mem_free(vdev); 194 return NULL; 195 } 196 /* Store pdev in vdev */ 197 wlan_vdev_set_pdev(vdev, pdev); 198 /* Attach vdev to PDEV */ 199 if (wlan_objmgr_pdev_vdev_attach(pdev, vdev) != 200 QDF_STATUS_SUCCESS) { 201 obj_mgr_err("pdev vdev attach failed for vdev-id:%d", 202 vdev->vdev_objmgr.vdev_id); 203 wlan_objmgr_psoc_vdev_detach(psoc, vdev); 204 qdf_mem_free(vdev->vdev_mlme.bss_chan); 205 qdf_mem_free(vdev->vdev_mlme.des_chan); 206 wlan_destroy_vdev_mlo_lock(vdev); 207 qdf_spinlock_destroy(&vdev->vdev_lock); 208 wlan_objmgr_vdev_trace_deinit_lock(vdev); 209 qdf_mem_free(vdev); 210 return NULL; 211 } 212 /* set opmode */ 213 wlan_vdev_mlme_set_opmode(vdev, params->opmode); 214 /* set MAC address */ 215 wlan_vdev_mlme_set_macaddr(vdev, params->macaddr); 216 /* set MAT address */ 217 wlan_vdev_mlme_set_mataddr(vdev, params->mataddr); 218 /* set MLD address */ 219 wlan_vdev_mlme_set_mldaddr(vdev, params->mldaddr); 220 /* set link address */ 221 wlan_vdev_mlme_set_linkaddr(vdev, params->macaddr); 222 /* Set create flags */ 223 vdev->vdev_objmgr.c_flags = params->flags; 224 /* store os-specific pointer */ 225 vdev->vdev_nif.osdev = wlan_objmgr_vdev_get_osif_priv(vdev); 226 227 /* peer count to 0 */ 228 vdev->vdev_objmgr.wlan_peer_count = 0; 229 qdf_atomic_init(&vdev->vdev_objmgr.ref_cnt); 230 vdev->vdev_objmgr.print_cnt = 0; 231 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); 232 /* Initialize max peer count based on opmode type */ 233 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) 234 vdev->vdev_objmgr.max_peer_count = WLAN_UMAC_MAX_STA_PEERS; 235 else 236 vdev->vdev_objmgr.max_peer_count = 237 wlan_pdev_get_max_peer_count(pdev); 238 239 if (params->legacy_osif) 240 vdev->vdev_nif.osdev->legacy_osif_priv = params->legacy_osif; 241 242 /* Initialize peer list */ 243 qdf_list_create(&vdev->vdev_objmgr.wlan_peer_list, 244 vdev->vdev_objmgr.max_peer_count + 245 WLAN_MAX_PDEV_TEMP_PEERS); 246 /* TODO init other parameters */ 247 248 /* Invoke registered create handlers */ 249 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 250 handler = g_umac_glb_obj->vdev_create_handler[id]; 251 arg = g_umac_glb_obj->vdev_create_handler_arg[id]; 252 if (handler) 253 vdev->obj_status[id] = handler(vdev, arg); 254 else 255 vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 256 } 257 258 /* Derive object status */ 259 obj_status = wlan_objmgr_vdev_object_status(vdev); 260 261 if (obj_status == QDF_STATUS_SUCCESS) { 262 /* Object status is SUCCESS, Object is created */ 263 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 264 /* Invoke component registered status handlers */ 265 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 266 stat_handler = g_umac_glb_obj->vdev_status_handler[id]; 267 arg = g_umac_glb_obj->vdev_status_handler_arg[id]; 268 if (stat_handler) { 269 stat_handler(vdev, arg, 270 QDF_STATUS_SUCCESS); 271 } 272 } 273 /* 274 * Few components operates in Asynchrous communction, Object state 275 * partially created 276 */ 277 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 278 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 279 /* Component object failed to be created, clean up the object */ 280 } else if (obj_status == QDF_STATUS_E_FAILURE) { 281 /* Clean up the psoc */ 282 obj_mgr_err("VDEV comp objects creation failed for vdev-id:%d", 283 vdev->vdev_objmgr.vdev_id); 284 wlan_objmgr_vdev_obj_delete(vdev); 285 return NULL; 286 } 287 288 wlan_minidump_log(vdev, sizeof(*vdev), psoc, 289 WLAN_MD_OBJMGR_VDEV, "wlan_objmgr_vdev"); 290 291 obj_mgr_debug("Created vdev %d", vdev->vdev_objmgr.vdev_id); 292 293 return vdev; 294 } 295 qdf_export_symbol(wlan_objmgr_vdev_obj_create); 296 297 static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev) 298 { 299 uint8_t id; 300 wlan_objmgr_vdev_destroy_handler handler; 301 QDF_STATUS obj_status; 302 void *arg; 303 uint8_t vdev_id; 304 305 if (!vdev) { 306 obj_mgr_err("vdev is NULL"); 307 return QDF_STATUS_E_FAILURE; 308 } 309 wlan_objmgr_notify_destroy(vdev, WLAN_VDEV_OP); 310 311 vdev_id = wlan_vdev_get_id(vdev); 312 313 obj_mgr_debug("Physically deleting vdev %d", vdev_id); 314 315 if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 316 obj_mgr_alert("VDEV object delete is not invoked vdevid:%d objstate:%d", 317 wlan_vdev_get_id(vdev), vdev->obj_state); 318 WLAN_OBJMGR_BUG(0); 319 return QDF_STATUS_E_FAILURE; 320 } 321 322 wlan_minidump_remove(vdev, sizeof(*vdev), wlan_vdev_get_psoc(vdev), 323 WLAN_MD_OBJMGR_VDEV, "wlan_objmgr_vdev"); 324 325 /* Invoke registered destroy handlers */ 326 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 327 handler = g_umac_glb_obj->vdev_destroy_handler[id]; 328 arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; 329 if (handler && 330 (vdev->obj_status[id] == QDF_STATUS_SUCCESS || 331 vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC)) 332 vdev->obj_status[id] = handler(vdev, arg); 333 else 334 vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 335 } 336 /* Derive object status */ 337 obj_status = wlan_objmgr_vdev_object_status(vdev); 338 339 if (obj_status == QDF_STATUS_E_FAILURE) { 340 obj_mgr_err("VDEV object deletion failed: vdev-id: %d", 341 vdev_id); 342 /* Ideally should not happen */ 343 /* This leads to memleak ??? how to handle */ 344 QDF_BUG(0); 345 return QDF_STATUS_E_FAILURE; 346 } 347 348 /* Deletion is in progress */ 349 if (obj_status == QDF_STATUS_COMP_ASYNC) { 350 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 351 return QDF_STATUS_COMP_ASYNC; 352 } 353 354 /* Free VDEV object */ 355 return wlan_objmgr_vdev_obj_free(vdev); 356 } 357 358 QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) 359 { 360 uint8_t print_idx; 361 362 if (!vdev) { 363 obj_mgr_err("vdev is NULL"); 364 return QDF_STATUS_E_FAILURE; 365 } 366 367 obj_mgr_debug("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id); 368 369 print_idx = qdf_get_pidx(); 370 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, 371 QDF_TRACE_LEVEL_DEBUG); 372 /* 373 * Update VDEV object state to LOGICALLY DELETED 374 * It prevents further access of this object 375 */ 376 wlan_vdev_obj_lock(vdev); 377 vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 378 wlan_vdev_obj_unlock(vdev); 379 wlan_objmgr_notify_log_delete(vdev, WLAN_VDEV_OP); 380 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 381 382 return QDF_STATUS_SUCCESS; 383 } 384 qdf_export_symbol(wlan_objmgr_vdev_obj_delete); 385 386 /** 387 ** APIs to attach/detach component objects 388 */ 389 QDF_STATUS wlan_objmgr_vdev_component_obj_attach( 390 struct wlan_objmgr_vdev *vdev, 391 enum wlan_umac_comp_id id, 392 void *comp_priv_obj, 393 QDF_STATUS status) 394 { 395 wlan_objmgr_vdev_status_handler stat_handler; 396 void *arg; 397 uint8_t i; 398 QDF_STATUS obj_status; 399 400 /* component id is invalid */ 401 if (id >= WLAN_UMAC_MAX_COMPONENTS) 402 return QDF_STATUS_MAXCOMP_FAIL; 403 404 wlan_vdev_obj_lock(vdev); 405 /* If there is a valid entry, return failure */ 406 if (vdev->vdev_comp_priv_obj[id]) { 407 wlan_vdev_obj_unlock(vdev); 408 return QDF_STATUS_E_FAILURE; 409 } 410 /* Save component's pointer and status */ 411 vdev->vdev_comp_priv_obj[id] = comp_priv_obj; 412 vdev->obj_status[id] = status; 413 wlan_vdev_obj_unlock(vdev); 414 if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 415 return QDF_STATUS_SUCCESS; 416 /* 417 * If VDEV object status is partially created means, this API is 418 * invoked with differnt context, this block should be executed for 419 * async components only 420 */ 421 /* Derive status */ 422 obj_status = wlan_objmgr_vdev_object_status(vdev); 423 /* STATUS_SUCCESS means, object is CREATED */ 424 if (obj_status == QDF_STATUS_SUCCESS) 425 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 426 /* 427 * update state as CREATION failed, caller has to delete the 428 * VDEV object 429 */ 430 else if (obj_status == QDF_STATUS_E_FAILURE) 431 vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 432 /* Notify components about the CREATION success/failure */ 433 if ((obj_status == QDF_STATUS_SUCCESS) || 434 (obj_status == QDF_STATUS_E_FAILURE)) { 435 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 436 stat_handler = g_umac_glb_obj->vdev_status_handler[i]; 437 arg = g_umac_glb_obj->vdev_status_handler_arg[i]; 438 if (stat_handler) 439 stat_handler(vdev, arg, obj_status); 440 } 441 } 442 return QDF_STATUS_SUCCESS; 443 } 444 qdf_export_symbol(wlan_objmgr_vdev_component_obj_attach); 445 446 QDF_STATUS wlan_objmgr_vdev_component_obj_detach( 447 struct wlan_objmgr_vdev *vdev, 448 enum wlan_umac_comp_id id, 449 void *comp_priv_obj) 450 { 451 QDF_STATUS obj_status; 452 453 /* component id is invalid */ 454 if (id >= WLAN_UMAC_MAX_COMPONENTS) 455 return QDF_STATUS_MAXCOMP_FAIL; 456 457 wlan_vdev_obj_lock(vdev); 458 /* If there is a valid entry, return failure */ 459 if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) { 460 vdev->obj_status[id] = QDF_STATUS_E_FAILURE; 461 wlan_vdev_obj_unlock(vdev); 462 return QDF_STATUS_E_FAILURE; 463 } 464 /* Reset pointers to NULL, update the status*/ 465 vdev->vdev_comp_priv_obj[id] = NULL; 466 vdev->obj_status[id] = QDF_STATUS_SUCCESS; 467 wlan_vdev_obj_unlock(vdev); 468 469 /** 470 *If VDEV object status is partially destroyed means, this API is 471 * invoked with differnt context, this block should be executed for 472 * async components only 473 */ 474 if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 475 (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 476 /* Derive object status */ 477 obj_status = wlan_objmgr_vdev_object_status(vdev); 478 if (obj_status == QDF_STATUS_SUCCESS) { 479 /* 480 * Update the status as Deleted, if full object 481 * deletion is in progress 482 */ 483 if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 484 vdev->obj_state = WLAN_OBJ_STATE_DELETED; 485 /* 486 * Move to creation state, since this component 487 * deletion alone requested 488 */ 489 else if (vdev->obj_state == 490 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 491 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 492 /* Object status is failure */ 493 } else if (obj_status == QDF_STATUS_E_FAILURE) { 494 /* 495 * Update the status as Deletion failed, if full object 496 * deletion is in progress 497 */ 498 if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 499 vdev->obj_state = 500 WLAN_OBJ_STATE_DELETION_FAILED; 501 /* Move to creation state, since this component 502 deletion alone requested (do not block other 503 components) */ 504 else if (vdev->obj_state == 505 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 506 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 507 } 508 /* Delete vdev object */ 509 if ((obj_status == QDF_STATUS_SUCCESS) && 510 (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) { 511 /* Free VDEV object */ 512 return wlan_objmgr_vdev_obj_free(vdev); 513 } 514 } 515 return QDF_STATUS_SUCCESS; 516 } 517 qdf_export_symbol(wlan_objmgr_vdev_component_obj_detach); 518 519 /** 520 ** APIs to operations on vdev objects 521 */ 522 QDF_STATUS wlan_objmgr_iterate_peerobj_list( 523 struct wlan_objmgr_vdev *vdev, 524 wlan_objmgr_vdev_op_handler handler, 525 void *arg, wlan_objmgr_ref_dbgid dbg_id) 526 { 527 qdf_list_t *peer_list = NULL; 528 struct wlan_objmgr_peer *peer = NULL; 529 struct wlan_objmgr_peer *peer_next = NULL; 530 uint8_t vdev_id; 531 532 if (!vdev) { 533 obj_mgr_err("VDEV is NULL"); 534 return QDF_STATUS_E_FAILURE; 535 } 536 wlan_vdev_obj_lock(vdev); 537 vdev_id = wlan_vdev_get_id(vdev); 538 539 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 540 wlan_vdev_obj_unlock(vdev); 541 obj_mgr_err("VDEV is not in create state:%d: vdev-id:%d", 542 vdev->obj_state, vdev_id); 543 return QDF_STATUS_E_FAILURE; 544 } 545 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 546 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 547 if (peer_list) { 548 /* Iterate through VDEV's peer list */ 549 peer = wlan_vdev_peer_list_peek_head(peer_list); 550 while (peer) { 551 peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, 552 peer); 553 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 554 QDF_STATUS_SUCCESS) { 555 /* Invoke handler for operation */ 556 handler(vdev, (void *)peer, arg); 557 wlan_objmgr_peer_release_ref(peer, dbg_id); 558 } 559 peer = peer_next; 560 } 561 } 562 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 563 wlan_vdev_obj_unlock(vdev); 564 return QDF_STATUS_SUCCESS; 565 } 566 567 qdf_export_symbol(wlan_objmgr_iterate_peerobj_list); 568 569 /** 570 ** APIs to get a peer with given mac in a vdev 571 */ 572 struct wlan_objmgr_peer * 573 wlan_objmgr_vdev_find_peer_by_mac(struct wlan_objmgr_vdev *vdev, 574 uint8_t *peer_mac, 575 wlan_objmgr_ref_dbgid dbg_id) 576 { 577 qdf_list_t *peer_list; 578 struct wlan_objmgr_peer *peer = NULL; 579 struct wlan_objmgr_peer *peer_next = NULL; 580 uint8_t vdev_id; 581 582 if (!vdev) { 583 obj_mgr_err("VDEV is NULL"); 584 return NULL; 585 } 586 wlan_vdev_obj_lock(vdev); 587 vdev_id = wlan_vdev_get_id(vdev); 588 589 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 590 wlan_vdev_obj_unlock(vdev); 591 obj_mgr_err("VDEV is not in create state:%d: vdev-id:%d", 592 vdev->obj_state, vdev_id); 593 return NULL; 594 } 595 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 596 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 597 /* Iterate through VDEV's peer list */ 598 peer = wlan_vdev_peer_list_peek_head(peer_list); 599 while (peer) { 600 peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, 601 peer); 602 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 603 QDF_STATUS_SUCCESS) { 604 if (!WLAN_ADDR_EQ(peer_mac, 605 wlan_peer_get_macaddr(peer))) { 606 wlan_objmgr_vdev_release_ref(vdev, 607 dbg_id); 608 wlan_vdev_obj_unlock(vdev); 609 return peer; 610 } 611 wlan_objmgr_peer_release_ref(peer, dbg_id); 612 } 613 peer = peer_next; 614 } 615 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 616 wlan_vdev_obj_unlock(vdev); 617 return NULL; 618 } 619 620 qdf_export_symbol(wlan_objmgr_vdev_find_peer_by_mac); 621 622 /** 623 * wlan_obj_vdev_populate_logically_del_peerlist() - get peer 624 * from vdev peer list 625 * @obj_list: peer object list 626 * @vdev_obj: vdev object mgr substructure 627 * @dbg_id: id of the caller 628 * 629 * API to finds peer object pointer by vdev from peer hash list for a node 630 * which is in logically deleted state 631 * 632 * Caller to free the list allocated in this function 633 * 634 * Return: list of peer pointers 635 * NULL on FAILURE 636 */ 637 static qdf_list_t *wlan_obj_vdev_populate_logically_del_peerlist( 638 qdf_list_t *obj_list, 639 struct wlan_objmgr_vdev_objmgr *vdev_obj, 640 wlan_objmgr_ref_dbgid dbg_id) 641 { 642 struct wlan_objmgr_peer *peer; 643 struct wlan_objmgr_peer *peer_next; 644 struct wlan_logically_del_peer *peer_list; 645 qdf_list_t *logical_del_peerlist; 646 bool lock_released = false; 647 648 logical_del_peerlist = qdf_mem_malloc(sizeof(*logical_del_peerlist)); 649 if (!logical_del_peerlist) 650 return NULL; 651 652 qdf_list_create(logical_del_peerlist, vdev_obj->max_peer_count); 653 654 peer = wlan_vdev_peer_list_peek_head(obj_list); 655 while (peer) { 656 wlan_peer_obj_lock(peer); 657 peer_next = wlan_peer_get_next_peer_of_vdev(obj_list, peer); 658 if (peer->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED && 659 qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 660 wlan_objmgr_peer_get_ref(peer, dbg_id); 661 wlan_peer_obj_unlock(peer); 662 lock_released = true; 663 664 peer_list = qdf_mem_malloc(sizeof(*peer_list)); 665 if (!peer_list) { 666 wlan_objmgr_peer_release_ref(peer, dbg_id); 667 WLAN_OBJMGR_BUG(0); 668 break; 669 } 670 671 peer_list->peer = peer; 672 qdf_list_insert_front(logical_del_peerlist, 673 &peer_list->list); 674 } 675 676 if (!lock_released) 677 wlan_peer_obj_unlock(peer); 678 679 peer = peer_next; 680 lock_released = false; 681 } 682 683 /* Not found, return NULL */ 684 if (qdf_list_empty(logical_del_peerlist)) { 685 qdf_mem_free(logical_del_peerlist); 686 return NULL; 687 } 688 689 return logical_del_peerlist; 690 } 691 692 qdf_list_t *wlan_objmgr_vdev_get_log_del_peer_list( 693 struct wlan_objmgr_vdev *vdev, 694 wlan_objmgr_ref_dbgid dbg_id) 695 { 696 qdf_list_t *peer_list; 697 qdf_list_t *log_del_peer_list = NULL; 698 699 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 700 obj_mgr_err("Invalid state vdev:%d state:%d", 701 wlan_vdev_get_id(vdev), vdev->obj_state); 702 return NULL; 703 } 704 705 wlan_vdev_obj_lock(vdev); 706 if (vdev->vdev_objmgr.wlan_peer_count == 0) { 707 wlan_vdev_obj_unlock(vdev); 708 return NULL; 709 } 710 711 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 712 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 713 if (peer_list) { 714 log_del_peer_list = 715 wlan_obj_vdev_populate_logically_del_peerlist( 716 peer_list, &vdev->vdev_objmgr, 717 dbg_id); 718 } 719 720 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 721 wlan_vdev_obj_unlock(vdev); 722 723 return log_del_peer_list; 724 } 725 726 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation( 727 struct wlan_objmgr_vdev *vdev, 728 enum wlan_umac_comp_id id) 729 { 730 wlan_objmgr_vdev_create_handler handler; 731 void *arg; 732 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 733 734 /* Component id is invalid */ 735 if (id >= WLAN_UMAC_MAX_COMPONENTS) 736 return QDF_STATUS_MAXCOMP_FAIL; 737 738 wlan_vdev_obj_lock(vdev); 739 /* 740 * If component object is already created, delete old 741 * component object, then invoke creation 742 */ 743 if (vdev->vdev_comp_priv_obj[id]) { 744 wlan_vdev_obj_unlock(vdev); 745 return QDF_STATUS_E_FAILURE; 746 } 747 wlan_vdev_obj_unlock(vdev); 748 749 /* Invoke registered create handlers */ 750 handler = g_umac_glb_obj->vdev_create_handler[id]; 751 arg = g_umac_glb_obj->vdev_create_handler_arg[id]; 752 if (handler) 753 vdev->obj_status[id] = handler(vdev, arg); 754 else 755 return QDF_STATUS_E_FAILURE; 756 757 /* If object status is created, then only handle this object status */ 758 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 759 /* Derive object status */ 760 obj_status = wlan_objmgr_vdev_object_status(vdev); 761 /* Move PDEV object state to Partially created state */ 762 if (obj_status == QDF_STATUS_COMP_ASYNC) { 763 /*TODO atomic */ 764 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 765 } 766 } 767 return obj_status; 768 } 769 770 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion( 771 struct wlan_objmgr_vdev *vdev, 772 enum wlan_umac_comp_id id) 773 { 774 wlan_objmgr_vdev_destroy_handler handler; 775 void *arg; 776 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 777 778 /* component id is invalid */ 779 if (id >= WLAN_UMAC_MAX_COMPONENTS) 780 return QDF_STATUS_MAXCOMP_FAIL; 781 782 wlan_vdev_obj_lock(vdev); 783 /* Component object was never created, invalid operation */ 784 if (!vdev->vdev_comp_priv_obj[id]) { 785 wlan_vdev_obj_unlock(vdev); 786 return QDF_STATUS_E_FAILURE; 787 } 788 wlan_vdev_obj_unlock(vdev); 789 790 /* Invoke registered create handlers */ 791 handler = g_umac_glb_obj->vdev_destroy_handler[id]; 792 arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; 793 if (handler) 794 vdev->obj_status[id] = handler(vdev, arg); 795 else 796 return QDF_STATUS_E_FAILURE; 797 798 /* If object status is created, then only handle this object status */ 799 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 800 obj_status = wlan_objmgr_vdev_object_status(vdev); 801 /* move object state to DEL progress */ 802 if (obj_status == QDF_STATUS_COMP_ASYNC) 803 vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 804 } 805 return obj_status; 806 } 807 808 809 810 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list, 811 struct wlan_objmgr_peer *obj) 812 { 813 qdf_list_insert_back(obj_list, &obj->vdev_peer); 814 } 815 816 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list, 817 struct wlan_objmgr_peer *peer) 818 { 819 qdf_list_node_t *vdev_node = NULL; 820 821 if (!peer) 822 return QDF_STATUS_E_FAILURE; 823 /* get vdev list node element */ 824 vdev_node = &peer->vdev_peer; 825 /* list is empty, return failure */ 826 if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) 827 return QDF_STATUS_E_FAILURE; 828 829 return QDF_STATUS_SUCCESS; 830 } 831 832 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, 833 struct wlan_objmgr_peer *peer) 834 { 835 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 836 struct wlan_objmgr_pdev *pdev; 837 enum QDF_OPMODE opmode; 838 839 wlan_vdev_obj_lock(vdev); 840 pdev = wlan_vdev_get_pdev(vdev); 841 /* If Max VDEV peer count exceeds, return failure */ 842 if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP && 843 peer->peer_mlme.peer_type != WLAN_PEER_MLO_TEMP) { 844 if (objmgr->wlan_peer_count >= objmgr->max_peer_count) { 845 wlan_vdev_obj_unlock(vdev); 846 return QDF_STATUS_E_FAILURE; 847 } 848 } 849 wlan_vdev_obj_unlock(vdev); 850 851 /* If Max PDEV peer count exceeds, return failure */ 852 wlan_pdev_obj_lock(pdev); 853 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP || 854 peer->peer_mlme.peer_type == WLAN_PEER_MLO_TEMP) { 855 if (wlan_pdev_get_temp_peer_count(pdev) >= 856 WLAN_MAX_PDEV_TEMP_PEERS) { 857 wlan_pdev_obj_unlock(pdev); 858 return QDF_STATUS_E_FAILURE; 859 } 860 } else { 861 if (wlan_pdev_get_peer_count(pdev) >= 862 wlan_pdev_get_max_peer_count(pdev)) { 863 wlan_pdev_obj_unlock(pdev); 864 return QDF_STATUS_E_FAILURE; 865 } 866 } 867 868 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP || 869 peer->peer_mlme.peer_type == WLAN_PEER_MLO_TEMP) 870 wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev)); 871 else 872 wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev)); 873 wlan_pdev_obj_unlock(pdev); 874 875 wlan_vdev_obj_lock(vdev); 876 /* Add peer to vdev's peer list */ 877 wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer); 878 objmgr->wlan_peer_count++; 879 880 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), 881 wlan_vdev_mlme_get_macaddr(vdev)) == 882 QDF_STATUS_SUCCESS) { 883 /* 884 * if peer mac address and vdev mac address match, set 885 * this peer as self peer 886 */ 887 wlan_vdev_set_selfpeer(vdev, peer); 888 opmode = wlan_vdev_mlme_get_opmode(vdev); 889 /* For AP mode, self peer and BSS peer are same */ 890 if ((opmode == QDF_SAP_MODE) || 891 (opmode == QDF_P2P_GO_MODE) || 892 (opmode == QDF_NDI_MODE)) 893 wlan_vdev_set_bsspeer(vdev, peer); 894 } 895 /* set BSS peer for sta */ 896 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE || 897 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) && 898 (wlan_peer_get_peer_type(peer) == WLAN_PEER_AP || 899 wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) 900 wlan_vdev_set_bsspeer(vdev, peer); 901 902 /* Increment vdev ref count to make sure it won't be destroyed before */ 903 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); 904 wlan_vdev_obj_unlock(vdev); 905 return QDF_STATUS_SUCCESS; 906 } 907 908 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev, 909 struct wlan_objmgr_peer *peer) 910 { 911 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 912 struct wlan_objmgr_pdev *pdev; 913 914 wlan_vdev_obj_lock(vdev); 915 /* if peer count is 0, return failure */ 916 if (objmgr->wlan_peer_count == 0) { 917 wlan_vdev_obj_unlock(vdev); 918 return QDF_STATUS_E_FAILURE; 919 } 920 921 if (wlan_vdev_get_selfpeer(vdev) == peer) { 922 /* 923 * There might be instances where new node is created 924 * before deleting existing node, in which case selfpeer 925 * will be pointing to the new node. So set selfpeer to 926 * NULL only if vdev->vdev_objmgr.self_peer is pointing 927 * to the peer processed for deletion 928 */ 929 wlan_vdev_set_selfpeer(vdev, NULL); 930 } 931 932 if (wlan_vdev_get_bsspeer(vdev) == peer) { 933 /* 934 * There might be instances where new node is created 935 * before deleting existing node, in which case bsspeer 936 * in vdev will be pointing to the new node. So set 937 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is 938 * pointing to the peer processed for deletion 939 */ 940 wlan_vdev_set_bsspeer(vdev, NULL); 941 } 942 943 /* remove peer from vdev's peer list */ 944 if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer) 945 == QDF_STATUS_E_FAILURE) { 946 wlan_vdev_obj_unlock(vdev); 947 return QDF_STATUS_E_FAILURE; 948 } 949 /* decrement peer count */ 950 objmgr->wlan_peer_count--; 951 /* decrement pdev peer count */ 952 pdev = wlan_vdev_get_pdev(vdev); 953 wlan_vdev_obj_unlock(vdev); 954 955 wlan_pdev_obj_lock(pdev); 956 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP || 957 peer->peer_mlme.peer_type == WLAN_PEER_MLO_TEMP) 958 wlan_pdev_decr_temp_peer_count(pdev); 959 else 960 wlan_pdev_decr_peer_count(pdev); 961 wlan_pdev_obj_unlock(pdev); 962 963 /* decrement vdev ref count after peer released its reference */ 964 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 965 return QDF_STATUS_SUCCESS; 966 } 967 968 struct wlan_objmgr_peer *wlan_objmgr_vdev_try_get_bsspeer( 969 struct wlan_objmgr_vdev *vdev, 970 wlan_objmgr_ref_dbgid id) 971 { 972 struct wlan_objmgr_peer *peer; 973 QDF_STATUS status = QDF_STATUS_E_EMPTY; 974 975 if (!vdev) 976 return NULL; 977 978 wlan_vdev_obj_lock(vdev); 979 peer = wlan_vdev_get_bsspeer(vdev); 980 if (peer) 981 status = wlan_objmgr_peer_try_get_ref(peer, id); 982 wlan_vdev_obj_unlock(vdev); 983 984 if (QDF_IS_STATUS_SUCCESS(status)) 985 return peer; 986 987 return NULL; 988 } 989 990 void *wlan_objmgr_vdev_get_comp_private_obj( 991 struct wlan_objmgr_vdev *vdev, 992 enum wlan_umac_comp_id id) 993 { 994 void *comp_priv_obj; 995 996 /* component id is invalid */ 997 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 998 QDF_BUG(0); 999 return NULL; 1000 } 1001 1002 if (!vdev) { 1003 QDF_BUG(0); 1004 return NULL; 1005 } 1006 1007 comp_priv_obj = vdev->vdev_comp_priv_obj[id]; 1008 1009 return comp_priv_obj; 1010 } 1011 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj); 1012 1013 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1014 static inline void 1015 wlan_objmgr_vdev_ref_trace(struct wlan_objmgr_vdev *vdev, 1016 wlan_objmgr_ref_dbgid id, 1017 const char *func, int line) 1018 { 1019 struct wlan_objmgr_trace *trace; 1020 1021 trace = &vdev->vdev_objmgr.trace; 1022 1023 if (func) 1024 wlan_objmgr_trace_ref(&trace->references[id].head, 1025 trace, func, line); 1026 } 1027 1028 static inline void 1029 wlan_objmgr_vdev_deref_trace(struct wlan_objmgr_vdev *vdev, 1030 wlan_objmgr_ref_dbgid id, 1031 const char *func, int line) 1032 { 1033 struct wlan_objmgr_trace *trace; 1034 1035 trace = &vdev->vdev_objmgr.trace; 1036 1037 if (func) 1038 wlan_objmgr_trace_ref(&trace->dereferences[id].head, 1039 trace, func, line); 1040 } 1041 #endif 1042 1043 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1044 void wlan_objmgr_vdev_get_ref_debug(struct wlan_objmgr_vdev *vdev, 1045 wlan_objmgr_ref_dbgid id, 1046 const char *func, int line) 1047 { 1048 if (!vdev) { 1049 obj_mgr_err("vdev obj is NULL for id:%d", id); 1050 QDF_ASSERT(0); 1051 return; 1052 } 1053 /* Increment ref count */ 1054 qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); 1055 qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); 1056 1057 wlan_objmgr_vdev_ref_trace(vdev, id, func, line); 1058 return; 1059 } 1060 1061 qdf_export_symbol(wlan_objmgr_vdev_get_ref_debug); 1062 #else 1063 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, 1064 wlan_objmgr_ref_dbgid id) 1065 { 1066 if (!vdev) { 1067 obj_mgr_err("vdev obj is NULL for id:%d", id); 1068 QDF_ASSERT(0); 1069 return; 1070 } 1071 /* Increment ref count */ 1072 qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); 1073 qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); 1074 } 1075 1076 qdf_export_symbol(wlan_objmgr_vdev_get_ref); 1077 #endif 1078 1079 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1080 QDF_STATUS wlan_objmgr_vdev_try_get_ref_debug(struct wlan_objmgr_vdev *vdev, 1081 wlan_objmgr_ref_dbgid id, 1082 const char *func, int line) 1083 { 1084 uint8_t vdev_id; 1085 1086 if (!vdev) { 1087 obj_mgr_err("vdev obj is NULL for id:%d", id); 1088 QDF_ASSERT(0); 1089 return QDF_STATUS_E_FAILURE; 1090 } 1091 1092 wlan_vdev_obj_lock(vdev); 1093 vdev_id = wlan_vdev_get_id(vdev); 1094 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 1095 wlan_vdev_obj_unlock(vdev); 1096 if (vdev->vdev_objmgr.print_cnt++ <= 1097 WLAN_OBJMGR_RATELIMIT_THRESH) 1098 obj_mgr_err( 1099 "[Ref id: %d] vdev(%d) is not in Created state(%d)", 1100 id, vdev_id, vdev->obj_state); 1101 1102 return QDF_STATUS_E_RESOURCES; 1103 } 1104 1105 /* Increment ref count */ 1106 wlan_objmgr_vdev_get_ref_debug(vdev, id, func, line); 1107 wlan_vdev_obj_unlock(vdev); 1108 1109 return QDF_STATUS_SUCCESS; 1110 } 1111 1112 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref_debug); 1113 #else 1114 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, 1115 wlan_objmgr_ref_dbgid id) 1116 { 1117 uint8_t vdev_id; 1118 1119 if (!vdev) { 1120 obj_mgr_err("vdev obj is NULL for id:%d", id); 1121 QDF_ASSERT(0); 1122 return QDF_STATUS_E_FAILURE; 1123 } 1124 1125 wlan_vdev_obj_lock(vdev); 1126 vdev_id = wlan_vdev_get_id(vdev); 1127 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 1128 wlan_vdev_obj_unlock(vdev); 1129 if (vdev->vdev_objmgr.print_cnt++ <= 1130 WLAN_OBJMGR_RATELIMIT_THRESH) 1131 obj_mgr_debug( 1132 "[Ref id: %d] vdev(%d) is not in Created state(%d)", 1133 id, vdev_id, vdev->obj_state); 1134 1135 return QDF_STATUS_E_RESOURCES; 1136 } 1137 1138 /* Increment ref count */ 1139 wlan_objmgr_vdev_get_ref(vdev, id); 1140 wlan_vdev_obj_unlock(vdev); 1141 1142 return QDF_STATUS_SUCCESS; 1143 } 1144 1145 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref); 1146 #endif 1147 1148 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1149 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev_debug( 1150 struct wlan_objmgr_pdev *pdev, 1151 qdf_list_t *vdev_list, 1152 struct wlan_objmgr_vdev *vdev, 1153 wlan_objmgr_ref_dbgid dbg_id, 1154 const char *func, int line) 1155 { 1156 struct wlan_objmgr_vdev *vdev_next; 1157 qdf_list_node_t *node = &vdev->vdev_node; 1158 qdf_list_node_t *prev_node = NULL; 1159 1160 if (!node) 1161 return NULL; 1162 1163 wlan_pdev_obj_lock(pdev); 1164 prev_node = node; 1165 while (qdf_list_peek_next(vdev_list, prev_node, &node) == 1166 QDF_STATUS_SUCCESS) { 1167 vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, 1168 vdev_node); 1169 if (wlan_objmgr_vdev_try_get_ref_debug(vdev_next, dbg_id, 1170 func, line) == 1171 QDF_STATUS_SUCCESS) { 1172 wlan_pdev_obj_unlock(pdev); 1173 return vdev_next; 1174 } 1175 1176 prev_node = node; 1177 } 1178 wlan_pdev_obj_unlock(pdev); 1179 1180 return NULL; 1181 } 1182 #else 1183 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( 1184 struct wlan_objmgr_pdev *pdev, 1185 qdf_list_t *vdev_list, 1186 struct wlan_objmgr_vdev *vdev, 1187 wlan_objmgr_ref_dbgid dbg_id) 1188 { 1189 struct wlan_objmgr_vdev *vdev_next; 1190 qdf_list_node_t *node = &vdev->vdev_node; 1191 qdf_list_node_t *prev_node = NULL; 1192 1193 if (!node) 1194 return NULL; 1195 1196 wlan_pdev_obj_lock(pdev); 1197 prev_node = node; 1198 while (qdf_list_peek_next(vdev_list, prev_node, &node) == 1199 QDF_STATUS_SUCCESS) { 1200 vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, 1201 vdev_node); 1202 if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) == 1203 QDF_STATUS_SUCCESS) { 1204 wlan_pdev_obj_unlock(pdev); 1205 return vdev_next; 1206 } 1207 1208 prev_node = node; 1209 } 1210 wlan_pdev_obj_unlock(pdev); 1211 1212 return NULL; 1213 } 1214 #endif 1215 1216 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1217 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head_debug( 1218 struct wlan_objmgr_pdev *pdev, 1219 qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id, 1220 const char *func, int line) 1221 { 1222 struct wlan_objmgr_vdev *vdev; 1223 qdf_list_node_t *node = NULL; 1224 qdf_list_node_t *prev_node = NULL; 1225 1226 wlan_pdev_obj_lock(pdev); 1227 1228 if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { 1229 wlan_pdev_obj_unlock(pdev); 1230 return NULL; 1231 } 1232 1233 do { 1234 vdev = qdf_container_of(node, struct wlan_objmgr_vdev, 1235 vdev_node); 1236 if (wlan_objmgr_vdev_try_get_ref_debug(vdev, dbg_id, 1237 func, line) == 1238 QDF_STATUS_SUCCESS) { 1239 wlan_pdev_obj_unlock(pdev); 1240 return vdev; 1241 } 1242 1243 prev_node = node; 1244 } while (qdf_list_peek_next(vdev_list, prev_node, &node) == 1245 QDF_STATUS_SUCCESS); 1246 1247 wlan_pdev_obj_unlock(pdev); 1248 1249 return NULL; 1250 } 1251 #else 1252 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( 1253 struct wlan_objmgr_pdev *pdev, 1254 qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id) 1255 { 1256 struct wlan_objmgr_vdev *vdev; 1257 qdf_list_node_t *node = NULL; 1258 qdf_list_node_t *prev_node = NULL; 1259 1260 wlan_pdev_obj_lock(pdev); 1261 1262 if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { 1263 wlan_pdev_obj_unlock(pdev); 1264 return NULL; 1265 } 1266 1267 do { 1268 vdev = qdf_container_of(node, struct wlan_objmgr_vdev, 1269 vdev_node); 1270 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 1271 QDF_STATUS_SUCCESS) { 1272 wlan_pdev_obj_unlock(pdev); 1273 return vdev; 1274 } 1275 1276 prev_node = node; 1277 } while (qdf_list_peek_next(vdev_list, prev_node, &node) == 1278 QDF_STATUS_SUCCESS); 1279 1280 wlan_pdev_obj_unlock(pdev); 1281 1282 return NULL; 1283 } 1284 #endif 1285 1286 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1287 struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev_debug( 1288 struct wlan_objmgr_pdev *pdev, 1289 wlan_objmgr_ref_dbgid dbg_id, 1290 const char *func, int line) 1291 { 1292 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 1293 qdf_list_t *vdev_list; 1294 1295 /* VDEV list */ 1296 vdev_list = &objmgr->wlan_vdev_list; 1297 1298 return wlan_pdev_vdev_list_peek_active_head_debug(pdev, vdev_list, 1299 dbg_id, func, line); 1300 } 1301 #else 1302 struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev( 1303 struct wlan_objmgr_pdev *pdev, 1304 wlan_objmgr_ref_dbgid dbg_id) 1305 { 1306 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 1307 qdf_list_t *vdev_list; 1308 1309 /* VDEV list */ 1310 vdev_list = &objmgr->wlan_vdev_list; 1311 1312 return wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list, 1313 dbg_id); 1314 } 1315 #endif 1316 1317 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1318 void wlan_objmgr_vdev_release_ref_debug(struct wlan_objmgr_vdev *vdev, 1319 wlan_objmgr_ref_dbgid id, 1320 const char *func, int line) 1321 { 1322 uint8_t vdev_id; 1323 1324 if (!vdev) { 1325 obj_mgr_err("vdev obj is NULL for id:%d", id); 1326 QDF_ASSERT(0); 1327 return; 1328 } 1329 1330 vdev_id = wlan_vdev_get_id(vdev); 1331 1332 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { 1333 obj_mgr_alert("vdev (id:%d)ref cnt was not taken by %d", 1334 vdev_id, id); 1335 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, 1336 QDF_TRACE_LEVEL_FATAL); 1337 WLAN_OBJMGR_BUG(0); 1338 return; 1339 } 1340 1341 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { 1342 obj_mgr_alert("vdev ref cnt is 0"); 1343 WLAN_OBJMGR_BUG(0); 1344 return; 1345 } 1346 qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); 1347 wlan_objmgr_vdev_deref_trace(vdev, id, func, line); 1348 1349 /* Decrement ref count, free vdev, if ref count == 0 */ 1350 if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) 1351 wlan_objmgr_vdev_obj_destroy(vdev); 1352 } 1353 1354 qdf_export_symbol(wlan_objmgr_vdev_release_ref_debug); 1355 #else 1356 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, 1357 wlan_objmgr_ref_dbgid id) 1358 { 1359 uint8_t vdev_id; 1360 1361 if (!vdev) { 1362 obj_mgr_err("vdev obj is NULL for id:%d", id); 1363 QDF_ASSERT(0); 1364 return; 1365 } 1366 1367 vdev_id = wlan_vdev_get_id(vdev); 1368 1369 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { 1370 obj_mgr_alert("vdev (id:%d)ref cnt was not taken by %d", 1371 vdev_id, id); 1372 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, 1373 QDF_TRACE_LEVEL_FATAL); 1374 WLAN_OBJMGR_BUG(0); 1375 return; 1376 } 1377 1378 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { 1379 obj_mgr_alert("vdev ref cnt is 0"); 1380 WLAN_OBJMGR_BUG(0); 1381 return; 1382 } 1383 qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); 1384 1385 /* Decrement ref count, free vdev, if ref count == 0 */ 1386 if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) 1387 wlan_objmgr_vdev_obj_destroy(vdev); 1388 } 1389 1390 qdf_export_symbol(wlan_objmgr_vdev_release_ref); 1391 #endif 1392 1393 #ifdef WLAN_OBJMGR_DEBUG 1394 void wlan_print_vdev_info(struct wlan_objmgr_vdev *vdev) 1395 { 1396 struct wlan_objmgr_vdev_objmgr *vdev_objmgr; 1397 uint32_t ref_cnt; 1398 1399 vdev_objmgr = &vdev->vdev_objmgr; 1400 1401 ref_cnt = qdf_atomic_read(&vdev_objmgr->ref_cnt); 1402 1403 obj_mgr_debug("vdev: %pK", vdev); 1404 obj_mgr_debug("vdev_id: %d", vdev_objmgr->vdev_id); 1405 obj_mgr_debug("print_cnt: %d", vdev_objmgr->print_cnt); 1406 obj_mgr_debug("wlan_pdev: %pK", vdev_objmgr->wlan_pdev); 1407 obj_mgr_debug("ref_cnt: %d", ref_cnt); 1408 } 1409 1410 qdf_export_symbol(wlan_print_vdev_info); 1411 #endif 1412 1413 void wlan_objmgr_vdev_peer_freed_notify(struct wlan_objmgr_vdev *vdev) 1414 { 1415 wlan_objmgr_vdev_peer_free_notify_handler stat_handler; 1416 uint8_t i; 1417 1418 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 1419 stat_handler = g_umac_glb_obj->vdev_peer_free_notify_handler[i]; 1420 if (stat_handler) 1421 stat_handler(vdev); 1422 } 1423 } 1424 1425 QDF_STATUS wlan_vdev_get_bss_peer_mac(struct wlan_objmgr_vdev *vdev, 1426 struct qdf_mac_addr *bss_peer_mac) 1427 { 1428 struct wlan_objmgr_peer *peer; 1429 1430 if (!vdev) { 1431 obj_mgr_err("vdev is null"); 1432 return QDF_STATUS_E_INVAL; 1433 } 1434 1435 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLME_OBJMGR_ID); 1436 if (!peer) { 1437 obj_mgr_err("not able to find bss peer for vdev %d", 1438 wlan_vdev_get_id(vdev)); 1439 return QDF_STATUS_E_INVAL; 1440 } 1441 wlan_peer_obj_lock(peer); 1442 qdf_mem_copy(bss_peer_mac->bytes, wlan_peer_get_macaddr(peer), 1443 QDF_MAC_ADDR_SIZE); 1444 wlan_peer_obj_unlock(peer); 1445 1446 wlan_objmgr_peer_release_ref(peer, WLAN_MLME_OBJMGR_ID); 1447 1448 return QDF_STATUS_SUCCESS; 1449 } 1450 1451 #ifdef WLAN_FEATURE_11BE_MLO 1452 QDF_STATUS wlan_vdev_get_bss_peer_mld_mac(struct wlan_objmgr_vdev *vdev, 1453 struct qdf_mac_addr *mld_mac) 1454 { 1455 struct wlan_objmgr_peer *peer; 1456 1457 if (!vdev) { 1458 obj_mgr_err("vdev is null"); 1459 return QDF_STATUS_E_INVAL; 1460 } 1461 1462 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLME_OBJMGR_ID); 1463 if (!peer) { 1464 obj_mgr_err("not able to find bss peer for vdev %d", 1465 wlan_vdev_get_id(vdev)); 1466 return QDF_STATUS_E_INVAL; 1467 } 1468 wlan_peer_obj_lock(peer); 1469 qdf_mem_copy(mld_mac->bytes, wlan_peer_mlme_get_mldaddr(peer), 1470 QDF_MAC_ADDR_SIZE); 1471 wlan_peer_obj_unlock(peer); 1472 1473 wlan_objmgr_peer_release_ref(peer, WLAN_MLME_OBJMGR_ID); 1474 1475 return QDF_STATUS_SUCCESS; 1476 } 1477 1478 bool wlan_vdev_mlme_is_mlo_vdev(struct wlan_objmgr_vdev *vdev) 1479 { 1480 bool is_mlo_vdev; 1481 1482 if (!vdev) { 1483 obj_mgr_err("vdev is NULL"); 1484 return false; 1485 } 1486 1487 wlan_acquire_vdev_mlo_lock(vdev); 1488 1489 is_mlo_vdev = 1490 wlan_vdev_mlme_feat_ext2_cap_get(vdev, WLAN_VDEV_FEXT2_MLO); 1491 1492 wlan_release_vdev_mlo_lock(vdev); 1493 1494 return is_mlo_vdev; 1495 } 1496 1497 qdf_export_symbol(wlan_vdev_mlme_is_mlo_vdev); 1498 1499 void wlan_vdev_mlme_set_mlo_vdev(struct wlan_objmgr_vdev *vdev) 1500 { 1501 struct wlan_objmgr_pdev *pdev; 1502 1503 if (!vdev) { 1504 obj_mgr_err("vdev is NULL"); 1505 return; 1506 } 1507 1508 pdev = wlan_vdev_get_pdev(vdev); 1509 if (!pdev) { 1510 obj_mgr_err("pdev is NULL"); 1511 return; 1512 } 1513 1514 wlan_acquire_vdev_mlo_lock(vdev); 1515 1516 if (wlan_vdev_mlme_feat_ext2_cap_get(vdev, WLAN_VDEV_FEXT2_MLO)) { 1517 wlan_release_vdev_mlo_lock(vdev); 1518 return; 1519 } 1520 wlan_vdev_mlme_feat_ext2_cap_set(vdev, WLAN_VDEV_FEXT2_MLO); 1521 1522 wlan_pdev_inc_mlo_vdev_count(pdev); 1523 1524 wlan_release_vdev_mlo_lock(vdev); 1525 } 1526 1527 void wlan_vdev_mlme_clear_mlo_vdev(struct wlan_objmgr_vdev *vdev) 1528 { 1529 struct wlan_objmgr_pdev *pdev; 1530 1531 if (!vdev) { 1532 obj_mgr_err("vdev is NULL"); 1533 return; 1534 } 1535 1536 pdev = wlan_vdev_get_pdev(vdev); 1537 if (!pdev) { 1538 obj_mgr_err("pdev is NULL"); 1539 return; 1540 } 1541 1542 wlan_acquire_vdev_mlo_lock(vdev); 1543 1544 if (!wlan_vdev_mlme_feat_ext2_cap_get(vdev, WLAN_VDEV_FEXT2_MLO)) { 1545 wlan_release_vdev_mlo_lock(vdev); 1546 return; 1547 } 1548 wlan_vdev_mlme_feat_ext2_cap_clear(vdev, WLAN_VDEV_FEXT2_MLO); 1549 1550 wlan_pdev_dec_mlo_vdev_count(pdev); 1551 1552 wlan_release_vdev_mlo_lock(vdev); 1553 } 1554 #endif /* WLAN_FEATURE_11BE_MLO */ 1555