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 /* TODO init other parameters */ 220 221 /* Invoke registered create handlers */ 222 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 223 handler = g_umac_glb_obj->vdev_create_handler[id]; 224 arg = g_umac_glb_obj->vdev_create_handler_arg[id]; 225 if (handler != NULL) 226 vdev->obj_status[id] = handler(vdev, arg); 227 else 228 vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 229 } 230 231 /* Derive object status */ 232 obj_status = wlan_objmgr_vdev_object_status(vdev); 233 234 if (obj_status == QDF_STATUS_SUCCESS) { 235 /* Object status is SUCCESS, Object is created */ 236 vdev->obj_state = WLAN_OBJ_STATE_CREATED; 237 /* Invoke component registered status handlers */ 238 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 239 stat_handler = g_umac_glb_obj->vdev_status_handler[id]; 240 arg = g_umac_glb_obj->vdev_status_handler_arg[id]; 241 if (stat_handler != NULL) { 242 stat_handler(vdev, arg, 243 QDF_STATUS_SUCCESS); 244 } 245 } 246 /* 247 * Few components operates in Asynchrous communction, Object state 248 * partially created 249 */ 250 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 251 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 252 /* Component object failed to be created, clean up the object */ 253 } else if (obj_status == QDF_STATUS_E_FAILURE) { 254 /* Clean up the psoc */ 255 wlan_objmgr_vdev_obj_delete(vdev); 256 obj_mgr_err("VDEV comp objects creation failed for vdev-id:%d", 257 vdev->vdev_objmgr.vdev_id); 258 return NULL; 259 } 260 261 obj_mgr_info("Created vdev %d", vdev->vdev_objmgr.vdev_id); 262 263 return vdev; 264 } 265 qdf_export_symbol(wlan_objmgr_vdev_obj_create); 266 267 static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev) 268 { 269 uint8_t id; 270 wlan_objmgr_vdev_destroy_handler handler; 271 QDF_STATUS obj_status; 272 void *arg; 273 uint8_t vdev_id; 274 275 if (vdev == NULL) { 276 obj_mgr_err("vdev is NULL"); 277 return QDF_STATUS_E_FAILURE; 278 } 279 wlan_objmgr_notify_destroy(vdev, WLAN_VDEV_OP); 280 281 vdev_id = wlan_vdev_get_id(vdev); 282 283 obj_mgr_info("Physically deleting vdev %d", vdev_id); 284 285 if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 286 obj_mgr_err("vdev object delete is not invoked: vdev-id:%d", 287 wlan_vdev_get_id(vdev)); 288 WLAN_OBJMGR_BUG(0); 289 } 290 291 /* Invoke registered destroy handlers */ 292 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 293 handler = g_umac_glb_obj->vdev_destroy_handler[id]; 294 arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; 295 if (handler != NULL) 296 vdev->obj_status[id] = handler(vdev, arg); 297 else 298 vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; 299 } 300 /* Derive object status */ 301 obj_status = wlan_objmgr_vdev_object_status(vdev); 302 303 if (obj_status == QDF_STATUS_E_FAILURE) { 304 obj_mgr_err("VDEV object deletion failed: vdev-id: %d", 305 vdev_id); 306 /* Ideally should not happen */ 307 /* This leads to memleak ??? how to handle */ 308 QDF_BUG(0); 309 return QDF_STATUS_E_FAILURE; 310 } 311 312 /* Deletion is in progress */ 313 if (obj_status == QDF_STATUS_COMP_ASYNC) { 314 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 315 return QDF_STATUS_COMP_ASYNC; 316 } 317 318 /* Free VDEV object */ 319 return wlan_objmgr_vdev_obj_free(vdev); 320 } 321 322 QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) 323 { 324 uint8_t print_idx; 325 326 if (vdev == NULL) { 327 obj_mgr_err("vdev is NULL"); 328 return QDF_STATUS_E_FAILURE; 329 } 330 331 obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id); 332 333 print_idx = qdf_get_pidx(); 334 if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR, 335 QDF_TRACE_LEVEL_DEBUG)) { 336 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg); 337 } 338 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 peer count exceeds, return failure */ 650 if (objmgr->wlan_peer_count >= objmgr->max_peer_count) { 651 wlan_vdev_obj_unlock(vdev); 652 return QDF_STATUS_E_FAILURE; 653 } 654 wlan_vdev_obj_unlock(vdev); 655 656 wlan_pdev_obj_lock(pdev); 657 if (wlan_pdev_get_peer_count(pdev) >= 658 wlan_pdev_get_max_peer_count(pdev)) { 659 wlan_pdev_obj_unlock(pdev); 660 return QDF_STATUS_E_FAILURE; 661 } 662 663 wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev)); 664 wlan_pdev_obj_unlock(pdev); 665 666 wlan_vdev_obj_lock(vdev); 667 /* Add peer to vdev's peer list */ 668 wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer); 669 objmgr->wlan_peer_count++; 670 671 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), 672 wlan_vdev_mlme_get_macaddr(vdev)) == 673 QDF_STATUS_SUCCESS) { 674 /* 675 * if peer mac address and vdev mac address match, set 676 * this peer as self peer 677 */ 678 wlan_vdev_set_selfpeer(vdev, peer); 679 opmode = wlan_vdev_mlme_get_opmode(vdev); 680 /* For AP mode, self peer and BSS peer are same */ 681 if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE)) 682 wlan_vdev_set_bsspeer(vdev, peer); 683 } 684 /* set BSS peer for sta */ 685 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) && 686 ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) || 687 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO))) 688 wlan_vdev_set_bsspeer(vdev, peer); 689 690 /* Increment vdev ref count to make sure it won't be destroyed before */ 691 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); 692 wlan_vdev_obj_unlock(vdev); 693 return QDF_STATUS_SUCCESS; 694 } 695 696 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev, 697 struct wlan_objmgr_peer *peer) 698 { 699 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 700 struct wlan_objmgr_pdev *pdev; 701 702 wlan_vdev_obj_lock(vdev); 703 /* if peer count is 0, return failure */ 704 if (objmgr->wlan_peer_count == 0) { 705 wlan_vdev_obj_unlock(vdev); 706 return QDF_STATUS_E_FAILURE; 707 } 708 709 if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) || 710 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) { 711 if (wlan_vdev_get_selfpeer(vdev) == peer) { 712 /* 713 * There might be instances where new node is created 714 * before deleting existing node, in which case selfpeer 715 * will be pointing to the new node. So set selfpeer to 716 * NULL only if vdev->vdev_objmgr.self_peer is pointing 717 * to the peer processed for deletion 718 */ 719 wlan_vdev_set_selfpeer(vdev, NULL); 720 } 721 722 if (wlan_vdev_get_bsspeer(vdev) == peer) { 723 /* 724 * There might be instances where new node is created 725 * before deleting existing node, in which case bsspeer 726 * in vdev will be pointing to the new node. So set 727 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is 728 * pointing to the peer processed for deletion 729 */ 730 wlan_vdev_set_bsspeer(vdev, NULL); 731 } 732 } 733 734 /* remove peer from vdev's peer list */ 735 if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer) 736 == QDF_STATUS_E_FAILURE) { 737 wlan_vdev_obj_unlock(vdev); 738 return QDF_STATUS_E_FAILURE; 739 } 740 /* decrement peer count */ 741 objmgr->wlan_peer_count--; 742 /* decrement pdev peer count */ 743 pdev = wlan_vdev_get_pdev(vdev); 744 wlan_vdev_obj_unlock(vdev); 745 746 wlan_pdev_obj_lock(pdev); 747 wlan_pdev_decr_peer_count(pdev); 748 wlan_pdev_obj_unlock(pdev); 749 750 /* decrement vdev ref count after peer released its reference */ 751 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 752 return QDF_STATUS_SUCCESS; 753 } 754 755 void *wlan_objmgr_vdev_get_comp_private_obj( 756 struct wlan_objmgr_vdev *vdev, 757 enum wlan_umac_comp_id id) 758 { 759 void *comp_priv_obj; 760 761 /* component id is invalid */ 762 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 763 QDF_BUG(0); 764 return NULL; 765 } 766 767 if (vdev == NULL) { 768 QDF_BUG(0); 769 return NULL; 770 } 771 772 comp_priv_obj = vdev->vdev_comp_priv_obj[id]; 773 774 return comp_priv_obj; 775 } 776 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj); 777 778 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, 779 wlan_objmgr_ref_dbgid id) 780 { 781 if (vdev == NULL) { 782 obj_mgr_err("vdev obj is NULL for id:%d", id); 783 QDF_ASSERT(0); 784 return; 785 } 786 /* Increment ref count */ 787 qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); 788 qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); 789 790 return; 791 } 792 qdf_export_symbol(wlan_objmgr_vdev_get_ref); 793 794 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, 795 wlan_objmgr_ref_dbgid id) 796 { 797 uint8_t vdev_id; 798 799 if (vdev == NULL) { 800 obj_mgr_err("vdev obj is NULL for id:%d", id); 801 QDF_ASSERT(0); 802 return QDF_STATUS_E_FAILURE; 803 } 804 805 wlan_vdev_obj_lock(vdev); 806 vdev_id = wlan_vdev_get_id(vdev); 807 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 808 wlan_vdev_obj_unlock(vdev); 809 if (vdev->vdev_objmgr.print_cnt++ <= 810 WLAN_OBJMGR_RATELIMIT_THRESH) 811 obj_mgr_err( 812 "[Ref id: %d] vdev(%d) is not in Created state(%d)", 813 id, vdev_id, vdev->obj_state); 814 815 return QDF_STATUS_E_RESOURCES; 816 } 817 818 /* Increment ref count */ 819 wlan_objmgr_vdev_get_ref(vdev, id); 820 wlan_vdev_obj_unlock(vdev); 821 822 return QDF_STATUS_SUCCESS; 823 } 824 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref); 825 826 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, 827 wlan_objmgr_ref_dbgid id) 828 { 829 uint8_t vdev_id; 830 831 if (vdev == NULL) { 832 obj_mgr_err("vdev obj is NULL for id:%d", id); 833 QDF_ASSERT(0); 834 return; 835 } 836 837 vdev_id = wlan_vdev_get_id(vdev); 838 839 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { 840 obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d", 841 vdev_id, id); 842 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg); 843 WLAN_OBJMGR_BUG(0); 844 } 845 846 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { 847 obj_mgr_err("vdev ref cnt is 0"); 848 WLAN_OBJMGR_BUG(0); 849 return; 850 } 851 qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); 852 853 /* Decrement ref count, free vdev, if ref count == 0 */ 854 if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) 855 wlan_objmgr_vdev_obj_destroy(vdev); 856 857 return; 858 } 859 qdf_export_symbol(wlan_objmgr_vdev_release_ref); 860 861 bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev) 862 { 863 struct wlan_objmgr_peer *peer; 864 enum wlan_peer_state peer_state; 865 866 wlan_vdev_obj_lock(vdev); 867 peer = wlan_vdev_get_bsspeer(vdev); 868 wlan_vdev_obj_unlock(vdev); 869 870 if (!peer) 871 return false; 872 873 wlan_peer_obj_lock(peer); 874 peer_state = wlan_peer_mlme_get_state(peer); 875 wlan_peer_obj_unlock(peer); 876 877 if (peer_state != WLAN_ASSOC_STATE) 878 return false; 879 880 return true; 881 } 882 qdf_export_symbol(wlan_vdev_is_connected); 883