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