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