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