1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 /** 20 * DOC: Public APIs to perform operations on Peer object 21 */ 22 #include <wlan_objmgr_cmn.h> 23 #include <wlan_objmgr_global_obj.h> 24 #include <wlan_objmgr_psoc_obj.h> 25 #include <wlan_objmgr_pdev_obj.h> 26 #include <wlan_objmgr_vdev_obj.h> 27 #include <wlan_objmgr_peer_obj.h> 28 #include <wlan_objmgr_debug.h> 29 #include <qdf_mem.h> 30 #include <qdf_module.h> 31 #include "wlan_objmgr_global_obj_i.h" 32 #include "wlan_objmgr_psoc_obj_i.h" 33 #include "wlan_objmgr_pdev_obj_i.h" 34 #include "wlan_objmgr_vdev_obj_i.h" 35 36 37 /** 38 ** APIs to Create/Delete Peer object APIs 39 */ 40 static QDF_STATUS wlan_objmgr_peer_object_status( 41 struct wlan_objmgr_peer *peer) 42 { 43 uint8_t id; 44 QDF_STATUS status = QDF_STATUS_SUCCESS; 45 46 wlan_peer_obj_lock(peer); 47 /* Iterate through all components to derive the object status */ 48 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 49 /* If component disabled, Ignore */ 50 if (peer->obj_status[id] == QDF_STATUS_COMP_DISABLED) 51 continue; 52 /* If component operates in Async, status is Partially created, 53 break */ 54 else if (peer->obj_status[id] == QDF_STATUS_COMP_ASYNC) { 55 if (!peer->peer_comp_priv_obj[id]) { 56 status = QDF_STATUS_COMP_ASYNC; 57 break; 58 } 59 /* If component failed to allocate its object, treat it as 60 failure, complete object need to be cleaned up */ 61 } else if ((peer->obj_status[id] == QDF_STATUS_E_NOMEM) || 62 (peer->obj_status[id] == QDF_STATUS_E_FAILURE)) { 63 obj_mgr_err("Peer comp object(id:%d) alloc fail", id); 64 status = QDF_STATUS_E_FAILURE; 65 break; 66 } 67 } 68 wlan_peer_obj_unlock(peer); 69 return status; 70 } 71 72 static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer) 73 { 74 struct wlan_objmgr_psoc *psoc; 75 struct wlan_objmgr_vdev *vdev; 76 uint8_t *macaddr; 77 uint8_t vdev_id; 78 bool peer_free_notify = true; 79 80 if (!peer) { 81 obj_mgr_err("PEER is NULL"); 82 return QDF_STATUS_E_FAILURE; 83 } 84 85 macaddr = wlan_peer_get_macaddr(peer); 86 87 vdev = wlan_peer_get_vdev(peer); 88 if (!vdev) { 89 obj_mgr_err( 90 "VDEV is NULL for peer("QDF_MAC_ADDR_FMT")", 91 QDF_MAC_ADDR_REF(macaddr)); 92 return QDF_STATUS_E_FAILURE; 93 } 94 95 /* Notify peer free only for non self peer*/ 96 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), 97 wlan_vdev_mlme_get_macaddr(vdev)) == 98 QDF_STATUS_SUCCESS) 99 peer_free_notify = false; 100 101 vdev_id = wlan_vdev_get_id(vdev); 102 103 /* get PSOC from VDEV, if it is NULL, return */ 104 psoc = wlan_vdev_get_psoc(vdev); 105 if (!psoc) { 106 obj_mgr_err( 107 "PSOC is NULL for peer("QDF_MAC_ADDR_FMT")", 108 QDF_MAC_ADDR_REF(macaddr)); 109 return QDF_STATUS_E_FAILURE; 110 } 111 112 /* Decrement ref count for BSS peer, so that BSS peer deletes last*/ 113 if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) || 114 (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP) || 115 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_CLI)) 116 wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev), 117 WLAN_OBJMGR_ID); 118 119 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); 120 121 /* Detach peer from VDEV's peer list */ 122 if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) { 123 obj_mgr_err( 124 "Peer("QDF_MAC_ADDR_FMT") VDEV detach fail, vdev id: %d", 125 QDF_MAC_ADDR_REF(macaddr), vdev_id); 126 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 127 return QDF_STATUS_E_FAILURE; 128 } 129 /* Detach peer from PSOC's peer list */ 130 if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) { 131 obj_mgr_err( 132 "Peer("QDF_MAC_ADDR_FMT") PSOC detach failure", 133 QDF_MAC_ADDR_REF(macaddr)); 134 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 135 return QDF_STATUS_E_FAILURE; 136 } 137 wlan_objmgr_peer_trace_del_ref_list(peer); 138 wlan_objmgr_peer_trace_deinit_lock(peer); 139 qdf_spinlock_destroy(&peer->peer_lock); 140 qdf_mem_free(peer); 141 peer = NULL; 142 143 if (peer_free_notify) 144 wlan_objmgr_vdev_peer_freed_notify(vdev); 145 146 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); 147 148 return QDF_STATUS_SUCCESS; 149 150 } 151 152 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 153 static void 154 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) 155 { 156 uint8_t id; 157 158 for (id = 0; id < WLAN_REF_ID_MAX; id++) 159 qdf_atomic_init(&peer->peer_objmgr.ref_id_dbg[id]); 160 } 161 #else 162 static inline void 163 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) {} 164 #endif 165 166 struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( 167 struct wlan_objmgr_vdev *vdev, 168 enum wlan_peer_type type, 169 uint8_t *macaddr) 170 { 171 struct wlan_objmgr_peer *peer; 172 struct wlan_objmgr_psoc *psoc; 173 wlan_objmgr_peer_create_handler handler; 174 wlan_objmgr_peer_status_handler stat_handler; 175 void *arg; 176 QDF_STATUS obj_status; 177 uint8_t id; 178 179 if (!vdev) { 180 obj_mgr_err( 181 "VDEV is NULL for peer ("QDF_MAC_ADDR_FMT")", 182 QDF_MAC_ADDR_REF(macaddr)); 183 return NULL; 184 } 185 /* Get psoc, if psoc is NULL, return */ 186 psoc = wlan_vdev_get_psoc(vdev); 187 if (!psoc) { 188 obj_mgr_err( 189 "PSOC is NULL for peer ("QDF_MAC_ADDR_FMT")", 190 QDF_MAC_ADDR_REF(macaddr)); 191 return NULL; 192 } 193 /* Allocate memory for peer object */ 194 peer = qdf_mem_malloc(sizeof(*peer)); 195 if (!peer) 196 return NULL; 197 198 peer->obj_state = WLAN_OBJ_STATE_ALLOCATED; 199 qdf_atomic_init(&peer->peer_objmgr.ref_cnt); 200 wlan_objmgr_peer_init_ref_id_debug(peer); 201 wlan_objmgr_peer_trace_init_lock(peer); 202 wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID); 203 /* set vdev to peer */ 204 wlan_peer_set_vdev(peer, vdev); 205 /* set peer type */ 206 wlan_peer_set_peer_type(peer, type); 207 /* set mac address of peer */ 208 wlan_peer_set_macaddr(peer, macaddr); 209 /* initialize peer state */ 210 wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE); 211 wlan_peer_mlme_reset_seq_num(peer); 212 peer->peer_objmgr.print_cnt = 0; 213 214 qdf_spinlock_create(&peer->peer_lock); 215 /* Attach peer to psoc, psoc maintains the node table for the device */ 216 if (wlan_objmgr_psoc_peer_attach(psoc, peer) != 217 QDF_STATUS_SUCCESS) { 218 obj_mgr_warn( 219 "Peer("QDF_MAC_ADDR_FMT") PSOC attach failure", 220 QDF_MAC_ADDR_REF(macaddr)); 221 qdf_spinlock_destroy(&peer->peer_lock); 222 wlan_objmgr_peer_trace_deinit_lock(peer); 223 qdf_mem_free(peer); 224 return NULL; 225 } 226 /* Attach peer to vdev peer table */ 227 if (wlan_objmgr_vdev_peer_attach(vdev, peer) != 228 QDF_STATUS_SUCCESS) { 229 obj_mgr_warn( 230 "Peer("QDF_MAC_ADDR_FMT") VDEV attach failure", 231 QDF_MAC_ADDR_REF(macaddr)); 232 /* if attach fails, detach from psoc table before free */ 233 wlan_objmgr_psoc_peer_detach(psoc, peer); 234 qdf_spinlock_destroy(&peer->peer_lock); 235 wlan_objmgr_peer_trace_deinit_lock(peer); 236 qdf_mem_free(peer); 237 return NULL; 238 } 239 wlan_peer_set_pdev_id(peer, wlan_objmgr_pdev_get_pdev_id( 240 wlan_vdev_get_pdev(vdev))); 241 /* Increment ref count for BSS peer, so that BSS peer deletes last*/ 242 if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP) 243 || (type == WLAN_PEER_P2P_CLI)) 244 wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev), 245 WLAN_OBJMGR_ID); 246 /* TODO init other parameters */ 247 /* Invoke registered create handlers */ 248 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 249 handler = g_umac_glb_obj->peer_create_handler[id]; 250 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 251 if (handler) 252 peer->obj_status[id] = handler(peer, arg); 253 else 254 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; 255 } 256 /* derive the object status */ 257 obj_status = wlan_objmgr_peer_object_status(peer); 258 /* If SUCCESS, Object is created */ 259 if (obj_status == QDF_STATUS_SUCCESS) { 260 peer->obj_state = WLAN_OBJ_STATE_CREATED; 261 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 262 stat_handler = g_umac_glb_obj->peer_status_handler[id]; 263 arg = g_umac_glb_obj->peer_status_handler_arg[id]; 264 if (stat_handler) 265 stat_handler(peer, arg, 266 QDF_STATUS_SUCCESS); 267 } 268 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 269 /* If any component operates in different context, update it 270 as partially created */ 271 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 272 } else if (obj_status == QDF_STATUS_E_FAILURE) { 273 /* Clean up the peer */ 274 obj_mgr_err( 275 "Peer("QDF_MAC_ADDR_FMT") comp object alloc fail", 276 QDF_MAC_ADDR_REF(macaddr)); 277 wlan_objmgr_peer_obj_delete(peer); 278 return NULL; 279 } 280 281 obj_mgr_debug("Created peer " QDF_MAC_ADDR_FMT " type %d", 282 QDF_MAC_ADDR_REF(macaddr), type); 283 284 return peer; 285 } 286 287 static QDF_STATUS 288 __wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) 289 { 290 uint8_t id; 291 wlan_objmgr_peer_destroy_handler handler; 292 QDF_STATUS obj_status; 293 void *arg; 294 uint8_t *macaddr; 295 296 if (!peer) { 297 obj_mgr_err("PEER is NULL"); 298 return QDF_STATUS_E_FAILURE; 299 } 300 wlan_objmgr_notify_destroy(peer, WLAN_PEER_OP); 301 302 macaddr = wlan_peer_get_macaddr(peer); 303 304 obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_FMT, 305 QDF_MAC_ADDR_REF(macaddr)); 306 307 if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 308 obj_mgr_err("PEER object del is not invoked obj_state:%d peer " 309 QDF_MAC_ADDR_FMT, peer->obj_state, 310 QDF_MAC_ADDR_REF(macaddr)); 311 WLAN_OBJMGR_BUG(0); 312 } 313 314 /* Invoke registered destroy handlers */ 315 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 316 handler = g_umac_glb_obj->peer_destroy_handler[id]; 317 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 318 if (handler && 319 (peer->obj_status[id] == QDF_STATUS_SUCCESS || 320 peer->obj_status[id] == QDF_STATUS_COMP_ASYNC)) 321 peer->obj_status[id] = handler(peer, arg); 322 else 323 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; 324 } 325 /* Derive the object status */ 326 obj_status = wlan_objmgr_peer_object_status(peer); 327 if (obj_status == QDF_STATUS_E_FAILURE) { 328 /* If it status is failure, memory will not be freed */ 329 QDF_BUG(0); 330 return QDF_STATUS_E_FAILURE; 331 } 332 /* few components deletion is in progress */ 333 if (obj_status == QDF_STATUS_COMP_ASYNC) { 334 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 335 return QDF_STATUS_COMP_ASYNC; 336 } 337 338 /* Free the peer object */ 339 return wlan_objmgr_peer_obj_free(peer); 340 } 341 342 #ifdef FEATURE_DELAYED_PEER_OBJ_DESTROY 343 /* 344 * Length of the list used to hold delayed peer obj free. 345 * Must be a multiple of 2. 346 */ 347 #define MAX_DELAYED_FREE_PEERS 64 348 349 /** 350 * wlan_objmgr_peer_obj_free_work() - Peer obj freed in the delayed work 351 * @data: PDEV object 352 * 353 * Peer obj freed in the delayed work 354 * 355 * Return: None 356 */ 357 static void wlan_objmgr_peer_obj_free_work(void *data) 358 { 359 struct wlan_objmgr_pdev *pdev = data; 360 struct wlan_objmgr_peer *peer; 361 qdf_list_node_t *node; 362 uint8_t *macaddr; 363 364 if (!pdev) { 365 obj_mgr_err("pdev is NULL"); 366 return; 367 } 368 369 qdf_spin_lock_bh(&pdev->peer_free_lock); 370 while (!(qdf_list_empty(&pdev->peer_free_list))) { 371 qdf_list_remove_front(&pdev->peer_free_list, &node); 372 qdf_spin_unlock_bh(&pdev->peer_free_lock); 373 374 peer = qdf_container_of(node, 375 struct wlan_objmgr_peer, 376 free_node); 377 378 macaddr = wlan_peer_get_macaddr(peer); 379 obj_mgr_debug("active_work_cnt %u list size %u peer 0x%pK(" 380 QDF_MAC_ADDR_FMT ")", 381 pdev->active_work_cnt, 382 qdf_list_size(&pdev->peer_free_list), 383 peer, 384 QDF_MAC_ADDR_REF(macaddr)); 385 386 __wlan_objmgr_peer_obj_destroy(peer); 387 388 qdf_spin_lock_bh(&pdev->peer_free_lock); 389 } 390 391 pdev->active_work_cnt--; 392 393 qdf_spin_unlock_bh(&pdev->peer_free_lock); 394 } 395 396 /** 397 * wlan_peer_obj_free_enqueue() - enqueue freed peer into kworker 398 * @peer: PEER object 399 * 400 * Enqueue freed peer into kworker 401 * 402 * Return: None 403 */ 404 static QDF_STATUS 405 wlan_peer_obj_free_enqueue(struct wlan_objmgr_peer *peer) 406 { 407 struct wlan_objmgr_vdev *vdev; 408 struct wlan_objmgr_pdev *pdev; 409 uint8_t *macaddr; 410 411 if (!peer) { 412 obj_mgr_err("peer is NULL"); 413 return QDF_STATUS_E_FAILURE; 414 } 415 416 macaddr = wlan_peer_get_macaddr(peer); 417 418 vdev = wlan_peer_get_vdev(peer); 419 if (!vdev) { 420 obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")", 421 QDF_MAC_ADDR_REF(macaddr)); 422 return QDF_STATUS_E_FAILURE; 423 } 424 /* get PDEV from VDEV, if it is NULL, return */ 425 pdev = wlan_vdev_get_pdev(vdev); 426 if (!pdev) { 427 obj_mgr_err("PDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")", 428 QDF_MAC_ADDR_REF(macaddr)); 429 return QDF_STATUS_E_FAILURE; 430 } 431 432 qdf_spin_lock_bh(&pdev->peer_free_lock); 433 qdf_list_insert_back(&pdev->peer_free_list, &peer->free_node); 434 pdev->active_work_cnt++; 435 qdf_spin_unlock_bh(&pdev->peer_free_lock); 436 437 obj_mgr_debug("active_work_cnt %u list size %u peer 0x%pK(" 438 QDF_MAC_ADDR_FMT ")", 439 pdev->active_work_cnt, 440 qdf_list_size(&pdev->peer_free_list), 441 peer, 442 QDF_MAC_ADDR_REF(macaddr)); 443 444 qdf_sched_work(0, &pdev->peer_obj_free_work); 445 446 return QDF_STATUS_SUCCESS; 447 } 448 449 static QDF_STATUS 450 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) 451 { 452 QDF_STATUS status; 453 454 status = wlan_peer_obj_free_enqueue(peer); 455 if (status != QDF_STATUS_SUCCESS) { 456 obj_mgr_warn("enqueue failure, call free obj directly"); 457 status = __wlan_objmgr_peer_obj_destroy(peer); 458 } 459 460 return status; 461 } 462 463 /** 464 * wlan_delayed_peer_obj_free_init() - Init for delayed peer obj freed queue 465 * @data: PDEV object 466 * 467 * Initialize main data structures to process peer obj destroy in a delayed 468 * workqueue. 469 * 470 * Return: QDF_STATUS_SUCCESS on success else a QDF error. 471 */ 472 QDF_STATUS wlan_delayed_peer_obj_free_init(void *data) 473 { 474 struct wlan_objmgr_pdev *pdev = data; 475 476 if (!pdev) { 477 obj_mgr_err("pdev is NULL"); 478 return QDF_STATUS_E_FAILURE; 479 } 480 481 qdf_spinlock_create(&pdev->peer_free_lock); 482 qdf_create_work(0, &pdev->peer_obj_free_work, 483 wlan_objmgr_peer_obj_free_work, 484 (void *)pdev); 485 pdev->active_work_cnt = 0; 486 487 /* Initialize PDEV's peer free list, assign default values */ 488 qdf_list_create(&pdev->peer_free_list, MAX_DELAYED_FREE_PEERS); 489 490 obj_mgr_debug("Delayed peer obj free init successfully"); 491 492 return QDF_STATUS_SUCCESS; 493 } 494 495 /** 496 * wlan_delayed_peer_obj_free_deinit() - De-Init delayed peer freed processing 497 * @data: PDEV object 498 * 499 * De-initialize main data structures to process peer obj freed in a delayed 500 * workqueue. 501 * 502 * Return: QDF_STATUS_SUCCESS on success else a QDF error. 503 */ 504 QDF_STATUS wlan_delayed_peer_obj_free_deinit(void *data) 505 { 506 struct wlan_objmgr_pdev *pdev = data; 507 508 if (!pdev) { 509 obj_mgr_err("pdev is NULL"); 510 return QDF_STATUS_E_FAILURE; 511 } 512 513 qdf_destroy_work(0, &pdev->peer_obj_free_work); 514 qdf_spinlock_destroy(&pdev->peer_free_lock); 515 516 obj_mgr_debug("Deinit successfully, active_work_cnt=%u", 517 pdev->active_work_cnt); 518 519 return QDF_STATUS_SUCCESS; 520 } 521 #else 522 static QDF_STATUS 523 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) 524 { 525 return __wlan_objmgr_peer_obj_destroy(peer); 526 } 527 #endif 528 529 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) 530 { 531 uint8_t print_idx; 532 uint8_t *macaddr; 533 534 if (!peer) { 535 obj_mgr_err("PEER is NULL"); 536 return QDF_STATUS_E_FAILURE; 537 } 538 539 wlan_peer_obj_lock(peer); 540 macaddr = wlan_peer_get_macaddr(peer); 541 wlan_peer_obj_unlock(peer); 542 543 obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_FMT, 544 QDF_MAC_ADDR_REF(macaddr)); 545 546 print_idx = qdf_get_pidx(); 547 wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG); 548 /** 549 * Update VDEV object state to LOGICALLY DELETED 550 * It prevents further access of this object 551 */ 552 wlan_peer_obj_lock(peer); 553 peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 554 wlan_peer_obj_unlock(peer); 555 wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP); 556 wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID); 557 558 return QDF_STATUS_SUCCESS; 559 } 560 qdf_export_symbol(wlan_objmgr_peer_obj_delete); 561 /** 562 ** APIs to attach/detach component objects 563 */ 564 QDF_STATUS wlan_objmgr_peer_component_obj_attach( 565 struct wlan_objmgr_peer *peer, 566 enum wlan_umac_comp_id id, 567 void *comp_priv_obj, 568 QDF_STATUS status) 569 { 570 wlan_objmgr_peer_status_handler s_hler; 571 void *arg; 572 uint8_t i; 573 QDF_STATUS obj_status; 574 575 /* component id is invalid */ 576 if (id >= WLAN_UMAC_MAX_COMPONENTS) 577 return QDF_STATUS_MAXCOMP_FAIL; 578 579 wlan_peer_obj_lock(peer); 580 /* If there is a valid entry, return failure, 581 valid object needs to be freed first */ 582 if (peer->peer_comp_priv_obj[id]) { 583 wlan_peer_obj_unlock(peer); 584 return QDF_STATUS_E_FAILURE; 585 } 586 /* Assign component object private pointer(can be NULL also), status */ 587 peer->peer_comp_priv_obj[id] = comp_priv_obj; 588 peer->obj_status[id] = status; 589 wlan_peer_obj_unlock(peer); 590 591 if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 592 return QDF_STATUS_SUCCESS; 593 594 /* If PEER object status is partially created means, this API is 595 invoked with differnt context. this block should be executed for async 596 components only */ 597 /* Derive status */ 598 obj_status = wlan_objmgr_peer_object_status(peer); 599 /* STATUS_SUCCESS means, object is CREATED */ 600 if (obj_status == QDF_STATUS_SUCCESS) 601 peer->obj_state = WLAN_OBJ_STATE_CREATED; 602 /* update state as CREATION failed, caller has to delete the 603 PEER object */ 604 else if (obj_status == QDF_STATUS_E_FAILURE) 605 peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 606 /* Notify components about the CREATION success/failure */ 607 if ((obj_status == QDF_STATUS_SUCCESS) || 608 (obj_status == QDF_STATUS_E_FAILURE)) { 609 /* nofity object status */ 610 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 611 s_hler = g_umac_glb_obj->peer_status_handler[i]; 612 arg = g_umac_glb_obj->peer_status_handler_arg[i]; 613 if (s_hler) 614 s_hler(peer, arg, obj_status); 615 } 616 } 617 return QDF_STATUS_SUCCESS; 618 } 619 620 qdf_export_symbol(wlan_objmgr_peer_component_obj_attach); 621 622 QDF_STATUS wlan_objmgr_peer_component_obj_detach( 623 struct wlan_objmgr_peer *peer, 624 enum wlan_umac_comp_id id, 625 void *comp_priv_obj) 626 { 627 QDF_STATUS obj_status; 628 629 /* component id is invalid */ 630 if (id >= WLAN_UMAC_MAX_COMPONENTS) 631 return QDF_STATUS_MAXCOMP_FAIL; 632 633 wlan_peer_obj_lock(peer); 634 /* If there is a invalid entry, return failure */ 635 if (peer->peer_comp_priv_obj[id] != comp_priv_obj) { 636 peer->obj_status[id] = QDF_STATUS_E_FAILURE; 637 wlan_peer_obj_unlock(peer); 638 return QDF_STATUS_E_FAILURE; 639 } 640 /* Reset the pointer to NULL */ 641 peer->peer_comp_priv_obj[id] = NULL; 642 peer->obj_status[id] = QDF_STATUS_SUCCESS; 643 wlan_peer_obj_unlock(peer); 644 645 /* If PEER object status is partially destroyed means, this API is 646 invoked with differnt context, this block should be executed for async 647 components only */ 648 if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 649 (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 650 /* Derive object status */ 651 obj_status = wlan_objmgr_peer_object_status(peer); 652 if (obj_status == QDF_STATUS_SUCCESS) { 653 /*Update the status as Deleted, if full object 654 deletion is in progress */ 655 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 656 peer->obj_state = WLAN_OBJ_STATE_DELETED; 657 /* Move to creation state, since this component 658 deletion alone requested */ 659 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 660 peer->obj_state = WLAN_OBJ_STATE_CREATED; 661 /* Object status is failure */ 662 } else if (obj_status == QDF_STATUS_E_FAILURE) { 663 /*Update the status as Deletion failed, if full object 664 deletion is in progress */ 665 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 666 peer->obj_state = 667 WLAN_OBJ_STATE_DELETION_FAILED; 668 /* Move to creation state, since this component 669 deletion alone requested (do not block other 670 components) */ 671 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 672 peer->obj_state = WLAN_OBJ_STATE_CREATED; 673 } 674 675 /* Delete peer object */ 676 if ((obj_status == QDF_STATUS_SUCCESS) && 677 (peer->obj_state == WLAN_OBJ_STATE_DELETED)) { 678 /* Free the peer object */ 679 return wlan_objmgr_peer_obj_free(peer); 680 } 681 } 682 683 return QDF_STATUS_SUCCESS; 684 } 685 686 qdf_export_symbol(wlan_objmgr_peer_component_obj_detach); 687 688 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation( 689 struct wlan_objmgr_peer *peer, 690 enum wlan_umac_comp_id id) 691 { 692 wlan_objmgr_peer_create_handler handler; 693 void *arg; 694 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 695 696 /* Component id is invalid */ 697 if (id >= WLAN_UMAC_MAX_COMPONENTS) 698 return QDF_STATUS_MAXCOMP_FAIL; 699 700 wlan_peer_obj_lock(peer); 701 /* If component object is already created, delete old 702 component object, then invoke creation */ 703 if (peer->peer_comp_priv_obj[id]) { 704 wlan_peer_obj_unlock(peer); 705 return QDF_STATUS_E_FAILURE; 706 } 707 wlan_peer_obj_unlock(peer); 708 709 /* Invoke registered create handlers */ 710 handler = g_umac_glb_obj->peer_create_handler[id]; 711 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 712 if (handler) 713 peer->obj_status[id] = handler(peer, arg); 714 else 715 return QDF_STATUS_E_FAILURE; 716 717 /* If object status is created, then only handle this object status */ 718 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 719 /* Derive object status */ 720 obj_status = wlan_objmgr_peer_object_status(peer); 721 /* Move PDEV object state to Partially created state */ 722 if (obj_status == QDF_STATUS_COMP_ASYNC) { 723 /*TODO atomic */ 724 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 725 } 726 } 727 728 return obj_status; 729 } 730 731 732 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion( 733 struct wlan_objmgr_peer *peer, 734 enum wlan_umac_comp_id id) 735 { 736 wlan_objmgr_peer_destroy_handler handler; 737 void *arg; 738 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 739 740 /* component id is invalid */ 741 if (id >= WLAN_UMAC_MAX_COMPONENTS) 742 return QDF_STATUS_MAXCOMP_FAIL; 743 744 wlan_peer_obj_lock(peer); 745 /* Component object was never created, invalid operation */ 746 if (!peer->peer_comp_priv_obj[id]) { 747 wlan_peer_obj_unlock(peer); 748 return QDF_STATUS_E_FAILURE; 749 } 750 751 wlan_peer_obj_unlock(peer); 752 753 /* Invoke registered destroy handlers */ 754 handler = g_umac_glb_obj->peer_destroy_handler[id]; 755 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 756 if (handler) 757 peer->obj_status[id] = handler(peer, arg); 758 else 759 return QDF_STATUS_E_FAILURE; 760 761 /* If object status is created, then only handle this object status */ 762 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 763 obj_status = wlan_objmgr_peer_object_status(peer); 764 /* move object state to DEL progress */ 765 if (obj_status == QDF_STATUS_COMP_ASYNC) 766 peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 767 } 768 return obj_status; 769 } 770 771 void *wlan_objmgr_peer_get_comp_private_obj( 772 struct wlan_objmgr_peer *peer, 773 enum wlan_umac_comp_id id) 774 { 775 void *comp_priv_obj; 776 777 /* component id is invalid */ 778 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 779 QDF_BUG(0); 780 return NULL; 781 } 782 783 if (!peer) { 784 QDF_BUG(0); 785 return NULL; 786 } 787 788 comp_priv_obj = peer->peer_comp_priv_obj[id]; 789 return comp_priv_obj; 790 } 791 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj); 792 793 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 794 static inline void 795 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, 796 wlan_objmgr_ref_dbgid id) 797 { 798 qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]); 799 } 800 #else 801 static inline void 802 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, 803 wlan_objmgr_ref_dbgid id) {} 804 #endif 805 806 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 807 static QDF_STATUS 808 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, 809 wlan_objmgr_ref_dbgid id) 810 { 811 if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) { 812 uint8_t *macaddr; 813 814 macaddr = wlan_peer_get_macaddr(peer); 815 obj_mgr_err( 816 "peer("QDF_MAC_ADDR_FMT") ref was not taken by %d", 817 QDF_MAC_ADDR_REF(macaddr), id); 818 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, 819 QDF_TRACE_LEVEL_FATAL); 820 WLAN_OBJMGR_BUG(0); 821 return QDF_STATUS_E_FAILURE; 822 } 823 824 qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]); 825 return QDF_STATUS_SUCCESS; 826 } 827 #else 828 static QDF_STATUS 829 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, 830 wlan_objmgr_ref_dbgid id) 831 { 832 return QDF_STATUS_SUCCESS; 833 } 834 #endif 835 836 #ifdef WLAN_OBJMGR_REF_ID_TRACE 837 static inline void 838 wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer *peer, 839 wlan_objmgr_ref_dbgid id, 840 const char *func, int line) 841 { 842 struct wlan_objmgr_trace *trace; 843 844 trace = &peer->peer_objmgr.trace; 845 846 if (func) 847 wlan_objmgr_trace_ref(&trace->references[id].head, 848 trace, func, line); 849 } 850 851 static inline void 852 wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer *peer, 853 wlan_objmgr_ref_dbgid id, 854 const char *func, int line) 855 { 856 struct wlan_objmgr_trace *trace; 857 858 trace = &peer->peer_objmgr.trace; 859 if (func) 860 wlan_objmgr_trace_ref(&trace->dereferences[id].head, 861 trace, func, line); 862 } 863 #endif 864 865 #ifdef WLAN_OBJMGR_REF_ID_TRACE 866 void wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer *peer, 867 wlan_objmgr_ref_dbgid id, 868 const char *func, int line) 869 { 870 if (!peer) { 871 obj_mgr_err("peer obj is NULL for %d", id); 872 QDF_ASSERT(0); 873 return; 874 } 875 /* Increment ref count */ 876 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); 877 wlan_objmgr_peer_get_debug_id_ref(peer, id); 878 879 wlan_objmgr_peer_ref_trace(peer, id, func, line); 880 return; 881 } 882 883 qdf_export_symbol(wlan_objmgr_peer_get_ref_debug); 884 #else 885 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, 886 wlan_objmgr_ref_dbgid id) 887 { 888 if (!peer) { 889 obj_mgr_err("peer obj is NULL for %d", id); 890 QDF_ASSERT(0); 891 return; 892 } 893 /* Increment ref count */ 894 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); 895 wlan_objmgr_peer_get_debug_id_ref(peer, id); 896 } 897 898 qdf_export_symbol(wlan_objmgr_peer_get_ref); 899 #endif 900 901 #ifdef WLAN_OBJMGR_REF_ID_TRACE 902 QDF_STATUS wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer *peer, 903 wlan_objmgr_ref_dbgid id, 904 const char *func, int line) 905 { 906 if (!peer) { 907 obj_mgr_err("peer obj is NULL for %d", id); 908 QDF_ASSERT(0); 909 return QDF_STATUS_E_FAILURE; 910 } 911 912 wlan_peer_obj_lock(peer); 913 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) { 914 wlan_peer_obj_unlock(peer); 915 if (peer->peer_objmgr.print_cnt++ <= 916 WLAN_OBJMGR_RATELIMIT_THRESH) { 917 uint8_t *macaddr; 918 919 macaddr = wlan_peer_get_macaddr(peer); 920 obj_mgr_debug( 921 "peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)", 922 QDF_MAC_ADDR_REF(macaddr), 923 peer->obj_state); 924 } 925 return QDF_STATUS_E_RESOURCES; 926 } 927 928 wlan_objmgr_peer_get_ref_debug(peer, id, func, line); 929 wlan_peer_obj_unlock(peer); 930 931 return QDF_STATUS_SUCCESS; 932 } 933 934 qdf_export_symbol(wlan_objmgr_peer_try_get_ref_debug); 935 #else 936 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, 937 wlan_objmgr_ref_dbgid id) 938 { 939 if (!peer) { 940 obj_mgr_err("peer obj is NULL for %d", id); 941 QDF_ASSERT(0); 942 return QDF_STATUS_E_FAILURE; 943 } 944 945 wlan_peer_obj_lock(peer); 946 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) { 947 wlan_peer_obj_unlock(peer); 948 if (peer->peer_objmgr.print_cnt++ <= 949 WLAN_OBJMGR_RATELIMIT_THRESH) { 950 uint8_t *macaddr; 951 952 macaddr = wlan_peer_get_macaddr(peer); 953 obj_mgr_debug( 954 "peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)", 955 QDF_MAC_ADDR_REF(macaddr), 956 peer->obj_state); 957 } 958 return QDF_STATUS_E_RESOURCES; 959 } 960 961 wlan_objmgr_peer_get_ref(peer, id); 962 wlan_peer_obj_unlock(peer); 963 964 return QDF_STATUS_SUCCESS; 965 } 966 967 qdf_export_symbol(wlan_objmgr_peer_try_get_ref); 968 #endif 969 970 #ifdef WLAN_OBJMGR_REF_ID_TRACE 971 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc_debug( 972 struct wlan_peer_list *peer_list, 973 uint8_t hash_index, 974 struct wlan_objmgr_peer *peer, 975 wlan_objmgr_ref_dbgid dbg_id, 976 const char *func, int line) 977 { 978 struct wlan_objmgr_peer *peer_next = NULL; 979 qdf_list_node_t *psoc_node = NULL; 980 qdf_list_node_t *prev_psoc_node = NULL; 981 qdf_list_t *obj_list; 982 983 qdf_spin_lock_bh(&peer_list->peer_list_lock); 984 obj_list = &peer_list->peer_hash[hash_index]; 985 986 prev_psoc_node = &peer->psoc_peer; 987 while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 988 QDF_STATUS_SUCCESS) { 989 peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 990 psoc_peer); 991 992 if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id, 993 func, line) == 994 QDF_STATUS_SUCCESS) { 995 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 996 return peer_next; 997 } 998 999 prev_psoc_node = psoc_node; 1000 } 1001 1002 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1003 1004 return NULL; 1005 } 1006 #else 1007 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( 1008 struct wlan_peer_list *peer_list, 1009 uint8_t hash_index, 1010 struct wlan_objmgr_peer *peer, 1011 wlan_objmgr_ref_dbgid dbg_id) 1012 { 1013 struct wlan_objmgr_peer *peer_next = NULL; 1014 qdf_list_node_t *psoc_node = NULL; 1015 qdf_list_node_t *prev_psoc_node = NULL; 1016 qdf_list_t *obj_list; 1017 1018 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1019 obj_list = &peer_list->peer_hash[hash_index]; 1020 1021 prev_psoc_node = &peer->psoc_peer; 1022 while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 1023 QDF_STATUS_SUCCESS) { 1024 peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 1025 psoc_peer); 1026 1027 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == 1028 QDF_STATUS_SUCCESS) { 1029 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1030 return peer_next; 1031 } 1032 1033 prev_psoc_node = psoc_node; 1034 } 1035 1036 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1037 1038 return NULL; 1039 } 1040 #endif 1041 1042 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1043 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head_debug( 1044 struct wlan_objmgr_vdev *vdev, 1045 qdf_list_t *peer_list, 1046 wlan_objmgr_ref_dbgid dbg_id, 1047 const char *func, int line) 1048 { 1049 struct wlan_objmgr_peer *peer; 1050 qdf_list_node_t *vdev_node = NULL; 1051 qdf_list_node_t *prev_vdev_node = NULL; 1052 1053 wlan_vdev_obj_lock(vdev); 1054 1055 if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) { 1056 wlan_vdev_obj_unlock(vdev); 1057 return NULL; 1058 } 1059 1060 do { 1061 peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 1062 vdev_peer); 1063 1064 if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id, 1065 func, line) == 1066 QDF_STATUS_SUCCESS) { 1067 wlan_vdev_obj_unlock(vdev); 1068 return peer; 1069 } 1070 1071 prev_vdev_node = vdev_node; 1072 } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 1073 QDF_STATUS_SUCCESS); 1074 1075 wlan_vdev_obj_unlock(vdev); 1076 1077 return NULL; 1078 } 1079 #else 1080 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head( 1081 struct wlan_objmgr_vdev *vdev, 1082 qdf_list_t *peer_list, 1083 wlan_objmgr_ref_dbgid dbg_id) 1084 { 1085 struct wlan_objmgr_peer *peer; 1086 qdf_list_node_t *vdev_node = NULL; 1087 qdf_list_node_t *prev_vdev_node = NULL; 1088 1089 wlan_vdev_obj_lock(vdev); 1090 1091 if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) { 1092 wlan_vdev_obj_unlock(vdev); 1093 return NULL; 1094 } 1095 1096 do { 1097 peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 1098 vdev_peer); 1099 1100 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 1101 QDF_STATUS_SUCCESS) { 1102 wlan_vdev_obj_unlock(vdev); 1103 return peer; 1104 } 1105 1106 prev_vdev_node = vdev_node; 1107 } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 1108 QDF_STATUS_SUCCESS); 1109 1110 wlan_vdev_obj_unlock(vdev); 1111 1112 return NULL; 1113 } 1114 #endif 1115 1116 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1117 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev_debug( 1118 struct wlan_objmgr_vdev *vdev, 1119 qdf_list_t *peer_list, 1120 struct wlan_objmgr_peer *peer, 1121 wlan_objmgr_ref_dbgid dbg_id, 1122 const char *func, int line) 1123 { 1124 struct wlan_objmgr_peer *peer_next; 1125 qdf_list_node_t *vdev_node = NULL; 1126 qdf_list_node_t *prev_vdev_node = NULL; 1127 1128 if (!peer) 1129 return NULL; 1130 1131 wlan_vdev_obj_lock(vdev); 1132 1133 prev_vdev_node = &peer->vdev_peer; 1134 while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 1135 QDF_STATUS_SUCCESS) { 1136 peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 1137 vdev_peer); 1138 1139 if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id, 1140 func, line) == 1141 QDF_STATUS_SUCCESS) { 1142 wlan_vdev_obj_unlock(vdev); 1143 return peer_next; 1144 } 1145 1146 prev_vdev_node = vdev_node; 1147 } 1148 1149 wlan_vdev_obj_unlock(vdev); 1150 1151 return NULL; 1152 } 1153 #else 1154 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev( 1155 struct wlan_objmgr_vdev *vdev, 1156 qdf_list_t *peer_list, 1157 struct wlan_objmgr_peer *peer, 1158 wlan_objmgr_ref_dbgid dbg_id) 1159 { 1160 struct wlan_objmgr_peer *peer_next; 1161 qdf_list_node_t *vdev_node = NULL; 1162 qdf_list_node_t *prev_vdev_node = NULL; 1163 1164 if (!peer) 1165 return NULL; 1166 1167 wlan_vdev_obj_lock(vdev); 1168 1169 prev_vdev_node = &peer->vdev_peer; 1170 while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 1171 QDF_STATUS_SUCCESS) { 1172 peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 1173 vdev_peer); 1174 1175 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == 1176 QDF_STATUS_SUCCESS) { 1177 wlan_vdev_obj_unlock(vdev); 1178 return peer_next; 1179 } 1180 1181 prev_vdev_node = vdev_node; 1182 } 1183 1184 wlan_vdev_obj_unlock(vdev); 1185 1186 return NULL; 1187 } 1188 #endif 1189 1190 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1191 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head_debug( 1192 struct wlan_peer_list *peer_list, 1193 uint8_t hash_index, 1194 wlan_objmgr_ref_dbgid dbg_id, 1195 const char *func, int line) 1196 { 1197 struct wlan_objmgr_peer *peer; 1198 qdf_list_node_t *psoc_node = NULL; 1199 qdf_list_node_t *prev_psoc_node = NULL; 1200 qdf_list_t *obj_list; 1201 1202 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1203 obj_list = &peer_list->peer_hash[hash_index]; 1204 1205 if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) { 1206 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1207 return NULL; 1208 } 1209 1210 do { 1211 peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 1212 psoc_peer); 1213 if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id, 1214 func, line) == 1215 QDF_STATUS_SUCCESS) { 1216 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1217 return peer; 1218 } 1219 1220 prev_psoc_node = psoc_node; 1221 } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 1222 QDF_STATUS_SUCCESS); 1223 1224 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1225 return NULL; 1226 } 1227 #else 1228 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( 1229 struct wlan_peer_list *peer_list, 1230 uint8_t hash_index, 1231 wlan_objmgr_ref_dbgid dbg_id) 1232 { 1233 struct wlan_objmgr_peer *peer; 1234 qdf_list_node_t *psoc_node = NULL; 1235 qdf_list_node_t *prev_psoc_node = NULL; 1236 qdf_list_t *obj_list; 1237 1238 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1239 obj_list = &peer_list->peer_hash[hash_index]; 1240 1241 if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) { 1242 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1243 return NULL; 1244 } 1245 1246 do { 1247 peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 1248 psoc_peer); 1249 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 1250 QDF_STATUS_SUCCESS) { 1251 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1252 return peer; 1253 } 1254 1255 prev_psoc_node = psoc_node; 1256 } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 1257 QDF_STATUS_SUCCESS); 1258 1259 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1260 return NULL; 1261 } 1262 #endif 1263 1264 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1265 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref_debug( 1266 struct wlan_peer_list *peer_list, 1267 uint8_t hash_index, 1268 wlan_objmgr_ref_dbgid dbg_id, 1269 const char *func, int line) 1270 { 1271 struct wlan_objmgr_peer *peer; 1272 qdf_list_t *obj_list; 1273 1274 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1275 obj_list = &peer_list->peer_hash[hash_index]; 1276 1277 peer = wlan_psoc_peer_list_peek_head(obj_list); 1278 1279 /* This API is invoked by caller, only when caller need to access the 1280 * peer object, though object is not in active state, this API should be 1281 * used carefully, where multiple object frees are not triggered 1282 */ 1283 if (peer) 1284 wlan_objmgr_peer_get_ref_debug(peer, dbg_id, func, line); 1285 1286 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1287 1288 return peer; 1289 } 1290 #else 1291 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( 1292 struct wlan_peer_list *peer_list, 1293 uint8_t hash_index, 1294 wlan_objmgr_ref_dbgid dbg_id) 1295 { 1296 struct wlan_objmgr_peer *peer; 1297 qdf_list_t *obj_list; 1298 1299 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1300 obj_list = &peer_list->peer_hash[hash_index]; 1301 1302 peer = wlan_psoc_peer_list_peek_head(obj_list); 1303 1304 /* This API is invoked by caller, only when caller need to access the 1305 * peer object, though object is not in active state, this API should be 1306 * used carefully, where multiple object frees are not triggered 1307 */ 1308 if (peer) 1309 wlan_objmgr_peer_get_ref(peer, dbg_id); 1310 1311 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1312 1313 return peer; 1314 } 1315 #endif 1316 1317 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1318 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref_debug( 1319 struct wlan_peer_list *peer_list, uint8_t hash_index, 1320 struct wlan_objmgr_peer *peer, 1321 wlan_objmgr_ref_dbgid dbg_id, 1322 const char *func, int line) 1323 { 1324 qdf_list_t *obj_list; 1325 struct wlan_objmgr_peer *peer_next; 1326 1327 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1328 obj_list = &peer_list->peer_hash[hash_index]; 1329 1330 peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer); 1331 /* This API is invoked by caller, only when caller need to access the 1332 * peer object, though object is not in active state, this API should be 1333 * used carefully, where multiple free on object are not triggered 1334 */ 1335 if (peer_next) 1336 wlan_objmgr_peer_get_ref_debug(peer_next, dbg_id, func, line); 1337 1338 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1339 1340 return peer_next; 1341 } 1342 #else 1343 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( 1344 struct wlan_peer_list *peer_list, uint8_t hash_index, 1345 struct wlan_objmgr_peer *peer, 1346 wlan_objmgr_ref_dbgid dbg_id) 1347 { 1348 qdf_list_t *obj_list; 1349 struct wlan_objmgr_peer *peer_next; 1350 1351 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1352 obj_list = &peer_list->peer_hash[hash_index]; 1353 1354 peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer); 1355 /* This API is invoked by caller, only when caller need to access the 1356 * peer object, though object is not in active state, this API should be 1357 * used carefully, where multiple free on object are not triggered 1358 */ 1359 if (peer_next) 1360 wlan_objmgr_peer_get_ref(peer_next, dbg_id); 1361 1362 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1363 1364 return peer_next; 1365 } 1366 #endif 1367 1368 #ifdef WLAN_OBJMGR_REF_ID_TRACE 1369 void wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer *peer, 1370 wlan_objmgr_ref_dbgid id, 1371 const char *func, int line) 1372 { 1373 QDF_STATUS status; 1374 1375 if (!peer) { 1376 obj_mgr_err("peer obj is NULL for %d", id); 1377 QDF_ASSERT(0); 1378 return; 1379 } 1380 1381 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 1382 uint8_t *macaddr; 1383 1384 macaddr = wlan_peer_get_macaddr(peer); 1385 obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0", 1386 QDF_MAC_ADDR_REF(macaddr)); 1387 WLAN_OBJMGR_BUG(0); 1388 return; 1389 } 1390 1391 status = wlan_objmgr_peer_release_debug_id_ref(peer, id); 1392 if (QDF_IS_STATUS_ERROR(status)) 1393 return; 1394 1395 wlan_objmgr_peer_deref_trace(peer, id, func, line); 1396 /* Provide synchronization from the access to add peer 1397 * to logically deleted peer list. 1398 */ 1399 wlan_peer_obj_lock(peer); 1400 /* Decrement ref count, free peer object, if ref count == 0 */ 1401 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { 1402 wlan_peer_obj_unlock(peer); 1403 wlan_objmgr_peer_obj_destroy(peer); 1404 } else { 1405 wlan_peer_obj_unlock(peer); 1406 } 1407 1408 return; 1409 } 1410 1411 qdf_export_symbol(wlan_objmgr_peer_release_ref_debug); 1412 #else 1413 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, 1414 wlan_objmgr_ref_dbgid id) 1415 { 1416 QDF_STATUS status; 1417 1418 if (!peer) { 1419 obj_mgr_err("peer obj is NULL for %d", id); 1420 QDF_ASSERT(0); 1421 return; 1422 } 1423 1424 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 1425 uint8_t *macaddr; 1426 1427 macaddr = wlan_peer_get_macaddr(peer); 1428 obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0", 1429 QDF_MAC_ADDR_REF(macaddr)); 1430 WLAN_OBJMGR_BUG(0); 1431 return; 1432 } 1433 1434 status = wlan_objmgr_peer_release_debug_id_ref(peer, id); 1435 if (QDF_IS_STATUS_ERROR(status)) 1436 return; 1437 1438 /* Provide synchronization from the access to add peer 1439 * to logically deleted peer list. 1440 */ 1441 wlan_peer_obj_lock(peer); 1442 /* Decrement ref count, free peer object, if ref count == 0 */ 1443 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { 1444 wlan_peer_obj_unlock(peer); 1445 wlan_objmgr_peer_obj_destroy(peer); 1446 } else { 1447 wlan_peer_obj_unlock(peer); 1448 } 1449 } 1450 1451 qdf_export_symbol(wlan_objmgr_peer_release_ref); 1452 #endif 1453 1454 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 1455 void 1456 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer, 1457 QDF_TRACE_LEVEL log_level) 1458 { 1459 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level); 1460 } 1461 1462 uint32_t 1463 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, 1464 enum wlan_umac_comp_id id) 1465 { 1466 return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]); 1467 } 1468 #else 1469 void 1470 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer, 1471 QDF_TRACE_LEVEL log_level) 1472 { 1473 uint32_t pending_ref; 1474 1475 pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt); 1476 obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref); 1477 } 1478 1479 uint32_t 1480 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, 1481 enum wlan_umac_comp_id id) 1482 { 1483 return 0; 1484 } 1485 #endif 1486 1487 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE 1488 QDF_STATUS wlan_peer_update_macaddr(struct wlan_objmgr_peer *peer, 1489 uint8_t *new_macaddr) 1490 { 1491 struct wlan_objmgr_psoc *psoc; 1492 struct wlan_objmgr_vdev *vdev; 1493 uint8_t *macaddr; 1494 QDF_STATUS status; 1495 1496 if (!peer) { 1497 obj_mgr_err("PEER is NULL"); 1498 return QDF_STATUS_E_FAILURE; 1499 } 1500 1501 macaddr = wlan_peer_get_macaddr(peer); 1502 1503 vdev = wlan_peer_get_vdev(peer); 1504 if (!vdev) { 1505 obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")", 1506 QDF_MAC_ADDR_REF(macaddr)); 1507 return QDF_STATUS_E_FAILURE; 1508 } 1509 1510 /* get PSOC from VDEV, if it is NULL, return */ 1511 psoc = wlan_vdev_get_psoc(vdev); 1512 if (!psoc) { 1513 obj_mgr_err("PSOC is NULL for peer(" QDF_MAC_ADDR_FMT ")", 1514 QDF_MAC_ADDR_REF(macaddr)); 1515 return QDF_STATUS_E_FAILURE; 1516 } 1517 1518 status = wlan_objmgr_psoc_peer_detach(psoc, peer); 1519 if (QDF_IS_STATUS_ERROR(status)) { 1520 obj_mgr_err("Failed to detach peer(" QDF_MAC_ADDR_FMT ")", 1521 QDF_MAC_ADDR_REF(macaddr)); 1522 return status; 1523 } 1524 1525 wlan_peer_set_macaddr(peer, new_macaddr); 1526 1527 status = wlan_objmgr_psoc_peer_attach(psoc, peer); 1528 if (QDF_IS_STATUS_ERROR(status)) { 1529 obj_mgr_err("Failed to attach peer(" QDF_MAC_ADDR_FMT ")", 1530 QDF_MAC_ADDR_REF(new_macaddr)); 1531 return status; 1532 } 1533 return QDF_STATUS_SUCCESS; 1534 } 1535 #endif 1536