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