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