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 #include "wlan_objmgr_vdev_obj_i.h" 33 34 /** 35 ** APIs to Create/Delete Global object APIs 36 */ 37 38 static QDF_STATUS wlan_objmgr_vdev_object_status( 39 struct wlan_objmgr_vdev *vdev) 40 { 41 uint8_t id; 42 QDF_STATUS status = QDF_STATUS_SUCCESS; 43 44 wlan_vdev_obj_lock(vdev); 45 46 /* Iterate through all components to derive the object status */ 47 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 48 /* If component disabled, Ignore */ 49 if (vdev->obj_status[id] == QDF_STATUS_COMP_DISABLED) { 50 continue; 51 /* 52 * If component operates in Async, status is Partially created, 53 * break 54 */ 55 } else if (vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC) { 56 if (vdev->vdev_comp_priv_obj[id] == NULL) { 57 status = QDF_STATUS_COMP_ASYNC; 58 break; 59 } 60 /* 61 * If component failed to allocate its object, treat it as 62 * failure, complete object need to be cleaned up 63 */ 64 } else if ((vdev->obj_status[id] == QDF_STATUS_E_NOMEM) || 65 (vdev->obj_status[id] == QDF_STATUS_E_FAILURE)) { 66 status = QDF_STATUS_E_FAILURE; 67 break; 68 } 69 } 70 wlan_vdev_obj_unlock(vdev); 71 72 return status; 73 } 74 75 static QDF_STATUS wlan_objmgr_vdev_obj_free(struct wlan_objmgr_vdev *vdev) 76 { 77 struct wlan_objmgr_pdev *pdev; 78 struct wlan_objmgr_psoc *psoc; 79 80 if (vdev == NULL) { 81 obj_mgr_err("vdev is NULL"); 82 return QDF_STATUS_E_FAILURE; 83 } 84 /* if PDEV is NULL, return */ 85 pdev = wlan_vdev_get_pdev(vdev); 86 if (pdev == NULL) { 87 obj_mgr_err("pdev is NULL for vdev-id: %d", 88 vdev->vdev_objmgr.vdev_id); 89 return QDF_STATUS_E_FAILURE; 90 } 91 psoc = wlan_pdev_get_psoc(pdev); 92 if (psoc == NULL) { 93 obj_mgr_err("psoc is NULL in pdev"); 94 return QDF_STATUS_E_FAILURE; 95 } 96 97 /* Detach VDEV from PDEV VDEV's list */ 98 if (wlan_objmgr_pdev_vdev_detach(pdev, vdev) == 99 QDF_STATUS_E_FAILURE) 100 return QDF_STATUS_E_FAILURE; 101 102 /* Detach VDEV from PSOC VDEV's list */ 103 if (wlan_objmgr_psoc_vdev_detach(psoc, vdev) == 104 QDF_STATUS_E_FAILURE) 105 return QDF_STATUS_E_FAILURE; 106 107 qdf_spinlock_destroy(&vdev->vdev_lock); 108 109 qdf_mem_free(vdev->vdev_mlme.bss_chan); 110 qdf_mem_free(vdev->vdev_mlme.des_chan); 111 qdf_mem_free(vdev); 112 113 return QDF_STATUS_SUCCESS; 114 115 } 116 117 struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( 118 struct wlan_objmgr_pdev *pdev, 119 struct wlan_vdev_create_params *params) 120 { 121 struct wlan_objmgr_vdev *vdev; 122 struct wlan_objmgr_psoc *psoc; 123 uint8_t id; 124 wlan_objmgr_vdev_create_handler handler; 125 wlan_objmgr_vdev_status_handler stat_handler; 126 void *arg; 127 QDF_STATUS obj_status; 128 129 if (pdev == NULL) { 130 obj_mgr_err("pdev is NULL"); 131 return NULL; 132 } 133 psoc = wlan_pdev_get_psoc(pdev); 134 /* PSOC is NULL */ 135 if (psoc == NULL) { 136 obj_mgr_err("psoc is NULL for pdev-id:%d", 137 pdev->pdev_objmgr.wlan_pdev_id); 138 return NULL; 139 } 140 /* Allocate vdev object memory */ 141 vdev = qdf_mem_malloc(sizeof(*vdev)); 142 if (vdev == NULL) { 143 obj_mgr_err("Memory allocation failure"); 144 return NULL; 145 } 146 vdev->obj_state = WLAN_OBJ_STATE_ALLOCATED; 147 148 vdev->vdev_mlme.bss_chan = (struct wlan_channel *)qdf_mem_malloc( 149 sizeof(struct wlan_channel)); 150 if (vdev->vdev_mlme.bss_chan == NULL) { 151 QDF_TRACE(QDF_MODULE_ID_MLME, QDF_TRACE_LEVEL_ERROR, 152 "%s:bss_chan is NULL", __func__); 153 qdf_mem_free(vdev); 154 return NULL; 155 } 156 157 vdev->vdev_mlme.des_chan = (struct wlan_channel *)qdf_mem_malloc( 158 sizeof(struct wlan_channel)); 159 if (vdev->vdev_mlme.des_chan == NULL) { 160 QDF_TRACE(QDF_MODULE_ID_MLME, QDF_TRACE_LEVEL_ERROR, 161 "%s:des_chan is NULL", __func__); 162 qdf_mem_free(vdev->vdev_mlme.bss_chan); 163 qdf_mem_free(vdev); 164 return NULL; 165 } 166 167 /* Initialize spinlock */ 168 qdf_spinlock_create(&vdev->vdev_lock); 169 /* Attach VDEV to PSOC VDEV's list */ 170 if (wlan_objmgr_psoc_vdev_attach(psoc, vdev) != 171 QDF_STATUS_SUCCESS) { 172 obj_mgr_err("psoc vdev attach failed for vdev-id:%d", 173 vdev->vdev_objmgr.vdev_id); 174 qdf_mem_free(vdev->vdev_mlme.bss_chan); 175 qdf_mem_free(vdev->vdev_mlme.des_chan); 176 qdf_spinlock_destroy(&vdev->vdev_lock); 177 qdf_mem_free(vdev); 178 return NULL; 179 } 180 /* Store pdev in vdev */ 181 wlan_vdev_set_pdev(vdev, pdev); 182 /* Attach vdev to PDEV */ 183 if (wlan_objmgr_pdev_vdev_attach(pdev, vdev) != 184 QDF_STATUS_SUCCESS) { 185 obj_mgr_err("pdev vdev attach failed for vdev-id:%d", 186 vdev->vdev_objmgr.vdev_id); 187 wlan_objmgr_psoc_vdev_detach(psoc, vdev); 188 qdf_mem_free(vdev->vdev_mlme.bss_chan); 189 qdf_mem_free(vdev->vdev_mlme.des_chan); 190 qdf_spinlock_destroy(&vdev->vdev_lock); 191 qdf_mem_free(vdev); 192 return NULL; 193 } 194 /* set opmode */ 195 wlan_vdev_mlme_set_opmode(vdev, params->opmode); 196 /* set MAC address */ 197 wlan_vdev_mlme_set_macaddr(vdev, params->macaddr); 198 /* set MAT address */ 199 wlan_vdev_mlme_set_mataddr(vdev, params->mataddr); 200 /* Set create flags */ 201 vdev->vdev_objmgr.c_flags = params->flags; 202 /* store os-specific pointer */ 203 vdev->vdev_nif.osdev = params->osifp; 204 /* peer count to 0 */ 205 vdev->vdev_objmgr.wlan_peer_count = 0; 206 qdf_atomic_init(&vdev->vdev_objmgr.ref_cnt); 207 vdev->vdev_objmgr.print_cnt = 0; 208 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); 209 /* Initialize max peer count based on opmode type */ 210 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) 211 vdev->vdev_objmgr.max_peer_count = WLAN_UMAC_MAX_STA_PEERS; 212 else 213 vdev->vdev_objmgr.max_peer_count = 214 wlan_pdev_get_max_peer_count(pdev); 215 216 /* Initialize peer list */ 217 qdf_list_create(&vdev->vdev_objmgr.wlan_peer_list, 218 vdev->vdev_objmgr.max_peer_count + 219 WLAN_MAX_PDEV_TEMP_PEERS); 220 /* TODO init other parameters */ 221 222 /* Invoke registered create handlers */ 223 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 224 handler = g_umac_glb_obj->vdev_create_handler[id]; 225 arg = g_umac_glb_obj->vdev_create_handler_arg[id]; 226 if (handler != NULL) 227 vdev->obj_status[id] = handler(vdev, arg); 228 else 229 vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 230 } 231 232 /* Derive object status */ 233 obj_status = wlan_objmgr_vdev_object_status(vdev); 234 235 if (obj_status == QDF_STATUS_SUCCESS) { 236 /* Object status is SUCCESS, Object is created */ 237 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 238 /* Invoke component registered status handlers */ 239 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 240 stat_handler = g_umac_glb_obj->vdev_status_handler[id]; 241 arg = g_umac_glb_obj->vdev_status_handler_arg[id]; 242 if (stat_handler != NULL) { 243 stat_handler(vdev, arg, 244 QDF_STATUS_SUCCESS); 245 } 246 } 247 /* 248 * Few components operates in Asynchrous communction, Object state 249 * partially created 250 */ 251 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 252 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 253 /* Component object failed to be created, clean up the object */ 254 } else if (obj_status == QDF_STATUS_E_FAILURE) { 255 /* Clean up the psoc */ 256 wlan_objmgr_vdev_obj_delete(vdev); 257 obj_mgr_err("VDEV comp objects creation failed for vdev-id:%d", 258 vdev->vdev_objmgr.vdev_id); 259 return NULL; 260 } 261 262 obj_mgr_info("Created vdev %d", vdev->vdev_objmgr.vdev_id); 263 264 return vdev; 265 } 266 qdf_export_symbol(wlan_objmgr_vdev_obj_create); 267 268 static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev) 269 { 270 uint8_t id; 271 wlan_objmgr_vdev_destroy_handler handler; 272 QDF_STATUS obj_status; 273 void *arg; 274 uint8_t vdev_id; 275 276 if (vdev == NULL) { 277 obj_mgr_err("vdev is NULL"); 278 return QDF_STATUS_E_FAILURE; 279 } 280 wlan_objmgr_notify_destroy(vdev, WLAN_VDEV_OP); 281 282 vdev_id = wlan_vdev_get_id(vdev); 283 284 obj_mgr_info("Physically deleting vdev %d", vdev_id); 285 286 if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 287 obj_mgr_err("VDEV object delete is not invoked vdevid:%d objstate:%d", 288 wlan_vdev_get_id(vdev), vdev->obj_state); 289 WLAN_OBJMGR_BUG(0); 290 } 291 292 /* Invoke registered destroy handlers */ 293 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 294 handler = g_umac_glb_obj->vdev_destroy_handler[id]; 295 arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; 296 if (handler != NULL) 297 vdev->obj_status[id] = handler(vdev, arg); 298 else 299 vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 300 } 301 /* Derive object status */ 302 obj_status = wlan_objmgr_vdev_object_status(vdev); 303 304 if (obj_status == QDF_STATUS_E_FAILURE) { 305 obj_mgr_err("VDEV object deletion failed: vdev-id: %d", 306 vdev_id); 307 /* Ideally should not happen */ 308 /* This leads to memleak ??? how to handle */ 309 QDF_BUG(0); 310 return QDF_STATUS_E_FAILURE; 311 } 312 313 /* Deletion is in progress */ 314 if (obj_status == QDF_STATUS_COMP_ASYNC) { 315 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 316 return QDF_STATUS_COMP_ASYNC; 317 } 318 319 /* Free VDEV object */ 320 return wlan_objmgr_vdev_obj_free(vdev); 321 } 322 323 QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) 324 { 325 uint8_t print_idx; 326 327 if (vdev == NULL) { 328 obj_mgr_err("vdev is NULL"); 329 return QDF_STATUS_E_FAILURE; 330 } 331 332 obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id); 333 334 print_idx = qdf_get_pidx(); 335 if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR, 336 QDF_TRACE_LEVEL_DEBUG)) { 337 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg); 338 } 339 340 /* 341 * Update VDEV object state to LOGICALLY DELETED 342 * It prevents further access of this object 343 */ 344 wlan_vdev_obj_lock(vdev); 345 vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 346 wlan_vdev_obj_unlock(vdev); 347 wlan_objmgr_notify_log_delete(vdev, WLAN_VDEV_OP); 348 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 349 350 return QDF_STATUS_SUCCESS; 351 } 352 qdf_export_symbol(wlan_objmgr_vdev_obj_delete); 353 354 /** 355 ** APIs to attach/detach component objects 356 */ 357 QDF_STATUS wlan_objmgr_vdev_component_obj_attach( 358 struct wlan_objmgr_vdev *vdev, 359 enum wlan_umac_comp_id id, 360 void *comp_priv_obj, 361 QDF_STATUS status) 362 { 363 wlan_objmgr_vdev_status_handler stat_handler; 364 void *arg; 365 uint8_t i; 366 QDF_STATUS obj_status; 367 368 /* component id is invalid */ 369 if (id >= WLAN_UMAC_MAX_COMPONENTS) 370 return QDF_STATUS_MAXCOMP_FAIL; 371 372 wlan_vdev_obj_lock(vdev); 373 /* If there is a valid entry, return failure */ 374 if (vdev->vdev_comp_priv_obj[id] != NULL) { 375 wlan_vdev_obj_unlock(vdev); 376 return QDF_STATUS_E_FAILURE; 377 } 378 /* Save component's pointer and status */ 379 vdev->vdev_comp_priv_obj[id] = comp_priv_obj; 380 vdev->obj_status[id] = status; 381 wlan_vdev_obj_unlock(vdev); 382 if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 383 return QDF_STATUS_SUCCESS; 384 /* 385 * If VDEV object status is partially created means, this API is 386 * invoked with differnt context, this block should be executed for 387 * async components only 388 */ 389 /* Derive status */ 390 obj_status = wlan_objmgr_vdev_object_status(vdev); 391 /* STATUS_SUCCESS means, object is CREATED */ 392 if (obj_status == QDF_STATUS_SUCCESS) 393 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 394 /* 395 * update state as CREATION failed, caller has to delete the 396 * VDEV object 397 */ 398 else if (obj_status == QDF_STATUS_E_FAILURE) 399 vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 400 /* Notify components about the CREATION success/failure */ 401 if ((obj_status == QDF_STATUS_SUCCESS) || 402 (obj_status == QDF_STATUS_E_FAILURE)) { 403 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 404 stat_handler = g_umac_glb_obj->vdev_status_handler[i]; 405 arg = g_umac_glb_obj->vdev_status_handler_arg[i]; 406 if (stat_handler != NULL) 407 stat_handler(vdev, arg, obj_status); 408 } 409 } 410 return QDF_STATUS_SUCCESS; 411 } 412 qdf_export_symbol(wlan_objmgr_vdev_component_obj_attach); 413 414 QDF_STATUS wlan_objmgr_vdev_component_obj_detach( 415 struct wlan_objmgr_vdev *vdev, 416 enum wlan_umac_comp_id id, 417 void *comp_priv_obj) 418 { 419 QDF_STATUS obj_status; 420 421 /* component id is invalid */ 422 if (id >= WLAN_UMAC_MAX_COMPONENTS) 423 return QDF_STATUS_MAXCOMP_FAIL; 424 425 wlan_vdev_obj_lock(vdev); 426 /* If there is a valid entry, return failure */ 427 if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) { 428 vdev->obj_status[id] = QDF_STATUS_E_FAILURE; 429 wlan_vdev_obj_unlock(vdev); 430 return QDF_STATUS_E_FAILURE; 431 } 432 /* Reset pointers to NULL, update the status*/ 433 vdev->vdev_comp_priv_obj[id] = NULL; 434 vdev->obj_status[id] = QDF_STATUS_SUCCESS; 435 wlan_vdev_obj_unlock(vdev); 436 437 /** 438 *If VDEV object status is partially destroyed means, this API is 439 * invoked with differnt context, this block should be executed for 440 * async components only 441 */ 442 if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 443 (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 444 /* Derive object status */ 445 obj_status = wlan_objmgr_vdev_object_status(vdev); 446 if (obj_status == QDF_STATUS_SUCCESS) { 447 /* 448 * Update the status as Deleted, if full object 449 * deletion is in progress 450 */ 451 if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 452 vdev->obj_state = WLAN_OBJ_STATE_DELETED; 453 /* 454 * Move to creation state, since this component 455 * deletion alone requested 456 */ 457 else if (vdev->obj_state == 458 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 459 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 460 /* Object status is failure */ 461 } else if (obj_status == QDF_STATUS_E_FAILURE) { 462 /* 463 * Update the status as Deletion failed, if full object 464 * deletion is in progress 465 */ 466 if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 467 vdev->obj_state = 468 WLAN_OBJ_STATE_DELETION_FAILED; 469 /* Move to creation state, since this component 470 deletion alone requested (do not block other 471 components) */ 472 else if (vdev->obj_state == 473 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 474 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 475 } 476 /* Delete vdev object */ 477 if ((obj_status == QDF_STATUS_SUCCESS) && 478 (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) { 479 /* Free VDEV object */ 480 return wlan_objmgr_vdev_obj_free(vdev); 481 } 482 } 483 return QDF_STATUS_SUCCESS; 484 } 485 qdf_export_symbol(wlan_objmgr_vdev_component_obj_detach); 486 487 /** 488 ** APIs to operations on vdev objects 489 */ 490 QDF_STATUS wlan_objmgr_iterate_peerobj_list( 491 struct wlan_objmgr_vdev *vdev, 492 wlan_objmgr_vdev_op_handler handler, 493 void *arg, wlan_objmgr_ref_dbgid dbg_id) 494 { 495 qdf_list_t *peer_list = NULL; 496 struct wlan_objmgr_peer *peer = NULL; 497 struct wlan_objmgr_peer *peer_next = NULL; 498 uint8_t vdev_id; 499 500 if (vdev == NULL) { 501 obj_mgr_err("VDEV is NULL"); 502 return QDF_STATUS_E_FAILURE; 503 } 504 wlan_vdev_obj_lock(vdev); 505 vdev_id = wlan_vdev_get_id(vdev); 506 507 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 508 wlan_vdev_obj_unlock(vdev); 509 obj_mgr_err("VDEV is not in create state(:%d): vdev-id:%d", 510 vdev_id, vdev->obj_state); 511 return QDF_STATUS_E_FAILURE; 512 } 513 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 514 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 515 if (peer_list != NULL) { 516 /* Iterate through VDEV's peer list */ 517 peer = wlan_vdev_peer_list_peek_head(peer_list); 518 while (peer != NULL) { 519 peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, 520 peer); 521 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 522 QDF_STATUS_SUCCESS) { 523 /* Invoke handler for operation */ 524 handler(vdev, (void *)peer, arg); 525 wlan_objmgr_peer_release_ref(peer, dbg_id); 526 } 527 peer = peer_next; 528 } 529 } 530 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 531 wlan_vdev_obj_unlock(vdev); 532 return QDF_STATUS_SUCCESS; 533 } 534 535 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation( 536 struct wlan_objmgr_vdev *vdev, 537 enum wlan_umac_comp_id id) 538 { 539 wlan_objmgr_vdev_create_handler handler; 540 void *arg; 541 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 542 543 /* Component id is invalid */ 544 if (id >= WLAN_UMAC_MAX_COMPONENTS) 545 return QDF_STATUS_MAXCOMP_FAIL; 546 547 wlan_vdev_obj_lock(vdev); 548 /* 549 * If component object is already created, delete old 550 * component object, then invoke creation 551 */ 552 if (vdev->vdev_comp_priv_obj[id] != NULL) { 553 wlan_vdev_obj_unlock(vdev); 554 return QDF_STATUS_E_FAILURE; 555 } 556 wlan_vdev_obj_unlock(vdev); 557 558 /* Invoke registered create handlers */ 559 handler = g_umac_glb_obj->vdev_create_handler[id]; 560 arg = g_umac_glb_obj->vdev_create_handler_arg[id]; 561 if (handler != NULL) 562 vdev->obj_status[id] = handler(vdev, arg); 563 else 564 return QDF_STATUS_E_FAILURE; 565 566 /* If object status is created, then only handle this object status */ 567 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 568 /* Derive object status */ 569 obj_status = wlan_objmgr_vdev_object_status(vdev); 570 /* Move PDEV object state to Partially created state */ 571 if (obj_status == QDF_STATUS_COMP_ASYNC) { 572 /*TODO atomic */ 573 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 574 } 575 } 576 return obj_status; 577 } 578 579 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion( 580 struct wlan_objmgr_vdev *vdev, 581 enum wlan_umac_comp_id id) 582 { 583 wlan_objmgr_vdev_destroy_handler handler; 584 void *arg; 585 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 586 587 /* component id is invalid */ 588 if (id >= WLAN_UMAC_MAX_COMPONENTS) 589 return QDF_STATUS_MAXCOMP_FAIL; 590 591 wlan_vdev_obj_lock(vdev); 592 /* Component object was never created, invalid operation */ 593 if (vdev->vdev_comp_priv_obj[id] == NULL) { 594 wlan_vdev_obj_unlock(vdev); 595 return QDF_STATUS_E_FAILURE; 596 } 597 wlan_vdev_obj_unlock(vdev); 598 599 /* Invoke registered create handlers */ 600 handler = g_umac_glb_obj->vdev_destroy_handler[id]; 601 arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; 602 if (handler != NULL) 603 vdev->obj_status[id] = handler(vdev, arg); 604 else 605 return QDF_STATUS_E_FAILURE; 606 607 /* If object status is created, then only handle this object status */ 608 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 609 obj_status = wlan_objmgr_vdev_object_status(vdev); 610 /* move object state to DEL progress */ 611 if (obj_status == QDF_STATUS_COMP_ASYNC) 612 vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 613 } 614 return obj_status; 615 } 616 617 618 619 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list, 620 struct wlan_objmgr_peer *obj) 621 { 622 qdf_list_insert_back(obj_list, &obj->vdev_peer); 623 } 624 625 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list, 626 struct wlan_objmgr_peer *peer) 627 { 628 qdf_list_node_t *vdev_node = NULL; 629 630 if (peer == NULL) 631 return QDF_STATUS_E_FAILURE; 632 /* get vdev list node element */ 633 vdev_node = &peer->vdev_peer; 634 /* list is empty, return failure */ 635 if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) 636 return QDF_STATUS_E_FAILURE; 637 638 return QDF_STATUS_SUCCESS; 639 } 640 641 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, 642 struct wlan_objmgr_peer *peer) 643 { 644 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 645 struct wlan_objmgr_pdev *pdev; 646 enum QDF_OPMODE opmode; 647 648 wlan_vdev_obj_lock(vdev); 649 pdev = wlan_vdev_get_pdev(vdev); 650 /* If Max VDEV peer count exceeds, return failure */ 651 if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) { 652 if (objmgr->wlan_peer_count >= objmgr->max_peer_count) { 653 wlan_vdev_obj_unlock(vdev); 654 return QDF_STATUS_E_FAILURE; 655 } 656 } 657 wlan_vdev_obj_unlock(vdev); 658 659 /* If Max PDEV peer count exceeds, return failure */ 660 wlan_pdev_obj_lock(pdev); 661 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) { 662 if (wlan_pdev_get_temp_peer_count(pdev) >= 663 WLAN_MAX_PDEV_TEMP_PEERS) { 664 wlan_pdev_obj_unlock(pdev); 665 return QDF_STATUS_E_FAILURE; 666 } 667 } else { 668 if (wlan_pdev_get_peer_count(pdev) >= 669 wlan_pdev_get_max_peer_count(pdev)) { 670 wlan_pdev_obj_unlock(pdev); 671 return QDF_STATUS_E_FAILURE; 672 } 673 } 674 675 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 676 wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev)); 677 else 678 wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev)); 679 wlan_pdev_obj_unlock(pdev); 680 681 wlan_vdev_obj_lock(vdev); 682 /* Add peer to vdev's peer list */ 683 wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer); 684 objmgr->wlan_peer_count++; 685 686 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), 687 wlan_vdev_mlme_get_macaddr(vdev)) == 688 QDF_STATUS_SUCCESS) { 689 /* 690 * if peer mac address and vdev mac address match, set 691 * this peer as self peer 692 */ 693 wlan_vdev_set_selfpeer(vdev, peer); 694 opmode = wlan_vdev_mlme_get_opmode(vdev); 695 /* For AP mode, self peer and BSS peer are same */ 696 if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE)) 697 wlan_vdev_set_bsspeer(vdev, peer); 698 } 699 /* set BSS peer for sta */ 700 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) && 701 ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) || 702 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO))) 703 wlan_vdev_set_bsspeer(vdev, peer); 704 705 /* Increment vdev ref count to make sure it won't be destroyed before */ 706 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); 707 wlan_vdev_obj_unlock(vdev); 708 return QDF_STATUS_SUCCESS; 709 } 710 711 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev, 712 struct wlan_objmgr_peer *peer) 713 { 714 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 715 struct wlan_objmgr_pdev *pdev; 716 717 wlan_vdev_obj_lock(vdev); 718 /* if peer count is 0, return failure */ 719 if (objmgr->wlan_peer_count == 0) { 720 wlan_vdev_obj_unlock(vdev); 721 return QDF_STATUS_E_FAILURE; 722 } 723 724 if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) || 725 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) { 726 if (wlan_vdev_get_selfpeer(vdev) == peer) { 727 /* 728 * There might be instances where new node is created 729 * before deleting existing node, in which case selfpeer 730 * will be pointing to the new node. So set selfpeer to 731 * NULL only if vdev->vdev_objmgr.self_peer is pointing 732 * to the peer processed for deletion 733 */ 734 wlan_vdev_set_selfpeer(vdev, NULL); 735 } 736 737 if (wlan_vdev_get_bsspeer(vdev) == peer) { 738 /* 739 * There might be instances where new node is created 740 * before deleting existing node, in which case bsspeer 741 * in vdev will be pointing to the new node. So set 742 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is 743 * pointing to the peer processed for deletion 744 */ 745 wlan_vdev_set_bsspeer(vdev, NULL); 746 } 747 } 748 749 /* remove peer from vdev's peer list */ 750 if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer) 751 == QDF_STATUS_E_FAILURE) { 752 wlan_vdev_obj_unlock(vdev); 753 return QDF_STATUS_E_FAILURE; 754 } 755 /* decrement peer count */ 756 objmgr->wlan_peer_count--; 757 /* decrement pdev peer count */ 758 pdev = wlan_vdev_get_pdev(vdev); 759 wlan_vdev_obj_unlock(vdev); 760 761 wlan_pdev_obj_lock(pdev); 762 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 763 wlan_pdev_decr_temp_peer_count(pdev); 764 else 765 wlan_pdev_decr_peer_count(pdev); 766 wlan_pdev_obj_unlock(pdev); 767 768 /* decrement vdev ref count after peer released its reference */ 769 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 770 return QDF_STATUS_SUCCESS; 771 } 772 773 void *wlan_objmgr_vdev_get_comp_private_obj( 774 struct wlan_objmgr_vdev *vdev, 775 enum wlan_umac_comp_id id) 776 { 777 void *comp_priv_obj; 778 779 /* component id is invalid */ 780 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 781 QDF_BUG(0); 782 return NULL; 783 } 784 785 if (vdev == NULL) { 786 QDF_BUG(0); 787 return NULL; 788 } 789 790 comp_priv_obj = vdev->vdev_comp_priv_obj[id]; 791 792 return comp_priv_obj; 793 } 794 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj); 795 796 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, 797 wlan_objmgr_ref_dbgid id) 798 { 799 if (vdev == NULL) { 800 obj_mgr_err("vdev obj is NULL for id:%d", id); 801 QDF_ASSERT(0); 802 return; 803 } 804 /* Increment ref count */ 805 qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); 806 qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); 807 808 return; 809 } 810 qdf_export_symbol(wlan_objmgr_vdev_get_ref); 811 812 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, 813 wlan_objmgr_ref_dbgid id) 814 { 815 uint8_t vdev_id; 816 817 if (vdev == NULL) { 818 obj_mgr_err("vdev obj is NULL for id:%d", id); 819 QDF_ASSERT(0); 820 return QDF_STATUS_E_FAILURE; 821 } 822 823 wlan_vdev_obj_lock(vdev); 824 vdev_id = wlan_vdev_get_id(vdev); 825 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 826 wlan_vdev_obj_unlock(vdev); 827 if (vdev->vdev_objmgr.print_cnt++ <= 828 WLAN_OBJMGR_RATELIMIT_THRESH) 829 obj_mgr_err( 830 "[Ref id: %d] vdev(%d) is not in Created state(%d)", 831 id, vdev_id, vdev->obj_state); 832 833 return QDF_STATUS_E_RESOURCES; 834 } 835 836 /* Increment ref count */ 837 wlan_objmgr_vdev_get_ref(vdev, id); 838 wlan_vdev_obj_unlock(vdev); 839 840 return QDF_STATUS_SUCCESS; 841 } 842 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref); 843 844 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, 845 wlan_objmgr_ref_dbgid id) 846 { 847 uint8_t vdev_id; 848 849 if (vdev == NULL) { 850 obj_mgr_err("vdev obj is NULL for id:%d", id); 851 QDF_ASSERT(0); 852 return; 853 } 854 855 vdev_id = wlan_vdev_get_id(vdev); 856 857 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { 858 obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d", 859 vdev_id, id); 860 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg); 861 WLAN_OBJMGR_BUG(0); 862 } 863 864 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { 865 obj_mgr_err("vdev ref cnt is 0"); 866 WLAN_OBJMGR_BUG(0); 867 return; 868 } 869 qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); 870 871 /* Decrement ref count, free vdev, if ref count == 0 */ 872 if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) 873 wlan_objmgr_vdev_obj_destroy(vdev); 874 875 return; 876 } 877 qdf_export_symbol(wlan_objmgr_vdev_release_ref); 878 879 bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev) 880 { 881 struct wlan_objmgr_peer *peer; 882 enum wlan_peer_state peer_state; 883 884 wlan_vdev_obj_lock(vdev); 885 peer = wlan_vdev_get_bsspeer(vdev); 886 wlan_vdev_obj_unlock(vdev); 887 888 if (!peer) 889 return false; 890 891 wlan_peer_obj_lock(peer); 892 peer_state = wlan_peer_mlme_get_state(peer); 893 wlan_peer_obj_unlock(peer); 894 895 if (peer_state != WLAN_ASSOC_STATE) 896 return false; 897 898 return true; 899 } 900 qdf_export_symbol(wlan_vdev_is_connected); 901 902 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( 903 struct wlan_objmgr_pdev *pdev, 904 qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id) 905 { 906 struct wlan_objmgr_vdev *vdev; 907 qdf_list_node_t *node = NULL; 908 qdf_list_node_t *prev_node = NULL; 909 910 wlan_pdev_obj_lock(pdev); 911 912 if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { 913 wlan_pdev_obj_unlock(pdev); 914 return NULL; 915 } 916 917 do { 918 vdev = qdf_container_of(node, struct wlan_objmgr_vdev, 919 vdev_node); 920 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 921 QDF_STATUS_SUCCESS) { 922 wlan_pdev_obj_unlock(pdev); 923 return vdev; 924 } 925 926 prev_node = node; 927 } while (qdf_list_peek_next(vdev_list, prev_node, &node) == 928 QDF_STATUS_SUCCESS); 929 930 wlan_pdev_obj_unlock(pdev); 931 932 return NULL; 933 } 934 935 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( 936 struct wlan_objmgr_pdev *pdev, 937 qdf_list_t *vdev_list, 938 struct wlan_objmgr_vdev *vdev, 939 wlan_objmgr_ref_dbgid dbg_id) 940 { 941 struct wlan_objmgr_vdev *vdev_next; 942 qdf_list_node_t *node = &vdev->vdev_node; 943 qdf_list_node_t *prev_node = NULL; 944 945 if (node == NULL) 946 return NULL; 947 948 wlan_pdev_obj_lock(pdev); 949 prev_node = node; 950 while (qdf_list_peek_next(vdev_list, prev_node, &node) == 951 QDF_STATUS_SUCCESS) { 952 vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, 953 vdev_node); 954 if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) == 955 QDF_STATUS_SUCCESS) { 956 wlan_pdev_obj_unlock(pdev); 957 return vdev_next; 958 } 959 960 prev_node = node; 961 } 962 wlan_pdev_obj_unlock(pdev); 963 964 return NULL; 965 } 966 967