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