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