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