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