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_debug("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 && 297 (vdev->obj_status[id] == QDF_STATUS_SUCCESS || 298 vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC)) 299 vdev->obj_status[id] = handler(vdev, arg); 300 else 301 vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 302 } 303 /* Derive object status */ 304 obj_status = wlan_objmgr_vdev_object_status(vdev); 305 306 if (obj_status == QDF_STATUS_E_FAILURE) { 307 obj_mgr_err("VDEV object deletion failed: vdev-id: %d", 308 vdev_id); 309 /* Ideally should not happen */ 310 /* This leads to memleak ??? how to handle */ 311 QDF_BUG(0); 312 return QDF_STATUS_E_FAILURE; 313 } 314 315 /* Deletion is in progress */ 316 if (obj_status == QDF_STATUS_COMP_ASYNC) { 317 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 318 return QDF_STATUS_COMP_ASYNC; 319 } 320 321 /* Free VDEV object */ 322 return wlan_objmgr_vdev_obj_free(vdev); 323 } 324 325 QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) 326 { 327 uint8_t print_idx; 328 329 if (vdev == NULL) { 330 obj_mgr_err("vdev is NULL"); 331 return QDF_STATUS_E_FAILURE; 332 } 333 334 obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id); 335 336 print_idx = qdf_get_pidx(); 337 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, 338 QDF_TRACE_LEVEL_DEBUG); 339 /* 340 * Update VDEV object state to LOGICALLY DELETED 341 * It prevents further access of this object 342 */ 343 wlan_vdev_obj_lock(vdev); 344 vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 345 wlan_vdev_obj_unlock(vdev); 346 wlan_objmgr_notify_log_delete(vdev, WLAN_VDEV_OP); 347 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 348 349 return QDF_STATUS_SUCCESS; 350 } 351 qdf_export_symbol(wlan_objmgr_vdev_obj_delete); 352 353 /** 354 ** APIs to attach/detach component objects 355 */ 356 QDF_STATUS wlan_objmgr_vdev_component_obj_attach( 357 struct wlan_objmgr_vdev *vdev, 358 enum wlan_umac_comp_id id, 359 void *comp_priv_obj, 360 QDF_STATUS status) 361 { 362 wlan_objmgr_vdev_status_handler stat_handler; 363 void *arg; 364 uint8_t i; 365 QDF_STATUS obj_status; 366 367 /* component id is invalid */ 368 if (id >= WLAN_UMAC_MAX_COMPONENTS) 369 return QDF_STATUS_MAXCOMP_FAIL; 370 371 wlan_vdev_obj_lock(vdev); 372 /* If there is a valid entry, return failure */ 373 if (vdev->vdev_comp_priv_obj[id] != NULL) { 374 wlan_vdev_obj_unlock(vdev); 375 return QDF_STATUS_E_FAILURE; 376 } 377 /* Save component's pointer and status */ 378 vdev->vdev_comp_priv_obj[id] = comp_priv_obj; 379 vdev->obj_status[id] = status; 380 wlan_vdev_obj_unlock(vdev); 381 if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 382 return QDF_STATUS_SUCCESS; 383 /* 384 * If VDEV object status is partially created means, this API is 385 * invoked with differnt context, this block should be executed for 386 * async components only 387 */ 388 /* Derive status */ 389 obj_status = wlan_objmgr_vdev_object_status(vdev); 390 /* STATUS_SUCCESS means, object is CREATED */ 391 if (obj_status == QDF_STATUS_SUCCESS) 392 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 393 /* 394 * update state as CREATION failed, caller has to delete the 395 * VDEV object 396 */ 397 else if (obj_status == QDF_STATUS_E_FAILURE) 398 vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 399 /* Notify components about the CREATION success/failure */ 400 if ((obj_status == QDF_STATUS_SUCCESS) || 401 (obj_status == QDF_STATUS_E_FAILURE)) { 402 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 403 stat_handler = g_umac_glb_obj->vdev_status_handler[i]; 404 arg = g_umac_glb_obj->vdev_status_handler_arg[i]; 405 if (stat_handler != NULL) 406 stat_handler(vdev, arg, obj_status); 407 } 408 } 409 return QDF_STATUS_SUCCESS; 410 } 411 qdf_export_symbol(wlan_objmgr_vdev_component_obj_attach); 412 413 QDF_STATUS wlan_objmgr_vdev_component_obj_detach( 414 struct wlan_objmgr_vdev *vdev, 415 enum wlan_umac_comp_id id, 416 void *comp_priv_obj) 417 { 418 QDF_STATUS obj_status; 419 420 /* component id is invalid */ 421 if (id >= WLAN_UMAC_MAX_COMPONENTS) 422 return QDF_STATUS_MAXCOMP_FAIL; 423 424 wlan_vdev_obj_lock(vdev); 425 /* If there is a valid entry, return failure */ 426 if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) { 427 vdev->obj_status[id] = QDF_STATUS_E_FAILURE; 428 wlan_vdev_obj_unlock(vdev); 429 return QDF_STATUS_E_FAILURE; 430 } 431 /* Reset pointers to NULL, update the status*/ 432 vdev->vdev_comp_priv_obj[id] = NULL; 433 vdev->obj_status[id] = QDF_STATUS_SUCCESS; 434 wlan_vdev_obj_unlock(vdev); 435 436 /** 437 *If VDEV object status is partially destroyed means, this API is 438 * invoked with differnt context, this block should be executed for 439 * async components only 440 */ 441 if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 442 (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 443 /* Derive object status */ 444 obj_status = wlan_objmgr_vdev_object_status(vdev); 445 if (obj_status == QDF_STATUS_SUCCESS) { 446 /* 447 * Update the status as Deleted, if full object 448 * deletion is in progress 449 */ 450 if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 451 vdev->obj_state = WLAN_OBJ_STATE_DELETED; 452 /* 453 * Move to creation state, since this component 454 * deletion alone requested 455 */ 456 else if (vdev->obj_state == 457 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 458 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 459 /* Object status is failure */ 460 } else if (obj_status == QDF_STATUS_E_FAILURE) { 461 /* 462 * Update the status as Deletion failed, if full object 463 * deletion is in progress 464 */ 465 if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 466 vdev->obj_state = 467 WLAN_OBJ_STATE_DELETION_FAILED; 468 /* Move to creation state, since this component 469 deletion alone requested (do not block other 470 components) */ 471 else if (vdev->obj_state == 472 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 473 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 474 } 475 /* Delete vdev object */ 476 if ((obj_status == QDF_STATUS_SUCCESS) && 477 (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) { 478 /* Free VDEV object */ 479 return wlan_objmgr_vdev_obj_free(vdev); 480 } 481 } 482 return QDF_STATUS_SUCCESS; 483 } 484 qdf_export_symbol(wlan_objmgr_vdev_component_obj_detach); 485 486 /** 487 ** APIs to operations on vdev objects 488 */ 489 QDF_STATUS wlan_objmgr_iterate_peerobj_list( 490 struct wlan_objmgr_vdev *vdev, 491 wlan_objmgr_vdev_op_handler handler, 492 void *arg, wlan_objmgr_ref_dbgid dbg_id) 493 { 494 qdf_list_t *peer_list = NULL; 495 struct wlan_objmgr_peer *peer = NULL; 496 struct wlan_objmgr_peer *peer_next = NULL; 497 uint8_t vdev_id; 498 499 if (vdev == NULL) { 500 obj_mgr_err("VDEV is NULL"); 501 return QDF_STATUS_E_FAILURE; 502 } 503 wlan_vdev_obj_lock(vdev); 504 vdev_id = wlan_vdev_get_id(vdev); 505 506 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 507 wlan_vdev_obj_unlock(vdev); 508 obj_mgr_err("VDEV is not in create state(:%d): vdev-id:%d", 509 vdev_id, vdev->obj_state); 510 return QDF_STATUS_E_FAILURE; 511 } 512 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 513 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 514 if (peer_list != NULL) { 515 /* Iterate through VDEV's peer list */ 516 peer = wlan_vdev_peer_list_peek_head(peer_list); 517 while (peer != NULL) { 518 peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, 519 peer); 520 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 521 QDF_STATUS_SUCCESS) { 522 /* Invoke handler for operation */ 523 handler(vdev, (void *)peer, arg); 524 wlan_objmgr_peer_release_ref(peer, dbg_id); 525 } 526 peer = peer_next; 527 } 528 } 529 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 530 wlan_vdev_obj_unlock(vdev); 531 return QDF_STATUS_SUCCESS; 532 } 533 534 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation( 535 struct wlan_objmgr_vdev *vdev, 536 enum wlan_umac_comp_id id) 537 { 538 wlan_objmgr_vdev_create_handler handler; 539 void *arg; 540 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 541 542 /* Component id is invalid */ 543 if (id >= WLAN_UMAC_MAX_COMPONENTS) 544 return QDF_STATUS_MAXCOMP_FAIL; 545 546 wlan_vdev_obj_lock(vdev); 547 /* 548 * If component object is already created, delete old 549 * component object, then invoke creation 550 */ 551 if (vdev->vdev_comp_priv_obj[id] != NULL) { 552 wlan_vdev_obj_unlock(vdev); 553 return QDF_STATUS_E_FAILURE; 554 } 555 wlan_vdev_obj_unlock(vdev); 556 557 /* Invoke registered create handlers */ 558 handler = g_umac_glb_obj->vdev_create_handler[id]; 559 arg = g_umac_glb_obj->vdev_create_handler_arg[id]; 560 if (handler != NULL) 561 vdev->obj_status[id] = handler(vdev, arg); 562 else 563 return QDF_STATUS_E_FAILURE; 564 565 /* If object status is created, then only handle this object status */ 566 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 567 /* Derive object status */ 568 obj_status = wlan_objmgr_vdev_object_status(vdev); 569 /* Move PDEV object state to Partially created state */ 570 if (obj_status == QDF_STATUS_COMP_ASYNC) { 571 /*TODO atomic */ 572 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 573 } 574 } 575 return obj_status; 576 } 577 578 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion( 579 struct wlan_objmgr_vdev *vdev, 580 enum wlan_umac_comp_id id) 581 { 582 wlan_objmgr_vdev_destroy_handler handler; 583 void *arg; 584 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 585 586 /* component id is invalid */ 587 if (id >= WLAN_UMAC_MAX_COMPONENTS) 588 return QDF_STATUS_MAXCOMP_FAIL; 589 590 wlan_vdev_obj_lock(vdev); 591 /* Component object was never created, invalid operation */ 592 if (vdev->vdev_comp_priv_obj[id] == NULL) { 593 wlan_vdev_obj_unlock(vdev); 594 return QDF_STATUS_E_FAILURE; 595 } 596 wlan_vdev_obj_unlock(vdev); 597 598 /* Invoke registered create handlers */ 599 handler = g_umac_glb_obj->vdev_destroy_handler[id]; 600 arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; 601 if (handler != NULL) 602 vdev->obj_status[id] = handler(vdev, arg); 603 else 604 return QDF_STATUS_E_FAILURE; 605 606 /* If object status is created, then only handle this object status */ 607 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 608 obj_status = wlan_objmgr_vdev_object_status(vdev); 609 /* move object state to DEL progress */ 610 if (obj_status == QDF_STATUS_COMP_ASYNC) 611 vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 612 } 613 return obj_status; 614 } 615 616 617 618 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list, 619 struct wlan_objmgr_peer *obj) 620 { 621 qdf_list_insert_back(obj_list, &obj->vdev_peer); 622 } 623 624 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list, 625 struct wlan_objmgr_peer *peer) 626 { 627 qdf_list_node_t *vdev_node = NULL; 628 629 if (peer == NULL) 630 return QDF_STATUS_E_FAILURE; 631 /* get vdev list node element */ 632 vdev_node = &peer->vdev_peer; 633 /* list is empty, return failure */ 634 if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) 635 return QDF_STATUS_E_FAILURE; 636 637 return QDF_STATUS_SUCCESS; 638 } 639 640 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, 641 struct wlan_objmgr_peer *peer) 642 { 643 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 644 struct wlan_objmgr_pdev *pdev; 645 enum QDF_OPMODE opmode; 646 647 wlan_vdev_obj_lock(vdev); 648 pdev = wlan_vdev_get_pdev(vdev); 649 /* If Max VDEV peer count exceeds, return failure */ 650 if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) { 651 if (objmgr->wlan_peer_count >= objmgr->max_peer_count) { 652 wlan_vdev_obj_unlock(vdev); 653 return QDF_STATUS_E_FAILURE; 654 } 655 } 656 wlan_vdev_obj_unlock(vdev); 657 658 /* If Max PDEV peer count exceeds, return failure */ 659 wlan_pdev_obj_lock(pdev); 660 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) { 661 if (wlan_pdev_get_temp_peer_count(pdev) >= 662 WLAN_MAX_PDEV_TEMP_PEERS) { 663 wlan_pdev_obj_unlock(pdev); 664 return QDF_STATUS_E_FAILURE; 665 } 666 } else { 667 if (wlan_pdev_get_peer_count(pdev) >= 668 wlan_pdev_get_max_peer_count(pdev)) { 669 wlan_pdev_obj_unlock(pdev); 670 return QDF_STATUS_E_FAILURE; 671 } 672 } 673 674 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 675 wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev)); 676 else 677 wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev)); 678 wlan_pdev_obj_unlock(pdev); 679 680 wlan_vdev_obj_lock(vdev); 681 /* Add peer to vdev's peer list */ 682 wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer); 683 objmgr->wlan_peer_count++; 684 685 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), 686 wlan_vdev_mlme_get_macaddr(vdev)) == 687 QDF_STATUS_SUCCESS) { 688 /* 689 * if peer mac address and vdev mac address match, set 690 * this peer as self peer 691 */ 692 wlan_vdev_set_selfpeer(vdev, peer); 693 opmode = wlan_vdev_mlme_get_opmode(vdev); 694 /* For AP mode, self peer and BSS peer are same */ 695 if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE)) 696 wlan_vdev_set_bsspeer(vdev, peer); 697 } 698 /* set BSS peer for sta */ 699 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE || 700 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_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 QDF_TRACE_LEVEL_FATAL); 862 WLAN_OBJMGR_BUG(0); 863 } 864 865 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { 866 obj_mgr_err("vdev ref cnt is 0"); 867 WLAN_OBJMGR_BUG(0); 868 return; 869 } 870 qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); 871 872 /* Decrement ref count, free vdev, if ref count == 0 */ 873 if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) 874 wlan_objmgr_vdev_obj_destroy(vdev); 875 876 return; 877 } 878 qdf_export_symbol(wlan_objmgr_vdev_release_ref); 879 880 bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev) 881 { 882 struct wlan_objmgr_peer *peer; 883 enum wlan_peer_state peer_state; 884 885 wlan_vdev_obj_lock(vdev); 886 peer = wlan_vdev_get_bsspeer(vdev); 887 wlan_vdev_obj_unlock(vdev); 888 889 if (!peer) 890 return false; 891 892 wlan_peer_obj_lock(peer); 893 peer_state = wlan_peer_mlme_get_state(peer); 894 wlan_peer_obj_unlock(peer); 895 896 if (peer_state != WLAN_ASSOC_STATE) 897 return false; 898 899 return true; 900 } 901 qdf_export_symbol(wlan_vdev_is_connected); 902 903 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( 904 struct wlan_objmgr_pdev *pdev, 905 qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id) 906 { 907 struct wlan_objmgr_vdev *vdev; 908 qdf_list_node_t *node = NULL; 909 qdf_list_node_t *prev_node = NULL; 910 911 wlan_pdev_obj_lock(pdev); 912 913 if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { 914 wlan_pdev_obj_unlock(pdev); 915 return NULL; 916 } 917 918 do { 919 vdev = qdf_container_of(node, struct wlan_objmgr_vdev, 920 vdev_node); 921 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 922 QDF_STATUS_SUCCESS) { 923 wlan_pdev_obj_unlock(pdev); 924 return vdev; 925 } 926 927 prev_node = node; 928 } while (qdf_list_peek_next(vdev_list, prev_node, &node) == 929 QDF_STATUS_SUCCESS); 930 931 wlan_pdev_obj_unlock(pdev); 932 933 return NULL; 934 } 935 936 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( 937 struct wlan_objmgr_pdev *pdev, 938 qdf_list_t *vdev_list, 939 struct wlan_objmgr_vdev *vdev, 940 wlan_objmgr_ref_dbgid dbg_id) 941 { 942 struct wlan_objmgr_vdev *vdev_next; 943 qdf_list_node_t *node = &vdev->vdev_node; 944 qdf_list_node_t *prev_node = NULL; 945 946 if (node == NULL) 947 return NULL; 948 949 wlan_pdev_obj_lock(pdev); 950 prev_node = node; 951 while (qdf_list_peek_next(vdev_list, prev_node, &node) == 952 QDF_STATUS_SUCCESS) { 953 vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, 954 vdev_node); 955 if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) == 956 QDF_STATUS_SUCCESS) { 957 wlan_pdev_obj_unlock(pdev); 958 return vdev_next; 959 } 960 961 prev_node = node; 962 } 963 wlan_pdev_obj_unlock(pdev); 964 965 return NULL; 966 } 967 968