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