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 /* Get peer list of the vdev */ 415 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 416 if (peer_list != NULL) { 417 peer = wlan_vdev_peer_list_peek_active_head(vdev, peer_list, 418 dbg_id); 419 while (peer != NULL) { 420 /* Invoke the handler */ 421 handler(pdev, (void *)peer, arg); 422 /* Get next peer pointer, increments the ref count */ 423 peer_next = wlan_peer_get_next_active_peer_of_vdev(vdev, 424 peer_list, peer, dbg_id); 425 wlan_objmgr_peer_release_ref(peer, dbg_id); 426 peer = peer_next; 427 } 428 } 429 } 430 431 QDF_STATUS wlan_objmgr_pdev_iterate_obj_list( 432 struct wlan_objmgr_pdev *pdev, 433 enum wlan_objmgr_obj_type obj_type, 434 wlan_objmgr_pdev_op_handler handler, 435 void *arg, uint8_t lock_free_op, 436 wlan_objmgr_ref_dbgid dbg_id) 437 { 438 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 439 qdf_list_t *vdev_list = NULL; 440 struct wlan_objmgr_vdev *vdev = NULL; 441 struct wlan_objmgr_vdev *vdev_next = NULL; 442 443 /* VDEV list */ 444 vdev_list = &objmgr->wlan_vdev_list; 445 446 switch (obj_type) { 447 case WLAN_VDEV_OP: 448 /* Iterate through all VDEV object, and invoke handler for each 449 VDEV object */ 450 vdev = wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list, 451 dbg_id); 452 while (vdev != NULL) { 453 handler(pdev, (void *)vdev, arg); 454 /* Get next vdev, it increments ref of next vdev */ 455 vdev_next = wlan_vdev_get_next_active_vdev_of_pdev( 456 pdev, vdev_list, vdev, dbg_id); 457 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 458 vdev = vdev_next; 459 } 460 break; 461 case WLAN_PEER_OP: 462 vdev = wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list, 463 dbg_id); 464 while (vdev != NULL) { 465 wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev, handler, 466 arg, lock_free_op, dbg_id); 467 /* Get next vdev, it increments ref of next vdev */ 468 vdev_next = wlan_vdev_get_next_active_vdev_of_pdev( 469 pdev, vdev_list, vdev, dbg_id); 470 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 471 vdev = vdev_next; 472 } 473 break; 474 default: 475 break; 476 } 477 478 return QDF_STATUS_SUCCESS; 479 } 480 qdf_export_symbol(wlan_objmgr_pdev_iterate_obj_list); 481 482 QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_creation( 483 struct wlan_objmgr_pdev *pdev, 484 enum wlan_umac_comp_id id) 485 { 486 wlan_objmgr_pdev_create_handler handler; 487 void *arg; 488 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 489 490 /* Component id is invalid */ 491 if (id >= WLAN_UMAC_MAX_COMPONENTS) 492 return QDF_STATUS_MAXCOMP_FAIL; 493 494 wlan_pdev_obj_lock(pdev); 495 /* If component object is already created, delete old 496 component object, then invoke creation */ 497 if (pdev->pdev_comp_priv_obj[id] != NULL) { 498 wlan_pdev_obj_unlock(pdev); 499 return QDF_STATUS_E_FAILURE; 500 } 501 wlan_pdev_obj_unlock(pdev); 502 503 /* Invoke registered create handlers */ 504 handler = g_umac_glb_obj->pdev_create_handler[id]; 505 arg = g_umac_glb_obj->pdev_create_handler_arg[id]; 506 if (handler != NULL) 507 pdev->obj_status[id] = handler(pdev, arg); 508 else 509 return QDF_STATUS_E_FAILURE; 510 /* If object status is created, then only handle this object status */ 511 if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) { 512 /* Derive object status */ 513 obj_status = wlan_objmgr_pdev_object_status(pdev); 514 /* Move PDEV object state to Partially created state */ 515 if (obj_status == QDF_STATUS_COMP_ASYNC) { 516 /*TODO atomic */ 517 pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 518 } 519 } 520 return obj_status; 521 } 522 523 QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion( 524 struct wlan_objmgr_pdev *pdev, 525 enum wlan_umac_comp_id id) 526 { 527 wlan_objmgr_pdev_destroy_handler handler; 528 void *arg; 529 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 530 531 /* component id is invalid */ 532 if (id >= WLAN_UMAC_MAX_COMPONENTS) 533 return QDF_STATUS_MAXCOMP_FAIL; 534 535 wlan_pdev_obj_lock(pdev); 536 /* Component object was never created, invalid operation */ 537 if (pdev->pdev_comp_priv_obj[id] == NULL) { 538 wlan_pdev_obj_unlock(pdev); 539 return QDF_STATUS_E_FAILURE; 540 } 541 wlan_pdev_obj_unlock(pdev); 542 543 /* Invoke registered create handlers */ 544 handler = g_umac_glb_obj->pdev_destroy_handler[id]; 545 arg = g_umac_glb_obj->pdev_destroy_handler_arg[id]; 546 if (handler != NULL) 547 pdev->obj_status[id] = handler(pdev, arg); 548 else 549 return QDF_STATUS_E_FAILURE; 550 551 /* If object status is created, then only handle this object status */ 552 if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) { 553 obj_status = wlan_objmgr_pdev_object_status(pdev); 554 /* move object state to DEL progress */ 555 if (obj_status == QDF_STATUS_COMP_ASYNC) 556 pdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 557 } 558 return obj_status; 559 } 560 561 static void wlan_obj_pdev_vdevlist_add_tail(qdf_list_t *obj_list, 562 struct wlan_objmgr_vdev *obj) 563 { 564 qdf_list_insert_back(obj_list, &obj->vdev_node); 565 } 566 567 static QDF_STATUS wlan_obj_pdev_vdevlist_remove_vdev( 568 qdf_list_t *obj_list, 569 struct wlan_objmgr_vdev *vdev) 570 { 571 qdf_list_node_t *vdev_node = NULL; 572 573 if (vdev == NULL) 574 return QDF_STATUS_E_FAILURE; 575 /* get vdev list node element */ 576 vdev_node = &vdev->vdev_node; 577 /* list is empty, return failure */ 578 if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) 579 return QDF_STATUS_E_FAILURE; 580 581 return QDF_STATUS_SUCCESS; 582 } 583 584 QDF_STATUS wlan_objmgr_pdev_vdev_attach(struct wlan_objmgr_pdev *pdev, 585 struct wlan_objmgr_vdev *vdev) 586 { 587 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 588 589 wlan_pdev_obj_lock(pdev); 590 /* If Max vdev count exceeds, return failure */ 591 if (objmgr->wlan_vdev_count > objmgr->max_vdev_count) { 592 wlan_pdev_obj_unlock(pdev); 593 return QDF_STATUS_E_FAILURE; 594 } 595 /* Add vdev to pdev's vdev list */ 596 wlan_obj_pdev_vdevlist_add_tail(&objmgr->wlan_vdev_list, vdev); 597 /* Increment pdev ref count to make sure it won't be destroyed before */ 598 wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID); 599 /* Increment vdev count of pdev */ 600 objmgr->wlan_vdev_count++; 601 wlan_pdev_obj_unlock(pdev); 602 603 return QDF_STATUS_SUCCESS; 604 } 605 606 QDF_STATUS wlan_objmgr_pdev_vdev_detach(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 vdev count is 0, return failure */ 613 if (objmgr->wlan_vdev_count == 0) { 614 wlan_pdev_obj_unlock(pdev); 615 return QDF_STATUS_E_FAILURE; 616 } 617 /* remove vdev from pdev's vdev list */ 618 wlan_obj_pdev_vdevlist_remove_vdev(&objmgr->wlan_vdev_list, vdev); 619 /* decrement vdev count */ 620 objmgr->wlan_vdev_count--; 621 wlan_pdev_obj_unlock(pdev); 622 /* Decrement pdev ref count since vdev is releasing reference */ 623 wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID); 624 return QDF_STATUS_SUCCESS; 625 } 626 627 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( 628 struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 629 wlan_objmgr_ref_dbgid dbg_id) 630 { 631 struct wlan_objmgr_vdev *vdev; 632 struct wlan_objmgr_vdev *vdev_next; 633 struct wlan_objmgr_pdev_objmgr *objmgr; 634 qdf_list_t *vdev_list; 635 636 wlan_pdev_obj_lock(pdev); 637 638 objmgr = &pdev->pdev_objmgr; 639 vdev_list = &objmgr->wlan_vdev_list; 640 /* Get first vdev */ 641 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 642 /* Iterate through pdev's vdev list, till vdev id matches with 643 entry of vdev list */ 644 while (vdev != NULL) { 645 if (wlan_vdev_get_id(vdev) == vdev_id) { 646 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != 647 QDF_STATUS_SUCCESS) 648 vdev = NULL; 649 650 wlan_pdev_obj_unlock(pdev); 651 return vdev; 652 } 653 /* get next vdev */ 654 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); 655 vdev = vdev_next; 656 } 657 wlan_pdev_obj_unlock(pdev); 658 return NULL; 659 } 660 qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev); 661 662 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( 663 struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 664 wlan_objmgr_ref_dbgid dbg_id) 665 { 666 struct wlan_objmgr_vdev *vdev; 667 struct wlan_objmgr_vdev *vdev_next; 668 struct wlan_objmgr_pdev_objmgr *objmgr; 669 qdf_list_t *vdev_list; 670 671 wlan_pdev_obj_lock(pdev); 672 673 objmgr = &pdev->pdev_objmgr; 674 vdev_list = &objmgr->wlan_vdev_list; 675 /* Get first vdev */ 676 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 677 /** 678 * Iterate through pdev's vdev list, till vdev id matches with 679 * entry of vdev list 680 */ 681 while (vdev != NULL) { 682 if (wlan_vdev_get_id(vdev) == vdev_id) { 683 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 684 wlan_pdev_obj_unlock(pdev); 685 686 return vdev; 687 } 688 /* get next vdev */ 689 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); 690 vdev = vdev_next; 691 } 692 wlan_pdev_obj_unlock(pdev); 693 694 return NULL; 695 } 696 qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev_no_state); 697 698 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( 699 struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, 700 wlan_objmgr_ref_dbgid dbg_id) 701 { 702 struct wlan_objmgr_vdev *vdev; 703 struct wlan_objmgr_vdev *vdev_next; 704 struct wlan_objmgr_pdev_objmgr *objmgr; 705 qdf_list_t *vdev_list; 706 707 wlan_pdev_obj_lock(pdev); 708 objmgr = &pdev->pdev_objmgr; 709 vdev_list = &objmgr->wlan_vdev_list; 710 /* Get first vdev */ 711 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 712 /* Iterate through pdev's vdev list, till vdev macaddr matches with 713 entry of vdev list */ 714 while (vdev != NULL) { 715 if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) 716 == QDF_STATUS_SUCCESS) { 717 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != 718 QDF_STATUS_SUCCESS) 719 vdev = NULL; 720 721 wlan_pdev_obj_unlock(pdev); 722 return vdev; 723 } 724 /* get next vdev */ 725 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); 726 vdev = vdev_next; 727 } 728 wlan_pdev_obj_unlock(pdev); 729 730 return NULL; 731 } 732 733 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( 734 struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, 735 wlan_objmgr_ref_dbgid dbg_id) 736 { 737 struct wlan_objmgr_vdev *vdev; 738 struct wlan_objmgr_vdev *vdev_next; 739 struct wlan_objmgr_pdev_objmgr *objmgr; 740 qdf_list_t *vdev_list; 741 742 wlan_pdev_obj_lock(pdev); 743 objmgr = &pdev->pdev_objmgr; 744 vdev_list = &objmgr->wlan_vdev_list; 745 /* Get first vdev */ 746 vdev = wlan_pdev_vdev_list_peek_head(vdev_list); 747 /* Iterate through pdev's vdev list, till vdev macaddr matches with 748 entry of vdev list */ 749 while (vdev != NULL) { 750 if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) 751 == QDF_STATUS_SUCCESS) { 752 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 753 wlan_pdev_obj_unlock(pdev); 754 755 return vdev; 756 } 757 /* get next vdev */ 758 vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); 759 vdev = vdev_next; 760 } 761 wlan_pdev_obj_unlock(pdev); 762 763 return NULL; 764 } 765 766 void *wlan_objmgr_pdev_get_comp_private_obj( 767 struct wlan_objmgr_pdev *pdev, 768 enum wlan_umac_comp_id id) 769 { 770 void *comp_priv_obj; 771 772 /* component id is invalid */ 773 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 774 QDF_BUG(0); 775 return NULL; 776 } 777 778 if (pdev == NULL) { 779 QDF_BUG(0); 780 return NULL; 781 } 782 783 comp_priv_obj = pdev->pdev_comp_priv_obj[id]; 784 785 return comp_priv_obj; 786 } 787 qdf_export_symbol(wlan_objmgr_pdev_get_comp_private_obj); 788 789 void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev, 790 wlan_objmgr_ref_dbgid id) 791 { 792 if (pdev == NULL) { 793 obj_mgr_err("pdev obj is NULL"); 794 QDF_ASSERT(0); 795 return; 796 } 797 qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt); 798 qdf_atomic_inc(&pdev->pdev_objmgr.ref_id_dbg[id]); 799 800 return; 801 } 802 qdf_export_symbol(wlan_objmgr_pdev_get_ref); 803 804 QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev, 805 wlan_objmgr_ref_dbgid id) 806 { 807 uint8_t pdev_id; 808 809 if (pdev == NULL) { 810 obj_mgr_err("pdev obj is NULL"); 811 QDF_ASSERT(0); 812 return QDF_STATUS_E_FAILURE; 813 } 814 815 wlan_pdev_obj_lock(pdev); 816 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 817 if (pdev->obj_state != WLAN_OBJ_STATE_CREATED) { 818 wlan_pdev_obj_unlock(pdev); 819 if (pdev->pdev_objmgr.print_cnt++ <= 820 WLAN_OBJMGR_RATELIMIT_THRESH) 821 obj_mgr_err( 822 "[Ref id: %d] pdev [%d] is not in Created(st:%d)", 823 id, pdev_id, pdev->obj_state); 824 return QDF_STATUS_E_RESOURCES; 825 } 826 827 wlan_objmgr_pdev_get_ref(pdev, id); 828 wlan_pdev_obj_unlock(pdev); 829 830 return QDF_STATUS_SUCCESS; 831 } 832 qdf_export_symbol(wlan_objmgr_pdev_try_get_ref); 833 834 void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev, 835 wlan_objmgr_ref_dbgid id) 836 { 837 uint8_t pdev_id; 838 839 if (pdev == NULL) { 840 obj_mgr_err("pdev obj is NULL"); 841 QDF_ASSERT(0); 842 return; 843 } 844 845 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 846 847 if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_id_dbg[id])) { 848 obj_mgr_err("pdev (id:%d)ref cnt was not taken by %d", 849 pdev_id, id); 850 wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg); 851 WLAN_OBJMGR_BUG(0); 852 } 853 854 if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) { 855 obj_mgr_err("pdev ref cnt is 0: pdev-id:%d", pdev_id); 856 WLAN_OBJMGR_BUG(0); 857 return; 858 } 859 860 qdf_atomic_dec(&pdev->pdev_objmgr.ref_id_dbg[id]); 861 /* Decrement ref count, free pdev, if ref count == 0 */ 862 if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt)) 863 wlan_objmgr_pdev_obj_destroy(pdev); 864 865 return; 866 } 867 qdf_export_symbol(wlan_objmgr_pdev_release_ref); 868 869 struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev( 870 struct wlan_objmgr_pdev *pdev, 871 wlan_objmgr_ref_dbgid dbg_id) 872 { 873 struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; 874 qdf_list_t *vdev_list = NULL; 875 struct wlan_objmgr_vdev *vdev; 876 qdf_list_node_t *node = NULL; 877 qdf_list_node_t *prev_node = NULL; 878 879 wlan_pdev_obj_lock(pdev); 880 881 /* VDEV list */ 882 vdev_list = &objmgr->wlan_vdev_list; 883 if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { 884 wlan_pdev_obj_unlock(pdev); 885 return NULL; 886 } 887 888 do { 889 vdev = qdf_container_of(node, struct wlan_objmgr_vdev, 890 vdev_node); 891 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 892 QDF_STATUS_SUCCESS) { 893 wlan_pdev_obj_unlock(pdev); 894 return vdev; 895 } 896 897 prev_node = node; 898 } while (qdf_list_peek_next(vdev_list, prev_node, &node) == 899 QDF_STATUS_SUCCESS); 900 901 wlan_pdev_obj_unlock(pdev); 902 903 return NULL; 904 } 905 906 qdf_export_symbol(wlan_objmgr_pdev_get_first_vdev); 907