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