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