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