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