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