1 /* 2 * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 /** 19 * DOC: Public APIs to perform operations on Global objects 20 */ 21 #include <wlan_objmgr_cmn.h> 22 #include <wlan_objmgr_global_obj.h> 23 #include <wlan_objmgr_psoc_obj.h> 24 #include <wlan_objmgr_pdev_obj.h> 25 #include <wlan_objmgr_vdev_obj.h> 26 #include <wlan_objmgr_peer_obj.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 33 34 /** 35 ** APIs to Create/Delete Global object APIs 36 */ 37 static QDF_STATUS wlan_objmgr_pdev_object_status( 38 struct wlan_objmgr_pdev *pdev) 39 { 40 uint8_t id; 41 QDF_STATUS status = QDF_STATUS_SUCCESS; 42 43 wlan_pdev_obj_lock(pdev); 44 /* Iterate through all components to derive the object status */ 45 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 46 /* If component disabled, Ignore */ 47 if (pdev->obj_status[id] == QDF_STATUS_COMP_DISABLED) { 48 continue; 49 /* If component operates in Async, status is Partially created, 50 break */ 51 } else if (pdev->obj_status[id] == QDF_STATUS_COMP_ASYNC) { 52 if (pdev->pdev_comp_priv_obj[id] == NULL) { 53 status = QDF_STATUS_COMP_ASYNC; 54 break; 55 } 56 /* If component failed to allocate its object, treat it as 57 failure, complete object need to be cleaned up */ 58 } else if ((pdev->obj_status[id] == QDF_STATUS_E_NOMEM) || 59 (pdev->obj_status[id] == QDF_STATUS_E_FAILURE)) { 60 status = QDF_STATUS_E_FAILURE; 61 break; 62 } 63 } 64 wlan_pdev_obj_unlock(pdev); 65 return status; 66 } 67 68 static QDF_STATUS wlan_objmgr_pdev_obj_free(struct wlan_objmgr_pdev *pdev) 69 { 70 71 uint8_t pdev_id; 72 73 if (pdev == NULL) { 74 obj_mgr_err("pdev obj is NULL"); 75 QDF_ASSERT(0); 76 return QDF_STATUS_E_FAILURE; 77 } 78 79 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 80 81 /* Detach PDEV from PSOC PDEV's list */ 82 if (wlan_objmgr_psoc_pdev_detach(pdev->pdev_objmgr.wlan_psoc, pdev) == 83 QDF_STATUS_E_FAILURE) { 84 obj_mgr_err("PSOC PDEV detach failed: pdev-id: %d", pdev_id); 85 return QDF_STATUS_E_FAILURE; 86 } 87 qdf_spinlock_destroy(&pdev->pdev_lock); 88 qdf_mem_free(pdev); 89 90 return QDF_STATUS_SUCCESS; 91 } 92 93 struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( 94 struct wlan_objmgr_psoc *psoc, 95 struct pdev_osif_priv *osdev_priv) 96 { 97 struct wlan_objmgr_pdev *pdev; 98 uint8_t id; 99 wlan_objmgr_pdev_create_handler handler; 100 wlan_objmgr_pdev_status_handler s_handler; 101 void *arg; 102 QDF_STATUS obj_status; 103 104 if (psoc == NULL) { 105 obj_mgr_err("psoc is NULL"); 106 return NULL; 107 } 108 /* Allocate PDEV object's memory */ 109 pdev = qdf_mem_malloc(sizeof(*pdev)); 110 if (pdev == NULL) { 111 obj_mgr_err("pdev alloc failed"); 112 return NULL; 113 } 114 pdev->obj_state = WLAN_OBJ_STATE_ALLOCATED; 115 /* Initialize PDEV spinlock */ 116 qdf_spinlock_create(&pdev->pdev_lock); 117 /* Attach PDEV with PSOC */ 118 if (wlan_objmgr_psoc_pdev_attach(psoc, pdev) 119 != QDF_STATUS_SUCCESS) { 120 obj_mgr_err("pdev psoc attach failed"); 121 qdf_spinlock_destroy(&pdev->pdev_lock); 122 qdf_mem_free(pdev); 123 return NULL; 124 } 125 /* Save PSOC object pointer in PDEV */ 126 wlan_pdev_set_psoc(pdev, psoc); 127 /* Initialize PDEV's VDEV list, assign default values */ 128 qdf_list_create(&pdev->pdev_objmgr.wlan_vdev_list, 129 WLAN_UMAC_PDEV_MAX_VDEVS); 130 pdev->pdev_objmgr.wlan_vdev_count = 0; 131 pdev->pdev_objmgr.max_vdev_count = WLAN_UMAC_PDEV_MAX_VDEVS; 132 pdev->pdev_objmgr.wlan_peer_count = 0; 133 pdev->pdev_objmgr.temp_peer_count = 0; 134 pdev->pdev_objmgr.max_peer_count = wlan_psoc_get_max_peer_count(psoc); 135 /* Save HDD/OSIF pointer */ 136 pdev->pdev_nif.pdev_ospriv = osdev_priv; 137 qdf_atomic_init(&pdev->pdev_objmgr.ref_cnt); 138 pdev->pdev_objmgr.print_cnt = 0; 139 wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID); 140 /* Invoke registered create handlers */ 141 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 142 handler = g_umac_glb_obj->pdev_create_handler[id]; 143 arg = g_umac_glb_obj->pdev_create_handler_arg[id]; 144 if (handler != NULL) 145 pdev->obj_status[id] = handler(pdev, arg); 146 else 147 pdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 148 } 149 /* Derive object status */ 150 obj_status = wlan_objmgr_pdev_object_status(pdev); 151 152 if (obj_status == QDF_STATUS_SUCCESS) { 153 /* Object status is SUCCESS, Object is created */ 154 pdev->obj_state = WLAN_OBJ_STATE_CREATED; 155 /* Invoke component registered status handlers */ 156 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 157 s_handler = g_umac_glb_obj->pdev_status_handler[id]; 158 arg = g_umac_glb_obj->pdev_status_handler_arg[id]; 159 if (s_handler != NULL) { 160 s_handler(pdev, arg, 161 QDF_STATUS_SUCCESS); 162 } 163 } 164 /* Few components operates in Asynchrous communction, Object state 165 partially created */ 166 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 167 pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 168 /* Component object failed to be created, clean up the object */ 169 } else if (obj_status == QDF_STATUS_E_FAILURE) { 170 /* Clean up the psoc */ 171 obj_mgr_err("PDEV component objects allocation failed"); 172 wlan_objmgr_pdev_obj_delete(pdev); 173 return NULL; 174 } 175 176 obj_mgr_info("Created pdev %d", pdev->pdev_objmgr.wlan_pdev_id); 177 178 return pdev; 179 } 180 qdf_export_symbol(wlan_objmgr_pdev_obj_create); 181 182 static QDF_STATUS wlan_objmgr_pdev_obj_destroy(struct wlan_objmgr_pdev *pdev) 183 { 184 uint8_t id; 185 wlan_objmgr_pdev_destroy_handler handler; 186 QDF_STATUS obj_status; 187 void *arg; 188 uint8_t pdev_id; 189 190 if (pdev == NULL) { 191 obj_mgr_err("pdev is NULL"); 192 return QDF_STATUS_E_FAILURE; 193 } 194 wlan_objmgr_notify_destroy(pdev, WLAN_PDEV_OP); 195 196 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 197 198 obj_mgr_info("Physically deleting pdev %d", pdev_id); 199 200 if (pdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 201 obj_mgr_err("PDEV object delete is not invoked pdevid:%d objstate:%d", 202 pdev_id, pdev->obj_state); 203 WLAN_OBJMGR_BUG(0); 204 } 205 206 /* Invoke registered destroy handlers */ 207 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 208 handler = g_umac_glb_obj->pdev_destroy_handler[id]; 209 arg = g_umac_glb_obj->pdev_destroy_handler_arg[id]; 210 if (handler != NULL) 211 pdev->obj_status[id] = handler(pdev, arg); 212 else 213 pdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 214 } 215 /* Derive object status */ 216 obj_status = wlan_objmgr_pdev_object_status(pdev); 217 218 if (obj_status == QDF_STATUS_E_FAILURE) { 219 obj_mgr_err("PDEV component objects destroy failed: pdev-id:%d", 220 pdev_id); 221 /* Ideally should not happen */ 222 /* This leads to memleak ??? how to handle */ 223 QDF_BUG(0); 224 return QDF_STATUS_E_FAILURE; 225 } 226 /* Deletion is in progress */ 227 if (obj_status == QDF_STATUS_COMP_ASYNC) { 228 pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 229 return QDF_STATUS_COMP_ASYNC; 230 } 231 232 /* Free PDEV object */ 233 return wlan_objmgr_pdev_obj_free(pdev); 234 } 235 236 QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) 237 { 238 uint8_t print_idx; 239 240 if (pdev == NULL) { 241 obj_mgr_err("pdev is NULL"); 242 return QDF_STATUS_E_FAILURE; 243 } 244 245 obj_mgr_info("Logically deleting pdev %d", 246 pdev->pdev_objmgr.wlan_pdev_id); 247 248 print_idx = qdf_get_pidx(); 249 if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR, 250 QDF_TRACE_LEVEL_DEBUG)) { 251 wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg); 252 } 253 254 /* 255 * Update PDEV object state to LOGICALLY DELETED 256 * It prevents further access of this object 257 */ 258 wlan_pdev_obj_lock(pdev); 259 pdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 260 wlan_pdev_obj_unlock(pdev); 261 wlan_objmgr_notify_log_delete(pdev, WLAN_PDEV_OP); 262 wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID); 263 264 return QDF_STATUS_SUCCESS; 265 } 266 qdf_export_symbol(wlan_objmgr_pdev_obj_delete); 267 268 /** 269 ** APIs to attach/detach component objects 270 */ 271 QDF_STATUS wlan_objmgr_pdev_component_obj_attach( 272 struct wlan_objmgr_pdev *pdev, 273 enum wlan_umac_comp_id id, 274 void *comp_priv_obj, 275 QDF_STATUS status) 276 { 277 uint8_t i; 278 wlan_objmgr_pdev_status_handler s_hlr; 279 void *a; 280 QDF_STATUS obj_status; 281 282 /* component id is invalid */ 283 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 284 obj_mgr_err("component-id %d is not supported", id); 285 return QDF_STATUS_MAXCOMP_FAIL; 286 } 287 wlan_pdev_obj_lock(pdev); 288 /* If there is a valid entry, return failure */ 289 if (pdev->pdev_comp_priv_obj[id] != NULL) { 290 obj_mgr_err("component-%d already have valid pointer", id); 291 wlan_pdev_obj_unlock(pdev); 292 return QDF_STATUS_E_FAILURE; 293 } 294 /* Save component's pointer and status */ 295 pdev->pdev_comp_priv_obj[id] = comp_priv_obj; 296 pdev->obj_status[id] = status; 297 298 wlan_pdev_obj_unlock(pdev); 299 300 if (pdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 301 return QDF_STATUS_SUCCESS; 302 /** 303 * If PDEV object status is partially created means, this API is 304 * invoked with differnt context, this block should be executed for 305 * async components only 306 */ 307 /* Derive status */ 308 obj_status = wlan_objmgr_pdev_object_status(pdev); 309 /* STATUS_SUCCESS means, object is CREATED */ 310 if (obj_status == QDF_STATUS_SUCCESS) 311 pdev->obj_state = WLAN_OBJ_STATE_CREATED; 312 /* update state as CREATION failed, caller has to delete the 313 PDEV object */ 314 else if (obj_status == QDF_STATUS_E_FAILURE) 315 pdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 316 /* Notify components about the CREATION success/failure */ 317 if ((obj_status == QDF_STATUS_SUCCESS) || 318 (obj_status == QDF_STATUS_E_FAILURE)) { 319 /* nofity object status */ 320 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 321 s_hlr = g_umac_glb_obj->pdev_status_handler[i]; 322 a = g_umac_glb_obj->pdev_status_handler_arg[i]; 323 if (s_hlr != NULL) 324 s_hlr(pdev, a, obj_status); 325 } 326 } 327 return QDF_STATUS_SUCCESS; 328 } 329 qdf_export_symbol(wlan_objmgr_pdev_component_obj_attach); 330 331 QDF_STATUS wlan_objmgr_pdev_component_obj_detach( 332 struct wlan_objmgr_pdev *pdev, 333 enum wlan_umac_comp_id id, 334 void *comp_priv_obj) 335 { 336 QDF_STATUS obj_status; 337 338 /* component id is invalid */ 339 if (id >= WLAN_UMAC_MAX_COMPONENTS) 340 return QDF_STATUS_MAXCOMP_FAIL; 341 342 wlan_pdev_obj_lock(pdev); 343 /* If there is a invalid entry, return failure */ 344 if (pdev->pdev_comp_priv_obj[id] != comp_priv_obj) { 345 pdev->obj_status[id] = QDF_STATUS_E_FAILURE; 346 wlan_pdev_obj_unlock(pdev); 347 return QDF_STATUS_E_FAILURE; 348 } 349 /* Reset pointers to NULL, update the status*/ 350 pdev->pdev_comp_priv_obj[id] = NULL; 351 pdev->obj_status[id] = QDF_STATUS_SUCCESS; 352 wlan_pdev_obj_unlock(pdev); 353 354 /* If PDEV object status is partially destroyed means, this API is 355 invoked with differnt context, this block should be executed for async 356 components only */ 357 if ((pdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 358 (pdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 359 /* Derive object status */ 360 obj_status = wlan_objmgr_pdev_object_status(pdev); 361 if (obj_status == QDF_STATUS_SUCCESS) { 362 /*Update the status as Deleted, if full object 363 deletion is in progress */ 364 if (pdev->obj_state == 365 WLAN_OBJ_STATE_PARTIALLY_DELETED) 366 pdev->obj_state = WLAN_OBJ_STATE_DELETED; 367 /* Move to creation state, since this component 368 deletion alone requested */ 369 if (pdev->obj_state == 370 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 371 pdev->obj_state = WLAN_OBJ_STATE_CREATED; 372 /* Object status is failure */ 373 } else if (obj_status == QDF_STATUS_E_FAILURE) { 374 /*Update the status as Deletion failed, if full object 375 deletion is in progress */ 376 if (pdev->obj_state == 377 WLAN_OBJ_STATE_PARTIALLY_DELETED) 378 pdev->obj_state = 379 WLAN_OBJ_STATE_DELETION_FAILED; 380 /* Move to creation state, since this component 381 deletion alone requested (do not block other 382 components)*/ 383 if (pdev->obj_state == 384 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 385 pdev->obj_state = WLAN_OBJ_STATE_CREATED; 386 } 387 388 /* Delete pdev object */ 389 if ((obj_status == QDF_STATUS_SUCCESS) && 390 (pdev->obj_state == WLAN_OBJ_STATE_DELETED)) { 391 /* Free PDEV object */ 392 return wlan_objmgr_pdev_obj_free(pdev); 393 } 394 } 395 return QDF_STATUS_SUCCESS; 396 } 397 qdf_export_symbol(wlan_objmgr_pdev_component_obj_detach); 398 399 /** 400 ** APIs to operations on pdev objects 401 */ 402 static void wlan_objmgr_pdev_vdev_iterate_peers(struct wlan_objmgr_pdev *pdev, 403 struct wlan_objmgr_vdev *vdev, 404 wlan_objmgr_pdev_op_handler handler, 405 void *arg, uint8_t lock_free_op, 406 wlan_objmgr_ref_dbgid dbg_id) 407 { 408 qdf_list_t *peer_list = NULL; 409 struct wlan_objmgr_peer *peer = NULL; 410 struct wlan_objmgr_peer *peer_next = NULL; 411 412 /* Iterating through vdev's peer list, so lock is 413 needed */ 414 if (!lock_free_op) 415 wlan_vdev_obj_lock(vdev); 416 /* Get peer list of the vdev */ 417 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 418 if (peer_list != NULL) { 419 peer = wlan_vdev_peer_list_peek_head(peer_list); 420 while (peer != NULL) { 421 /* Get next peer pointer */ 422 peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, 423 peer); 424 /* Increment ref count, to hold the 425 peer pointer */ 426 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 427 QDF_STATUS_SUCCESS) { 428 /* Invoke the handler */ 429 handler(pdev, (void *)peer, arg); 430 wlan_objmgr_peer_release_ref(peer, dbg_id); 431 } 432 peer = peer_next; 433 } 434 } 435 if (!lock_free_op) 436 wlan_vdev_obj_unlock(vdev); 437 } 438 439 QDF_STATUS wlan_objmgr_pdev_iterate_obj_list( 440 struct wlan_objmgr_pdev *pdev, 441 enum wlan_objmgr_obj_type obj_type, 442 wlan_objmgr_pdev_op_handler handler, 443 void *arg, uint8_t lock_free_op, 444 wlan_objmgr_ref_dbgid dbg_id) 445 { 446 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 447 qdf_list_t *vdev_list = NULL; 448 struct wlan_objmgr_vdev *vdev = NULL; 449 struct wlan_objmgr_vdev *vdev_next = NULL; 450 451 /* If caller requests for lock free opeation, do not acquire 452 handler will handle the synchronization*/ 453 if (!lock_free_op) 454 wlan_pdev_obj_lock(pdev); 455 /* VDEV list */ 456 vdev_list = &objmgr->wlan_vdev_list; 457 switch (obj_type) { 458 case WLAN_VDEV_OP: 459 /* Iterate through all VDEV object, and invoke handler for each 460 VDEV object */ 461 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 462 while (vdev != NULL) { 463 /* 464 * Get next vdev (handler can be invoked for 465 * vdev deletion also 466 */ 467 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, 468 vdev); 469 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 470 QDF_STATUS_SUCCESS) { 471 handler(pdev, (void *)vdev, arg); 472 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 473 } 474 vdev = vdev_next; 475 } 476 break; 477 case WLAN_PEER_OP: 478 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 479 while (vdev != NULL) { 480 /* Get Next VDEV */ 481 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, 482 vdev); 483 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 484 QDF_STATUS_SUCCESS) { 485 wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev, 486 handler, arg, 487 lock_free_op, 488 dbg_id); 489 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 490 } 491 vdev = vdev_next; 492 } 493 break; 494 default: 495 break; 496 } 497 if (!lock_free_op) 498 wlan_pdev_obj_unlock(pdev); 499 500 return QDF_STATUS_SUCCESS; 501 } 502 qdf_export_symbol(wlan_objmgr_pdev_iterate_obj_list); 503 504 QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_creation( 505 struct wlan_objmgr_pdev *pdev, 506 enum wlan_umac_comp_id id) 507 { 508 wlan_objmgr_pdev_create_handler handler; 509 void *arg; 510 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 511 512 /* Component id is invalid */ 513 if (id >= WLAN_UMAC_MAX_COMPONENTS) 514 return QDF_STATUS_MAXCOMP_FAIL; 515 516 wlan_pdev_obj_lock(pdev); 517 /* If component object is already created, delete old 518 component object, then invoke creation */ 519 if (pdev->pdev_comp_priv_obj[id] != NULL) { 520 wlan_pdev_obj_unlock(pdev); 521 return QDF_STATUS_E_FAILURE; 522 } 523 wlan_pdev_obj_unlock(pdev); 524 525 /* Invoke registered create handlers */ 526 handler = g_umac_glb_obj->pdev_create_handler[id]; 527 arg = g_umac_glb_obj->pdev_create_handler_arg[id]; 528 if (handler != NULL) 529 pdev->obj_status[id] = handler(pdev, arg); 530 else 531 return QDF_STATUS_E_FAILURE; 532 /* If object status is created, then only handle this object status */ 533 if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) { 534 /* Derive object status */ 535 obj_status = wlan_objmgr_pdev_object_status(pdev); 536 /* Move PDEV object state to Partially created state */ 537 if (obj_status == QDF_STATUS_COMP_ASYNC) { 538 /*TODO atomic */ 539 pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 540 } 541 } 542 return obj_status; 543 } 544 545 QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion( 546 struct wlan_objmgr_pdev *pdev, 547 enum wlan_umac_comp_id id) 548 { 549 wlan_objmgr_pdev_destroy_handler handler; 550 void *arg; 551 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 552 553 /* component id is invalid */ 554 if (id >= WLAN_UMAC_MAX_COMPONENTS) 555 return QDF_STATUS_MAXCOMP_FAIL; 556 557 wlan_pdev_obj_lock(pdev); 558 /* Component object was never created, invalid operation */ 559 if (pdev->pdev_comp_priv_obj[id] == NULL) { 560 wlan_pdev_obj_unlock(pdev); 561 return QDF_STATUS_E_FAILURE; 562 } 563 wlan_pdev_obj_unlock(pdev); 564 565 /* Invoke registered create handlers */ 566 handler = g_umac_glb_obj->pdev_destroy_handler[id]; 567 arg = g_umac_glb_obj->pdev_destroy_handler_arg[id]; 568 if (handler != NULL) 569 pdev->obj_status[id] = handler(pdev, arg); 570 else 571 return QDF_STATUS_E_FAILURE; 572 573 /* If object status is created, then only handle this object status */ 574 if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) { 575 obj_status = wlan_objmgr_pdev_object_status(pdev); 576 /* move object state to DEL progress */ 577 if (obj_status == QDF_STATUS_COMP_ASYNC) 578 pdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 579 } 580 return obj_status; 581 } 582 583 static void wlan_obj_pdev_vdevlist_add_tail(qdf_list_t *obj_list, 584 struct wlan_objmgr_vdev *obj) 585 { 586 qdf_list_insert_back(obj_list, &obj->vdev_node); 587 } 588 589 static QDF_STATUS wlan_obj_pdev_vdevlist_remove_vdev( 590 qdf_list_t *obj_list, 591 struct wlan_objmgr_vdev *vdev) 592 { 593 qdf_list_node_t *vdev_node = NULL; 594 595 if (vdev == NULL) 596 return QDF_STATUS_E_FAILURE; 597 /* get vdev list node element */ 598 vdev_node = &vdev->vdev_node; 599 /* list is empty, return failure */ 600 if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) 601 return QDF_STATUS_E_FAILURE; 602 603 return QDF_STATUS_SUCCESS; 604 } 605 606 QDF_STATUS wlan_objmgr_pdev_vdev_attach(struct wlan_objmgr_pdev *pdev, 607 struct wlan_objmgr_vdev *vdev) 608 { 609 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 610 611 wlan_pdev_obj_lock(pdev); 612 /* If Max vdev count exceeds, return failure */ 613 if (objmgr->wlan_vdev_count > objmgr->max_vdev_count) { 614 wlan_pdev_obj_unlock(pdev); 615 return QDF_STATUS_E_FAILURE; 616 } 617 /* Add vdev to pdev's vdev list */ 618 wlan_obj_pdev_vdevlist_add_tail(&objmgr->wlan_vdev_list, vdev); 619 /* Increment pdev ref count to make sure it won't be destroyed before */ 620 wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID); 621 /* Increment vdev count of pdev */ 622 objmgr->wlan_vdev_count++; 623 wlan_pdev_obj_unlock(pdev); 624 625 return QDF_STATUS_SUCCESS; 626 } 627 628 QDF_STATUS wlan_objmgr_pdev_vdev_detach(struct wlan_objmgr_pdev *pdev, 629 struct wlan_objmgr_vdev *vdev) 630 { 631 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 632 633 wlan_pdev_obj_lock(pdev); 634 /* if vdev count is 0, return failure */ 635 if (objmgr->wlan_vdev_count == 0) { 636 wlan_pdev_obj_unlock(pdev); 637 return QDF_STATUS_E_FAILURE; 638 } 639 /* remove vdev from pdev's vdev list */ 640 wlan_obj_pdev_vdevlist_remove_vdev(&objmgr->wlan_vdev_list, vdev); 641 /* decrement vdev count */ 642 objmgr->wlan_vdev_count--; 643 wlan_pdev_obj_unlock(pdev); 644 /* Decrement pdev ref count since vdev is releasing reference */ 645 wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID); 646 return QDF_STATUS_SUCCESS; 647 } 648 649 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( 650 struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 651 wlan_objmgr_ref_dbgid dbg_id) 652 { 653 struct wlan_objmgr_vdev *vdev; 654 struct wlan_objmgr_vdev *vdev_next; 655 struct wlan_objmgr_pdev_objmgr *objmgr; 656 qdf_list_t *vdev_list; 657 658 wlan_pdev_obj_lock(pdev); 659 660 objmgr = &pdev->pdev_objmgr; 661 vdev_list = &objmgr->wlan_vdev_list; 662 /* Get first vdev */ 663 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 664 /* Iterate through pdev's vdev list, till vdev id matches with 665 entry of vdev list */ 666 while (vdev != NULL) { 667 if (wlan_vdev_get_id(vdev) == vdev_id) { 668 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != 669 QDF_STATUS_SUCCESS) 670 vdev = NULL; 671 672 wlan_pdev_obj_unlock(pdev); 673 return vdev; 674 } 675 /* get next vdev */ 676 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); 677 vdev = vdev_next; 678 } 679 wlan_pdev_obj_unlock(pdev); 680 return NULL; 681 } 682 qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev); 683 684 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( 685 struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 686 wlan_objmgr_ref_dbgid dbg_id) 687 { 688 struct wlan_objmgr_vdev *vdev; 689 struct wlan_objmgr_vdev *vdev_next; 690 struct wlan_objmgr_pdev_objmgr *objmgr; 691 qdf_list_t *vdev_list; 692 693 wlan_pdev_obj_lock(pdev); 694 695 objmgr = &pdev->pdev_objmgr; 696 vdev_list = &objmgr->wlan_vdev_list; 697 /* Get first vdev */ 698 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 699 /** 700 * Iterate through pdev's vdev list, till vdev id matches with 701 * entry of vdev list 702 */ 703 while (vdev != NULL) { 704 if (wlan_vdev_get_id(vdev) == vdev_id) { 705 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 706 wlan_pdev_obj_unlock(pdev); 707 708 return vdev; 709 } 710 /* get next vdev */ 711 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); 712 vdev = vdev_next; 713 } 714 wlan_pdev_obj_unlock(pdev); 715 716 return NULL; 717 } 718 qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev_no_state); 719 720 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( 721 struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, 722 wlan_objmgr_ref_dbgid dbg_id) 723 { 724 struct wlan_objmgr_vdev *vdev; 725 struct wlan_objmgr_vdev *vdev_next; 726 struct wlan_objmgr_pdev_objmgr *objmgr; 727 qdf_list_t *vdev_list; 728 729 wlan_pdev_obj_lock(pdev); 730 objmgr = &pdev->pdev_objmgr; 731 vdev_list = &objmgr->wlan_vdev_list; 732 /* Get first vdev */ 733 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 734 /* Iterate through pdev's vdev list, till vdev macaddr matches with 735 entry of vdev list */ 736 while (vdev != NULL) { 737 if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) 738 == QDF_STATUS_SUCCESS) { 739 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != 740 QDF_STATUS_SUCCESS) 741 vdev = NULL; 742 743 wlan_pdev_obj_unlock(pdev); 744 return vdev; 745 } 746 /* get next vdev */ 747 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); 748 vdev = vdev_next; 749 } 750 wlan_pdev_obj_unlock(pdev); 751 752 return NULL; 753 } 754 755 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( 756 struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, 757 wlan_objmgr_ref_dbgid dbg_id) 758 { 759 struct wlan_objmgr_vdev *vdev; 760 struct wlan_objmgr_vdev *vdev_next; 761 struct wlan_objmgr_pdev_objmgr *objmgr; 762 qdf_list_t *vdev_list; 763 764 wlan_pdev_obj_lock(pdev); 765 objmgr = &pdev->pdev_objmgr; 766 vdev_list = &objmgr->wlan_vdev_list; 767 /* Get first vdev */ 768 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 769 /* Iterate through pdev's vdev list, till vdev macaddr matches with 770 entry of vdev list */ 771 while (vdev != NULL) { 772 if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) 773 == QDF_STATUS_SUCCESS) { 774 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 775 wlan_pdev_obj_unlock(pdev); 776 777 return vdev; 778 } 779 /* get next vdev */ 780 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); 781 vdev = vdev_next; 782 } 783 wlan_pdev_obj_unlock(pdev); 784 785 return NULL; 786 } 787 788 void *wlan_objmgr_pdev_get_comp_private_obj( 789 struct wlan_objmgr_pdev *pdev, 790 enum wlan_umac_comp_id id) 791 { 792 void *comp_priv_obj; 793 794 /* component id is invalid */ 795 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 796 QDF_BUG(0); 797 return NULL; 798 } 799 800 if (pdev == NULL) { 801 QDF_BUG(0); 802 return NULL; 803 } 804 805 comp_priv_obj = pdev->pdev_comp_priv_obj[id]; 806 807 return comp_priv_obj; 808 } 809 qdf_export_symbol(wlan_objmgr_pdev_get_comp_private_obj); 810 811 void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev, 812 wlan_objmgr_ref_dbgid id) 813 { 814 if (pdev == NULL) { 815 obj_mgr_err("pdev obj is NULL"); 816 QDF_ASSERT(0); 817 return; 818 } 819 qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt); 820 qdf_atomic_inc(&pdev->pdev_objmgr.ref_id_dbg[id]); 821 822 return; 823 } 824 qdf_export_symbol(wlan_objmgr_pdev_get_ref); 825 826 QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev, 827 wlan_objmgr_ref_dbgid id) 828 { 829 uint8_t pdev_id; 830 831 if (pdev == NULL) { 832 obj_mgr_err("pdev obj is NULL"); 833 QDF_ASSERT(0); 834 return QDF_STATUS_E_FAILURE; 835 } 836 837 wlan_pdev_obj_lock(pdev); 838 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 839 if (pdev->obj_state != WLAN_OBJ_STATE_CREATED) { 840 wlan_pdev_obj_unlock(pdev); 841 if (pdev->pdev_objmgr.print_cnt++ <= 842 WLAN_OBJMGR_RATELIMIT_THRESH) 843 obj_mgr_err( 844 "[Ref id: %d] pdev [%d] is not in Created(st:%d)", 845 id, pdev_id, pdev->obj_state); 846 return QDF_STATUS_E_RESOURCES; 847 } 848 849 wlan_objmgr_pdev_get_ref(pdev, id); 850 wlan_pdev_obj_unlock(pdev); 851 852 return QDF_STATUS_SUCCESS; 853 } 854 qdf_export_symbol(wlan_objmgr_pdev_try_get_ref); 855 856 void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev, 857 wlan_objmgr_ref_dbgid id) 858 { 859 uint8_t pdev_id; 860 861 if (pdev == NULL) { 862 obj_mgr_err("pdev obj is NULL"); 863 QDF_ASSERT(0); 864 return; 865 } 866 867 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 868 869 if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_id_dbg[id])) { 870 obj_mgr_err("pdev (id:%d)ref cnt was not taken by %d", 871 pdev_id, id); 872 wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg); 873 WLAN_OBJMGR_BUG(0); 874 } 875 876 if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) { 877 obj_mgr_err("pdev ref cnt is 0: pdev-id:%d", pdev_id); 878 WLAN_OBJMGR_BUG(0); 879 return; 880 } 881 882 qdf_atomic_dec(&pdev->pdev_objmgr.ref_id_dbg[id]); 883 /* Decrement ref count, free pdev, if ref count == 0 */ 884 if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt)) 885 wlan_objmgr_pdev_obj_destroy(pdev); 886 887 return; 888 } 889 qdf_export_symbol(wlan_objmgr_pdev_release_ref); 890 891 struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev( 892 struct wlan_objmgr_pdev *pdev, 893 wlan_objmgr_ref_dbgid dbg_id) 894 { 895 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 896 qdf_list_t *vdev_list = NULL; 897 struct wlan_objmgr_vdev *vdev; 898 qdf_list_node_t *node = NULL; 899 qdf_list_node_t *prev_node = NULL; 900 901 wlan_pdev_obj_lock(pdev); 902 903 /* VDEV list */ 904 vdev_list = &objmgr->wlan_vdev_list; 905 if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { 906 wlan_pdev_obj_unlock(pdev); 907 return NULL; 908 } 909 910 do { 911 vdev = qdf_container_of(node, struct wlan_objmgr_vdev, 912 vdev_node); 913 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 914 QDF_STATUS_SUCCESS) { 915 wlan_pdev_obj_unlock(pdev); 916 return vdev; 917 } 918 919 prev_node = node; 920 } while (qdf_list_peek_next(vdev_list, prev_node, &node) == 921 QDF_STATUS_SUCCESS); 922 923 wlan_pdev_obj_unlock(pdev); 924 925 return NULL; 926 } 927 928 qdf_export_symbol(wlan_objmgr_pdev_get_first_vdev); 929