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]) { 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) { 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) { 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) { 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->vdev_nif.osdev); 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) { 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) { 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) 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) 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) { 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) { 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) { 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]) { 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) 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) { 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) { 508 /* Iterate through VDEV's peer list */ 509 peer = wlan_vdev_peer_list_peek_head(peer_list); 510 while (peer) { 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 /** 528 * wlan_obj_vdev_populate_logically_del_peerlist() - get peer 529 * from vdev peer list 530 * @obj_list: peer object list 531 * @vdev_obj: vdev object mgr substructure 532 * @dbg_id: id of the caller 533 * 534 * API to finds peer object pointer by vdev from peer hash list for a node 535 * which is in logically deleted state 536 * 537 * Caller to free the list allocated in this function 538 * 539 * Return: list of peer pointers 540 * NULL on FAILURE 541 */ 542 static qdf_list_t *wlan_obj_vdev_populate_logically_del_peerlist( 543 qdf_list_t *obj_list, 544 struct wlan_objmgr_vdev_objmgr *vdev_obj, 545 wlan_objmgr_ref_dbgid dbg_id) 546 { 547 struct wlan_objmgr_peer *peer; 548 struct wlan_objmgr_peer *peer_next; 549 struct wlan_logically_del_peer *peer_list; 550 qdf_list_t *logical_del_peerlist; 551 bool lock_released = false; 552 553 logical_del_peerlist = qdf_mem_malloc(sizeof(*logical_del_peerlist)); 554 if (!logical_del_peerlist) 555 return NULL; 556 557 qdf_list_create(logical_del_peerlist, vdev_obj->max_peer_count); 558 559 peer = wlan_vdev_peer_list_peek_head(obj_list); 560 while (peer) { 561 wlan_peer_obj_lock(peer); 562 peer_next = wlan_peer_get_next_peer_of_vdev(obj_list, peer); 563 if (peer->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED && 564 qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 565 wlan_objmgr_peer_get_ref(peer, dbg_id); 566 wlan_peer_obj_unlock(peer); 567 lock_released = true; 568 569 peer_list = qdf_mem_malloc(sizeof(*peer_list)); 570 if (!peer_list) { 571 wlan_objmgr_peer_release_ref(peer, dbg_id); 572 WLAN_OBJMGR_BUG(0); 573 break; 574 } 575 576 peer_list->peer = peer; 577 qdf_list_insert_front(logical_del_peerlist, 578 &peer_list->list); 579 } 580 581 if (!lock_released) 582 wlan_peer_obj_unlock(peer); 583 584 peer = peer_next; 585 lock_released = false; 586 } 587 588 /* Not found, return NULL */ 589 if (qdf_list_empty(logical_del_peerlist)) { 590 qdf_mem_free(logical_del_peerlist); 591 return NULL; 592 } 593 594 return logical_del_peerlist; 595 } 596 597 qdf_list_t *wlan_objmgr_vdev_get_log_del_peer_list( 598 struct wlan_objmgr_vdev *vdev, 599 wlan_objmgr_ref_dbgid dbg_id) 600 { 601 qdf_list_t *peer_list; 602 qdf_list_t *log_del_peer_list = NULL; 603 604 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 605 obj_mgr_err("Invalid state vdev:%d state:%d", 606 wlan_vdev_get_id(vdev), vdev->obj_state); 607 return NULL; 608 } 609 610 wlan_vdev_obj_lock(vdev); 611 if (vdev->vdev_objmgr.wlan_peer_count == 0) { 612 wlan_vdev_obj_unlock(vdev); 613 return NULL; 614 } 615 616 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 617 peer_list = &vdev->vdev_objmgr.wlan_peer_list; 618 if (peer_list) { 619 log_del_peer_list = 620 wlan_obj_vdev_populate_logically_del_peerlist( 621 peer_list, &vdev->vdev_objmgr, 622 dbg_id); 623 } 624 625 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 626 wlan_vdev_obj_unlock(vdev); 627 628 return log_del_peer_list; 629 } 630 631 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation( 632 struct wlan_objmgr_vdev *vdev, 633 enum wlan_umac_comp_id id) 634 { 635 wlan_objmgr_vdev_create_handler handler; 636 void *arg; 637 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 638 639 /* Component id is invalid */ 640 if (id >= WLAN_UMAC_MAX_COMPONENTS) 641 return QDF_STATUS_MAXCOMP_FAIL; 642 643 wlan_vdev_obj_lock(vdev); 644 /* 645 * If component object is already created, delete old 646 * component object, then invoke creation 647 */ 648 if (vdev->vdev_comp_priv_obj[id]) { 649 wlan_vdev_obj_unlock(vdev); 650 return QDF_STATUS_E_FAILURE; 651 } 652 wlan_vdev_obj_unlock(vdev); 653 654 /* Invoke registered create handlers */ 655 handler = g_umac_glb_obj->vdev_create_handler[id]; 656 arg = g_umac_glb_obj->vdev_create_handler_arg[id]; 657 if (handler) 658 vdev->obj_status[id] = handler(vdev, arg); 659 else 660 return QDF_STATUS_E_FAILURE; 661 662 /* If object status is created, then only handle this object status */ 663 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 664 /* Derive object status */ 665 obj_status = wlan_objmgr_vdev_object_status(vdev); 666 /* Move PDEV object state to Partially created state */ 667 if (obj_status == QDF_STATUS_COMP_ASYNC) { 668 /*TODO atomic */ 669 vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 670 } 671 } 672 return obj_status; 673 } 674 675 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion( 676 struct wlan_objmgr_vdev *vdev, 677 enum wlan_umac_comp_id id) 678 { 679 wlan_objmgr_vdev_destroy_handler handler; 680 void *arg; 681 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 682 683 /* component id is invalid */ 684 if (id >= WLAN_UMAC_MAX_COMPONENTS) 685 return QDF_STATUS_MAXCOMP_FAIL; 686 687 wlan_vdev_obj_lock(vdev); 688 /* Component object was never created, invalid operation */ 689 if (!vdev->vdev_comp_priv_obj[id]) { 690 wlan_vdev_obj_unlock(vdev); 691 return QDF_STATUS_E_FAILURE; 692 } 693 wlan_vdev_obj_unlock(vdev); 694 695 /* Invoke registered create handlers */ 696 handler = g_umac_glb_obj->vdev_destroy_handler[id]; 697 arg = g_umac_glb_obj->vdev_destroy_handler_arg[id]; 698 if (handler) 699 vdev->obj_status[id] = handler(vdev, arg); 700 else 701 return QDF_STATUS_E_FAILURE; 702 703 /* If object status is created, then only handle this object status */ 704 if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { 705 obj_status = wlan_objmgr_vdev_object_status(vdev); 706 /* move object state to DEL progress */ 707 if (obj_status == QDF_STATUS_COMP_ASYNC) 708 vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 709 } 710 return obj_status; 711 } 712 713 714 715 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list, 716 struct wlan_objmgr_peer *obj) 717 { 718 qdf_list_insert_back(obj_list, &obj->vdev_peer); 719 } 720 721 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list, 722 struct wlan_objmgr_peer *peer) 723 { 724 qdf_list_node_t *vdev_node = NULL; 725 726 if (!peer) 727 return QDF_STATUS_E_FAILURE; 728 /* get vdev list node element */ 729 vdev_node = &peer->vdev_peer; 730 /* list is empty, return failure */ 731 if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) 732 return QDF_STATUS_E_FAILURE; 733 734 return QDF_STATUS_SUCCESS; 735 } 736 737 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, 738 struct wlan_objmgr_peer *peer) 739 { 740 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 741 struct wlan_objmgr_pdev *pdev; 742 enum QDF_OPMODE opmode; 743 744 wlan_vdev_obj_lock(vdev); 745 pdev = wlan_vdev_get_pdev(vdev); 746 /* If Max VDEV peer count exceeds, return failure */ 747 if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) { 748 if (objmgr->wlan_peer_count >= objmgr->max_peer_count) { 749 wlan_vdev_obj_unlock(vdev); 750 return QDF_STATUS_E_FAILURE; 751 } 752 } 753 wlan_vdev_obj_unlock(vdev); 754 755 /* If Max PDEV peer count exceeds, return failure */ 756 wlan_pdev_obj_lock(pdev); 757 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) { 758 if (wlan_pdev_get_temp_peer_count(pdev) >= 759 WLAN_MAX_PDEV_TEMP_PEERS) { 760 wlan_pdev_obj_unlock(pdev); 761 return QDF_STATUS_E_FAILURE; 762 } 763 } else { 764 if (wlan_pdev_get_peer_count(pdev) >= 765 wlan_pdev_get_max_peer_count(pdev)) { 766 wlan_pdev_obj_unlock(pdev); 767 return QDF_STATUS_E_FAILURE; 768 } 769 } 770 771 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 772 wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev)); 773 else 774 wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev)); 775 wlan_pdev_obj_unlock(pdev); 776 777 wlan_vdev_obj_lock(vdev); 778 /* Add peer to vdev's peer list */ 779 wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer); 780 objmgr->wlan_peer_count++; 781 782 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), 783 wlan_vdev_mlme_get_macaddr(vdev)) == 784 QDF_STATUS_SUCCESS) { 785 /* 786 * if peer mac address and vdev mac address match, set 787 * this peer as self peer 788 */ 789 wlan_vdev_set_selfpeer(vdev, peer); 790 opmode = wlan_vdev_mlme_get_opmode(vdev); 791 /* For AP mode, self peer and BSS peer are same */ 792 if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE)) 793 wlan_vdev_set_bsspeer(vdev, peer); 794 } 795 /* set BSS peer for sta */ 796 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE || 797 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) && 798 (wlan_peer_get_peer_type(peer) == WLAN_PEER_AP || 799 wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) 800 wlan_vdev_set_bsspeer(vdev, peer); 801 802 /* Increment vdev ref count to make sure it won't be destroyed before */ 803 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); 804 wlan_vdev_obj_unlock(vdev); 805 return QDF_STATUS_SUCCESS; 806 } 807 808 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev, 809 struct wlan_objmgr_peer *peer) 810 { 811 struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; 812 struct wlan_objmgr_pdev *pdev; 813 814 wlan_vdev_obj_lock(vdev); 815 /* if peer count is 0, return failure */ 816 if (objmgr->wlan_peer_count == 0) { 817 wlan_vdev_obj_unlock(vdev); 818 return QDF_STATUS_E_FAILURE; 819 } 820 821 if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) || 822 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) { 823 if (wlan_vdev_get_selfpeer(vdev) == peer) { 824 /* 825 * There might be instances where new node is created 826 * before deleting existing node, in which case selfpeer 827 * will be pointing to the new node. So set selfpeer to 828 * NULL only if vdev->vdev_objmgr.self_peer is pointing 829 * to the peer processed for deletion 830 */ 831 wlan_vdev_set_selfpeer(vdev, NULL); 832 } 833 834 if (wlan_vdev_get_bsspeer(vdev) == peer) { 835 /* 836 * There might be instances where new node is created 837 * before deleting existing node, in which case bsspeer 838 * in vdev will be pointing to the new node. So set 839 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is 840 * pointing to the peer processed for deletion 841 */ 842 wlan_vdev_set_bsspeer(vdev, NULL); 843 } 844 } 845 846 /* remove peer from vdev's peer list */ 847 if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer) 848 == QDF_STATUS_E_FAILURE) { 849 wlan_vdev_obj_unlock(vdev); 850 return QDF_STATUS_E_FAILURE; 851 } 852 /* decrement peer count */ 853 objmgr->wlan_peer_count--; 854 /* decrement pdev peer count */ 855 pdev = wlan_vdev_get_pdev(vdev); 856 wlan_vdev_obj_unlock(vdev); 857 858 wlan_pdev_obj_lock(pdev); 859 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 860 wlan_pdev_decr_temp_peer_count(pdev); 861 else 862 wlan_pdev_decr_peer_count(pdev); 863 wlan_pdev_obj_unlock(pdev); 864 865 /* decrement vdev ref count after peer released its reference */ 866 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 867 return QDF_STATUS_SUCCESS; 868 } 869 870 struct wlan_objmgr_peer *wlan_objmgr_vdev_try_get_bsspeer( 871 struct wlan_objmgr_vdev *vdev, 872 wlan_objmgr_ref_dbgid id) 873 { 874 struct wlan_objmgr_peer *peer; 875 QDF_STATUS status = QDF_STATUS_E_EMPTY; 876 877 if (!vdev) 878 return NULL; 879 880 wlan_vdev_obj_lock(vdev); 881 peer = wlan_vdev_get_bsspeer(vdev); 882 if (peer) 883 status = wlan_objmgr_peer_try_get_ref(peer, id); 884 wlan_vdev_obj_unlock(vdev); 885 886 if (QDF_IS_STATUS_SUCCESS(status)) 887 return peer; 888 889 return NULL; 890 } 891 892 void *wlan_objmgr_vdev_get_comp_private_obj( 893 struct wlan_objmgr_vdev *vdev, 894 enum wlan_umac_comp_id id) 895 { 896 void *comp_priv_obj; 897 898 /* component id is invalid */ 899 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 900 QDF_BUG(0); 901 return NULL; 902 } 903 904 if (!vdev) { 905 QDF_BUG(0); 906 return NULL; 907 } 908 909 comp_priv_obj = vdev->vdev_comp_priv_obj[id]; 910 911 return comp_priv_obj; 912 } 913 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj); 914 915 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, 916 wlan_objmgr_ref_dbgid id) 917 { 918 if (!vdev) { 919 obj_mgr_err("vdev obj is NULL for id:%d", id); 920 QDF_ASSERT(0); 921 return; 922 } 923 /* Increment ref count */ 924 qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); 925 qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); 926 927 return; 928 } 929 qdf_export_symbol(wlan_objmgr_vdev_get_ref); 930 931 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, 932 wlan_objmgr_ref_dbgid id) 933 { 934 uint8_t vdev_id; 935 936 if (!vdev) { 937 obj_mgr_err("vdev obj is NULL for id:%d", id); 938 QDF_ASSERT(0); 939 return QDF_STATUS_E_FAILURE; 940 } 941 942 wlan_vdev_obj_lock(vdev); 943 vdev_id = wlan_vdev_get_id(vdev); 944 if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { 945 wlan_vdev_obj_unlock(vdev); 946 if (vdev->vdev_objmgr.print_cnt++ <= 947 WLAN_OBJMGR_RATELIMIT_THRESH) 948 obj_mgr_err( 949 "[Ref id: %d] vdev(%d) is not in Created state(%d)", 950 id, vdev_id, vdev->obj_state); 951 952 return QDF_STATUS_E_RESOURCES; 953 } 954 955 /* Increment ref count */ 956 wlan_objmgr_vdev_get_ref(vdev, id); 957 wlan_vdev_obj_unlock(vdev); 958 959 return QDF_STATUS_SUCCESS; 960 } 961 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref); 962 963 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, 964 wlan_objmgr_ref_dbgid id) 965 { 966 uint8_t vdev_id; 967 968 if (!vdev) { 969 obj_mgr_err("vdev obj is NULL for id:%d", id); 970 QDF_ASSERT(0); 971 return; 972 } 973 974 vdev_id = wlan_vdev_get_id(vdev); 975 976 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { 977 obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d", 978 vdev_id, id); 979 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, 980 QDF_TRACE_LEVEL_FATAL); 981 WLAN_OBJMGR_BUG(0); 982 return; 983 } 984 985 if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { 986 obj_mgr_err("vdev ref cnt is 0"); 987 WLAN_OBJMGR_BUG(0); 988 return; 989 } 990 qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); 991 992 /* Decrement ref count, free vdev, if ref count == 0 */ 993 if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) 994 wlan_objmgr_vdev_obj_destroy(vdev); 995 996 return; 997 } 998 qdf_export_symbol(wlan_objmgr_vdev_release_ref); 999 1000 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( 1001 struct wlan_objmgr_pdev *pdev, 1002 qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id) 1003 { 1004 struct wlan_objmgr_vdev *vdev; 1005 qdf_list_node_t *node = NULL; 1006 qdf_list_node_t *prev_node = NULL; 1007 1008 wlan_pdev_obj_lock(pdev); 1009 1010 if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { 1011 wlan_pdev_obj_unlock(pdev); 1012 return NULL; 1013 } 1014 1015 do { 1016 vdev = qdf_container_of(node, struct wlan_objmgr_vdev, 1017 vdev_node); 1018 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == 1019 QDF_STATUS_SUCCESS) { 1020 wlan_pdev_obj_unlock(pdev); 1021 return vdev; 1022 } 1023 1024 prev_node = node; 1025 } while (qdf_list_peek_next(vdev_list, prev_node, &node) == 1026 QDF_STATUS_SUCCESS); 1027 1028 wlan_pdev_obj_unlock(pdev); 1029 1030 return NULL; 1031 } 1032 1033 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( 1034 struct wlan_objmgr_pdev *pdev, 1035 qdf_list_t *vdev_list, 1036 struct wlan_objmgr_vdev *vdev, 1037 wlan_objmgr_ref_dbgid dbg_id) 1038 { 1039 struct wlan_objmgr_vdev *vdev_next; 1040 qdf_list_node_t *node = &vdev->vdev_node; 1041 qdf_list_node_t *prev_node = NULL; 1042 1043 if (!node) 1044 return NULL; 1045 1046 wlan_pdev_obj_lock(pdev); 1047 prev_node = node; 1048 while (qdf_list_peek_next(vdev_list, prev_node, &node) == 1049 QDF_STATUS_SUCCESS) { 1050 vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, 1051 vdev_node); 1052 if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) == 1053 QDF_STATUS_SUCCESS) { 1054 wlan_pdev_obj_unlock(pdev); 1055 return vdev_next; 1056 } 1057 1058 prev_node = node; 1059 } 1060 wlan_pdev_obj_unlock(pdev); 1061 1062 return NULL; 1063 } 1064 1065