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 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, 336 QDF_TRACE_LEVEL_DEBUG); 337 /* 338 * Update VDEV object state to LOGICALLY DELETED 339 * It prevents further access of this object 340 */ 341 wlan_vdev_obj_lock(vdev); 342 vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 343 wlan_vdev_obj_unlock(vdev); 344 wlan_objmgr_notify_log_delete(vdev, WLAN_VDEV_OP); 345 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 346 347 return QDF_STATUS_SUCCESS; 348 } 349 qdf_export_symbol(wlan_objmgr_vdev_obj_delete); 350 351 /** 352 ** APIs to attach/detach component objects 353 */ 354 QDF_STATUS wlan_objmgr_vdev_component_obj_attach( 355 struct wlan_objmgr_vdev *vdev, 356 enum wlan_umac_comp_id id, 357 void *comp_priv_obj, 358 QDF_STATUS status) 359 { 360 wlan_objmgr_vdev_status_handler stat_handler; 361 void *arg; 362 uint8_t i; 363 QDF_STATUS obj_status; 364 365 /* component id is invalid */ 366 if (id >= WLAN_UMAC_MAX_COMPONENTS) 367 return QDF_STATUS_MAXCOMP_FAIL; 368 369 wlan_vdev_obj_lock(vdev); 370 /* If there is a valid entry, return failure */ 371 if (vdev->vdev_comp_priv_obj[id] != NULL) { 372 wlan_vdev_obj_unlock(vdev); 373 return QDF_STATUS_E_FAILURE; 374 } 375 /* Save component's pointer and status */ 376 vdev->vdev_comp_priv_obj[id] = comp_priv_obj; 377 vdev->obj_status[id] = status; 378 wlan_vdev_obj_unlock(vdev); 379 if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 380 return QDF_STATUS_SUCCESS; 381 /* 382 * If VDEV object status is partially created means, this API is 383 * invoked with differnt context, this block should be executed for 384 * async components only 385 */ 386 /* Derive status */ 387 obj_status = wlan_objmgr_vdev_object_status(vdev); 388 /* STATUS_SUCCESS means, object is CREATED */ 389 if (obj_status == QDF_STATUS_SUCCESS) 390 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 391 /* 392 * update state as CREATION failed, caller has to delete the 393 * VDEV object 394 */ 395 else if (obj_status == QDF_STATUS_E_FAILURE) 396 vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 397 /* Notify components about the CREATION success/failure */ 398 if ((obj_status == QDF_STATUS_SUCCESS) || 399 (obj_status == QDF_STATUS_E_FAILURE)) { 400 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 401 stat_handler = g_umac_glb_obj->vdev_status_handler[i]; 402 arg = g_umac_glb_obj->vdev_status_handler_arg[i]; 403 if (stat_handler != NULL) 404 stat_handler(vdev, arg, obj_status); 405 } 406 } 407 return QDF_STATUS_SUCCESS; 408 } 409 qdf_export_symbol(wlan_objmgr_vdev_component_obj_attach); 410 411 QDF_STATUS wlan_objmgr_vdev_component_obj_detach( 412 struct wlan_objmgr_vdev *vdev, 413 enum wlan_umac_comp_id id, 414 void *comp_priv_obj) 415 { 416 QDF_STATUS obj_status; 417 418 /* component id is invalid */ 419 if (id >= WLAN_UMAC_MAX_COMPONENTS) 420 return QDF_STATUS_MAXCOMP_FAIL; 421 422 wlan_vdev_obj_lock(vdev); 423 /* If there is a valid entry, return failure */ 424 if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) { 425 vdev->obj_status[id] = QDF_STATUS_E_FAILURE; 426 wlan_vdev_obj_unlock(vdev); 427 return QDF_STATUS_E_FAILURE; 428 } 429 /* Reset pointers to NULL, update the status*/ 430 vdev->vdev_comp_priv_obj[id] = NULL; 431 vdev->obj_status[id] = QDF_STATUS_SUCCESS; 432 wlan_vdev_obj_unlock(vdev); 433 434 /** 435 *If VDEV object status is partially destroyed means, this API is 436 * invoked with differnt context, this block should be executed for 437 * async components only 438 */ 439 if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 440 (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 441 /* Derive object status */ 442 obj_status = wlan_objmgr_vdev_object_status(vdev); 443 if (obj_status == QDF_STATUS_SUCCESS) { 444 /* 445 * Update the status as Deleted, if full object 446 * deletion is in progress 447 */ 448 if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 449 vdev->obj_state = WLAN_OBJ_STATE_DELETED; 450 /* 451 * Move to creation state, since this component 452 * deletion alone requested 453 */ 454 else if (vdev->obj_state == 455 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 456 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 457 /* Object status is failure */ 458 } else if (obj_status == QDF_STATUS_E_FAILURE) { 459 /* 460 * Update the status as Deletion failed, if full object 461 * deletion is in progress 462 */ 463 if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 464 vdev->obj_state = 465 WLAN_OBJ_STATE_DELETION_FAILED; 466 /* Move to creation state, since this component 467 deletion alone requested (do not block other 468 components) */ 469 else if (vdev->obj_state == 470 WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 471 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 472 } 473 /* Delete vdev object */ 474 if ((obj_status == QDF_STATUS_SUCCESS) && 475 (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) { 476 /* Free VDEV object */ 477 return wlan_objmgr_vdev_obj_free(vdev); 478 } 479 } 480 return QDF_STATUS_SUCCESS; 481 } 482 qdf_export_symbol(wlan_objmgr_vdev_component_obj_detach); 483 484 /** 485 ** APIs to operations on vdev objects 486 */ 487 QDF_STATUS wlan_objmgr_iterate_peerobj_list( 488 struct wlan_objmgr_vdev *vdev, 489 wlan_objmgr_vdev_op_handler handler, 490 void *arg, wlan_objmgr_ref_dbgid dbg_id) 491 { 492 qdf_list_t *peer_list = NULL; 493 struct wlan_objmgr_peer *peer = NULL; 494 struct wlan_objmgr_peer *peer_next = NULL; 495 uint8_t vdev_id; 496 497 if (vdev == NULL) { 498 obj_mgr_err("VDEV is NULL"); 499 return QDF_STATUS_E_FAILURE; 500 } 501 wlan_vdev_obj_lock(vdev); 502 vdev_id = wlan_vdev_get_id(vdev); 503 504 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 505 wlan_vdev_obj_unlock(vdev); 506 obj_mgr_err("VDEV is not in create state(:%d): vdev-id:%d", 507 vdev_id, vdev->obj_state); 508 return QDF_STATUS_E_FAILURE; 509 } 510 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 511 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 512 if (peer_list != NULL) { 513 /* Iterate through VDEV's peer list */ 514 peer = wlan_vdev_peer_list_peek_head(peer_list); 515 while (peer != NULL) { 516 peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, 517 peer); 518 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 519 QDF_STATUS_SUCCESS) { 520 /* Invoke handler for operation */ 521 handler(vdev, (void *)peer, arg); 522 wlan_objmgr_peer_release_ref(peer, dbg_id); 523 } 524 peer = peer_next; 525 } 526 } 527 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 528 wlan_vdev_obj_unlock(vdev); 529 return QDF_STATUS_SUCCESS; 530 } 531 532 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation( 533 struct wlan_objmgr_vdev *vdev, 534 enum wlan_umac_comp_id id) 535 { 536 wlan_objmgr_vdev_create_handler handler; 537 void *arg; 538 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 539 540 /* Component id is invalid */ 541 if (id >= WLAN_UMAC_MAX_COMPONENTS) 542 return QDF_STATUS_MAXCOMP_FAIL; 543 544 wlan_vdev_obj_lock(vdev); 545 /* 546 * If component object is already created, delete old 547 * component object, then invoke creation 548 */ 549 if (vdev->vdev_comp_priv_obj[id] != NULL) { 550 wlan_vdev_obj_unlock(vdev); 551 return QDF_STATUS_E_FAILURE; 552 } 553 wlan_vdev_obj_unlock(vdev); 554 555 /* Invoke registered create handlers */ 556 handler = g_umac_glb_obj->vdev_create_handler[id]; 557 arg = g_umac_glb_obj->vdev_create_handler_arg[id]; 558 if (handler != NULL) 559 vdev->obj_status[id] = handler(vdev, arg); 560 else 561 return QDF_STATUS_E_FAILURE; 562 563 /* If object status is created, then only handle this object status */ 564 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 565 /* Derive object status */ 566 obj_status = wlan_objmgr_vdev_object_status(vdev); 567 /* Move PDEV object state to Partially created state */ 568 if (obj_status == QDF_STATUS_COMP_ASYNC) { 569 /*TODO atomic */ 570 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 571 } 572 } 573 return obj_status; 574 } 575 576 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion( 577 struct wlan_objmgr_vdev *vdev, 578 enum wlan_umac_comp_id id) 579 { 580 wlan_objmgr_vdev_destroy_handler handler; 581 void *arg; 582 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 583 584 /* component id is invalid */ 585 if (id >= WLAN_UMAC_MAX_COMPONENTS) 586 return QDF_STATUS_MAXCOMP_FAIL; 587 588 wlan_vdev_obj_lock(vdev); 589 /* Component object was never created, invalid operation */ 590 if (vdev->vdev_comp_priv_obj[id] == NULL) { 591 wlan_vdev_obj_unlock(vdev); 592 return QDF_STATUS_E_FAILURE; 593 } 594 wlan_vdev_obj_unlock(vdev); 595 596 /* Invoke registered create handlers */ 597 handler = g_umac_glb_obj->vdev_destroy_handler[id]; 598 arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; 599 if (handler != NULL) 600 vdev->obj_status[id] = handler(vdev, arg); 601 else 602 return QDF_STATUS_E_FAILURE; 603 604 /* If object status is created, then only handle this object status */ 605 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 606 obj_status = wlan_objmgr_vdev_object_status(vdev); 607 /* move object state to DEL progress */ 608 if (obj_status == QDF_STATUS_COMP_ASYNC) 609 vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 610 } 611 return obj_status; 612 } 613 614 615 616 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list, 617 struct wlan_objmgr_peer *obj) 618 { 619 qdf_list_insert_back(obj_list, &obj->vdev_peer); 620 } 621 622 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list, 623 struct wlan_objmgr_peer *peer) 624 { 625 qdf_list_node_t *vdev_node = NULL; 626 627 if (peer == NULL) 628 return QDF_STATUS_E_FAILURE; 629 /* get vdev list node element */ 630 vdev_node = &peer->vdev_peer; 631 /* list is empty, return failure */ 632 if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) 633 return QDF_STATUS_E_FAILURE; 634 635 return QDF_STATUS_SUCCESS; 636 } 637 638 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, 639 struct wlan_objmgr_peer *peer) 640 { 641 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 642 struct wlan_objmgr_pdev *pdev; 643 enum QDF_OPMODE opmode; 644 645 wlan_vdev_obj_lock(vdev); 646 pdev = wlan_vdev_get_pdev(vdev); 647 /* If Max VDEV peer count exceeds, return failure */ 648 if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) { 649 if (objmgr->wlan_peer_count >= objmgr->max_peer_count) { 650 wlan_vdev_obj_unlock(vdev); 651 return QDF_STATUS_E_FAILURE; 652 } 653 } 654 wlan_vdev_obj_unlock(vdev); 655 656 /* If Max PDEV peer count exceeds, return failure */ 657 wlan_pdev_obj_lock(pdev); 658 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) { 659 if (wlan_pdev_get_temp_peer_count(pdev) >= 660 WLAN_MAX_PDEV_TEMP_PEERS) { 661 wlan_pdev_obj_unlock(pdev); 662 return QDF_STATUS_E_FAILURE; 663 } 664 } else { 665 if (wlan_pdev_get_peer_count(pdev) >= 666 wlan_pdev_get_max_peer_count(pdev)) { 667 wlan_pdev_obj_unlock(pdev); 668 return QDF_STATUS_E_FAILURE; 669 } 670 } 671 672 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 673 wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev)); 674 else 675 wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev)); 676 wlan_pdev_obj_unlock(pdev); 677 678 wlan_vdev_obj_lock(vdev); 679 /* Add peer to vdev's peer list */ 680 wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer); 681 objmgr->wlan_peer_count++; 682 683 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), 684 wlan_vdev_mlme_get_macaddr(vdev)) == 685 QDF_STATUS_SUCCESS) { 686 /* 687 * if peer mac address and vdev mac address match, set 688 * this peer as self peer 689 */ 690 wlan_vdev_set_selfpeer(vdev, peer); 691 opmode = wlan_vdev_mlme_get_opmode(vdev); 692 /* For AP mode, self peer and BSS peer are same */ 693 if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE)) 694 wlan_vdev_set_bsspeer(vdev, peer); 695 } 696 /* set BSS peer for sta */ 697 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) && 698 ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) || 699 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO))) 700 wlan_vdev_set_bsspeer(vdev, peer); 701 702 /* Increment vdev ref count to make sure it won't be destroyed before */ 703 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); 704 wlan_vdev_obj_unlock(vdev); 705 return QDF_STATUS_SUCCESS; 706 } 707 708 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev, 709 struct wlan_objmgr_peer *peer) 710 { 711 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 712 struct wlan_objmgr_pdev *pdev; 713 714 wlan_vdev_obj_lock(vdev); 715 /* if peer count is 0, return failure */ 716 if (objmgr->wlan_peer_count == 0) { 717 wlan_vdev_obj_unlock(vdev); 718 return QDF_STATUS_E_FAILURE; 719 } 720 721 if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) || 722 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) { 723 if (wlan_vdev_get_selfpeer(vdev) == peer) { 724 /* 725 * There might be instances where new node is created 726 * before deleting existing node, in which case selfpeer 727 * will be pointing to the new node. So set selfpeer to 728 * NULL only if vdev->vdev_objmgr.self_peer is pointing 729 * to the peer processed for deletion 730 */ 731 wlan_vdev_set_selfpeer(vdev, NULL); 732 } 733 734 if (wlan_vdev_get_bsspeer(vdev) == peer) { 735 /* 736 * There might be instances where new node is created 737 * before deleting existing node, in which case bsspeer 738 * in vdev will be pointing to the new node. So set 739 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is 740 * pointing to the peer processed for deletion 741 */ 742 wlan_vdev_set_bsspeer(vdev, NULL); 743 } 744 } 745 746 /* remove peer from vdev's peer list */ 747 if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer) 748 == QDF_STATUS_E_FAILURE) { 749 wlan_vdev_obj_unlock(vdev); 750 return QDF_STATUS_E_FAILURE; 751 } 752 /* decrement peer count */ 753 objmgr->wlan_peer_count--; 754 /* decrement pdev peer count */ 755 pdev = wlan_vdev_get_pdev(vdev); 756 wlan_vdev_obj_unlock(vdev); 757 758 wlan_pdev_obj_lock(pdev); 759 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 760 wlan_pdev_decr_temp_peer_count(pdev); 761 else 762 wlan_pdev_decr_peer_count(pdev); 763 wlan_pdev_obj_unlock(pdev); 764 765 /* decrement vdev ref count after peer released its reference */ 766 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 767 return QDF_STATUS_SUCCESS; 768 } 769 770 void *wlan_objmgr_vdev_get_comp_private_obj( 771 struct wlan_objmgr_vdev *vdev, 772 enum wlan_umac_comp_id id) 773 { 774 void *comp_priv_obj; 775 776 /* component id is invalid */ 777 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 778 QDF_BUG(0); 779 return NULL; 780 } 781 782 if (vdev == NULL) { 783 QDF_BUG(0); 784 return NULL; 785 } 786 787 comp_priv_obj = vdev->vdev_comp_priv_obj[id]; 788 789 return comp_priv_obj; 790 } 791 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj); 792 793 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, 794 wlan_objmgr_ref_dbgid id) 795 { 796 if (vdev == NULL) { 797 obj_mgr_err("vdev obj is NULL for id:%d", id); 798 QDF_ASSERT(0); 799 return; 800 } 801 /* Increment ref count */ 802 qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); 803 qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); 804 805 return; 806 } 807 qdf_export_symbol(wlan_objmgr_vdev_get_ref); 808 809 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, 810 wlan_objmgr_ref_dbgid id) 811 { 812 uint8_t vdev_id; 813 814 if (vdev == NULL) { 815 obj_mgr_err("vdev obj is NULL for id:%d", id); 816 QDF_ASSERT(0); 817 return QDF_STATUS_E_FAILURE; 818 } 819 820 wlan_vdev_obj_lock(vdev); 821 vdev_id = wlan_vdev_get_id(vdev); 822 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 823 wlan_vdev_obj_unlock(vdev); 824 if (vdev->vdev_objmgr.print_cnt++ <= 825 WLAN_OBJMGR_RATELIMIT_THRESH) 826 obj_mgr_err( 827 "[Ref id: %d] vdev(%d) is not in Created state(%d)", 828 id, vdev_id, vdev->obj_state); 829 830 return QDF_STATUS_E_RESOURCES; 831 } 832 833 /* Increment ref count */ 834 wlan_objmgr_vdev_get_ref(vdev, id); 835 wlan_vdev_obj_unlock(vdev); 836 837 return QDF_STATUS_SUCCESS; 838 } 839 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref); 840 841 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, 842 wlan_objmgr_ref_dbgid id) 843 { 844 uint8_t vdev_id; 845 846 if (vdev == NULL) { 847 obj_mgr_err("vdev obj is NULL for id:%d", id); 848 QDF_ASSERT(0); 849 return; 850 } 851 852 vdev_id = wlan_vdev_get_id(vdev); 853 854 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { 855 obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d", 856 vdev_id, id); 857 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, 858 QDF_TRACE_LEVEL_FATAL); 859 WLAN_OBJMGR_BUG(0); 860 } 861 862 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { 863 obj_mgr_err("vdev ref cnt is 0"); 864 WLAN_OBJMGR_BUG(0); 865 return; 866 } 867 qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); 868 869 /* Decrement ref count, free vdev, if ref count == 0 */ 870 if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) 871 wlan_objmgr_vdev_obj_destroy(vdev); 872 873 return; 874 } 875 qdf_export_symbol(wlan_objmgr_vdev_release_ref); 876 877 bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev) 878 { 879 struct wlan_objmgr_peer *peer; 880 enum wlan_peer_state peer_state; 881 882 wlan_vdev_obj_lock(vdev); 883 peer = wlan_vdev_get_bsspeer(vdev); 884 wlan_vdev_obj_unlock(vdev); 885 886 if (!peer) 887 return false; 888 889 wlan_peer_obj_lock(peer); 890 peer_state = wlan_peer_mlme_get_state(peer); 891 wlan_peer_obj_unlock(peer); 892 893 if (peer_state != WLAN_ASSOC_STATE) 894 return false; 895 896 return true; 897 } 898 qdf_export_symbol(wlan_vdev_is_connected); 899 900 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( 901 struct wlan_objmgr_pdev *pdev, 902 qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id) 903 { 904 struct wlan_objmgr_vdev *vdev; 905 qdf_list_node_t *node = NULL; 906 qdf_list_node_t *prev_node = NULL; 907 908 wlan_pdev_obj_lock(pdev); 909 910 if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { 911 wlan_pdev_obj_unlock(pdev); 912 return NULL; 913 } 914 915 do { 916 vdev = qdf_container_of(node, struct wlan_objmgr_vdev, 917 vdev_node); 918 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 919 QDF_STATUS_SUCCESS) { 920 wlan_pdev_obj_unlock(pdev); 921 return vdev; 922 } 923 924 prev_node = node; 925 } while (qdf_list_peek_next(vdev_list, prev_node, &node) == 926 QDF_STATUS_SUCCESS); 927 928 wlan_pdev_obj_unlock(pdev); 929 930 return NULL; 931 } 932 933 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( 934 struct wlan_objmgr_pdev *pdev, 935 qdf_list_t *vdev_list, 936 struct wlan_objmgr_vdev *vdev, 937 wlan_objmgr_ref_dbgid dbg_id) 938 { 939 struct wlan_objmgr_vdev *vdev_next; 940 qdf_list_node_t *node = &vdev->vdev_node; 941 qdf_list_node_t *prev_node = NULL; 942 943 if (node == NULL) 944 return NULL; 945 946 wlan_pdev_obj_lock(pdev); 947 prev_node = node; 948 while (qdf_list_peek_next(vdev_list, prev_node, &node) == 949 QDF_STATUS_SUCCESS) { 950 vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, 951 vdev_node); 952 if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) == 953 QDF_STATUS_SUCCESS) { 954 wlan_pdev_obj_unlock(pdev); 955 return vdev_next; 956 } 957 958 prev_node = node; 959 } 960 wlan_pdev_obj_unlock(pdev); 961 962 return NULL; 963 } 964 965