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