1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 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 */ wlan_objmgr_peer_object_status(struct wlan_objmgr_peer * peer)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 wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer * peer)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 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer * peer)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 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer * peer)163 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) {} 164 #endif 165 wlan_objmgr_peer_obj_create(struct wlan_objmgr_vdev * vdev,enum wlan_peer_type type,uint8_t * macaddr)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 __wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)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 */ wlan_objmgr_peer_obj_free_work(void * data)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 wlan_peer_obj_free_enqueue(struct wlan_objmgr_peer * peer)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 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)450 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) 451 { 452 QDF_STATUS status; 453 454 if (qdf_in_atomic()) { 455 status = wlan_peer_obj_free_enqueue(peer); 456 if (status == QDF_STATUS_SUCCESS) 457 return status; 458 459 obj_mgr_err("enqueue failure, call free obj directly"); 460 } 461 462 status = __wlan_objmgr_peer_obj_destroy(peer); 463 464 return status; 465 } 466 467 /** 468 * wlan_delayed_peer_obj_free_init() - Init for delayed peer obj freed queue 469 * @data: PDEV object 470 * 471 * Initialize main data structures to process peer obj destroy in a delayed 472 * workqueue. 473 * 474 * Return: QDF_STATUS_SUCCESS on success else a QDF error. 475 */ wlan_delayed_peer_obj_free_init(void * data)476 QDF_STATUS wlan_delayed_peer_obj_free_init(void *data) 477 { 478 struct wlan_objmgr_pdev *pdev = data; 479 480 if (!pdev) { 481 obj_mgr_err("pdev is NULL"); 482 return QDF_STATUS_E_FAILURE; 483 } 484 485 qdf_spinlock_create(&pdev->peer_free_lock); 486 qdf_create_work(0, &pdev->peer_obj_free_work, 487 wlan_objmgr_peer_obj_free_work, 488 (void *)pdev); 489 pdev->active_work_cnt = 0; 490 491 /* Initialize PDEV's peer free list, assign default values */ 492 qdf_list_create(&pdev->peer_free_list, MAX_DELAYED_FREE_PEERS); 493 494 obj_mgr_debug("Delayed peer obj free init successfully"); 495 496 return QDF_STATUS_SUCCESS; 497 } 498 499 /** 500 * wlan_delayed_peer_obj_free_deinit() - De-Init delayed peer freed processing 501 * @data: PDEV object 502 * 503 * De-initialize main data structures to process peer obj freed in a delayed 504 * workqueue. 505 * 506 * Return: QDF_STATUS_SUCCESS on success else a QDF error. 507 */ wlan_delayed_peer_obj_free_deinit(void * data)508 QDF_STATUS wlan_delayed_peer_obj_free_deinit(void *data) 509 { 510 struct wlan_objmgr_pdev *pdev = data; 511 512 if (!pdev) { 513 obj_mgr_err("pdev is NULL"); 514 return QDF_STATUS_E_FAILURE; 515 } 516 517 qdf_destroy_work(0, &pdev->peer_obj_free_work); 518 qdf_spinlock_destroy(&pdev->peer_free_lock); 519 520 obj_mgr_debug("Deinit successfully, active_work_cnt=%u", 521 pdev->active_work_cnt); 522 523 return QDF_STATUS_SUCCESS; 524 } 525 #else 526 static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)527 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) 528 { 529 return __wlan_objmgr_peer_obj_destroy(peer); 530 } 531 #endif 532 wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer * peer)533 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) 534 { 535 uint8_t print_idx; 536 uint8_t *macaddr; 537 538 if (!peer) { 539 obj_mgr_err("PEER is NULL"); 540 return QDF_STATUS_E_FAILURE; 541 } 542 543 wlan_peer_obj_lock(peer); 544 macaddr = wlan_peer_get_macaddr(peer); 545 wlan_peer_obj_unlock(peer); 546 547 obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_FMT, 548 QDF_MAC_ADDR_REF(macaddr)); 549 550 print_idx = qdf_get_pidx(); 551 wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG); 552 /* 553 * Update VDEV object state to LOGICALLY DELETED 554 * It prevents further access of this object 555 */ 556 wlan_peer_obj_lock(peer); 557 peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 558 wlan_peer_obj_unlock(peer); 559 wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP); 560 wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID); 561 562 return QDF_STATUS_SUCCESS; 563 } 564 qdf_export_symbol(wlan_objmgr_peer_obj_delete); 565 /* 566 * APIs to attach/detach component objects 567 */ wlan_objmgr_peer_component_obj_attach(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id,void * comp_priv_obj,QDF_STATUS status)568 QDF_STATUS wlan_objmgr_peer_component_obj_attach( 569 struct wlan_objmgr_peer *peer, 570 enum wlan_umac_comp_id id, 571 void *comp_priv_obj, 572 QDF_STATUS status) 573 { 574 wlan_objmgr_peer_status_handler s_hler; 575 void *arg; 576 uint8_t i; 577 QDF_STATUS obj_status; 578 579 /* component id is invalid */ 580 if (id >= WLAN_UMAC_MAX_COMPONENTS) 581 return QDF_STATUS_MAXCOMP_FAIL; 582 583 wlan_peer_obj_lock(peer); 584 /* If there is a valid entry, return failure, 585 valid object needs to be freed first */ 586 if (peer->peer_comp_priv_obj[id]) { 587 wlan_peer_obj_unlock(peer); 588 return QDF_STATUS_E_FAILURE; 589 } 590 /* Assign component object private pointer(can be NULL also), status */ 591 peer->peer_comp_priv_obj[id] = comp_priv_obj; 592 peer->obj_status[id] = status; 593 wlan_peer_obj_unlock(peer); 594 595 if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 596 return QDF_STATUS_SUCCESS; 597 598 /* If PEER object status is partially created means, this API is 599 invoked with different context. this block should be executed for async 600 components only */ 601 /* Derive status */ 602 obj_status = wlan_objmgr_peer_object_status(peer); 603 /* STATUS_SUCCESS means, object is CREATED */ 604 if (obj_status == QDF_STATUS_SUCCESS) 605 peer->obj_state = WLAN_OBJ_STATE_CREATED; 606 /* update state as CREATION failed, caller has to delete the 607 PEER object */ 608 else if (obj_status == QDF_STATUS_E_FAILURE) 609 peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 610 /* Notify components about the CREATION success/failure */ 611 if ((obj_status == QDF_STATUS_SUCCESS) || 612 (obj_status == QDF_STATUS_E_FAILURE)) { 613 /* notify object status */ 614 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 615 s_hler = g_umac_glb_obj->peer_status_handler[i]; 616 arg = g_umac_glb_obj->peer_status_handler_arg[i]; 617 if (s_hler) 618 s_hler(peer, arg, obj_status); 619 } 620 } 621 return QDF_STATUS_SUCCESS; 622 } 623 624 qdf_export_symbol(wlan_objmgr_peer_component_obj_attach); 625 wlan_objmgr_peer_component_obj_detach(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id,void * comp_priv_obj)626 QDF_STATUS wlan_objmgr_peer_component_obj_detach( 627 struct wlan_objmgr_peer *peer, 628 enum wlan_umac_comp_id id, 629 void *comp_priv_obj) 630 { 631 QDF_STATUS obj_status; 632 633 /* component id is invalid */ 634 if (id >= WLAN_UMAC_MAX_COMPONENTS) 635 return QDF_STATUS_MAXCOMP_FAIL; 636 637 wlan_peer_obj_lock(peer); 638 /* If there is a invalid entry, return failure */ 639 if (peer->peer_comp_priv_obj[id] != comp_priv_obj) { 640 peer->obj_status[id] = QDF_STATUS_E_FAILURE; 641 wlan_peer_obj_unlock(peer); 642 return QDF_STATUS_E_FAILURE; 643 } 644 /* Reset the pointer to NULL */ 645 peer->peer_comp_priv_obj[id] = NULL; 646 peer->obj_status[id] = QDF_STATUS_SUCCESS; 647 wlan_peer_obj_unlock(peer); 648 649 /* If PEER object status is partially destroyed means, this API is 650 invoked with different context, this block should be executed for async 651 components only */ 652 if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 653 (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 654 /* Derive object status */ 655 obj_status = wlan_objmgr_peer_object_status(peer); 656 if (obj_status == QDF_STATUS_SUCCESS) { 657 /*Update the status as Deleted, if full object 658 deletion is in progress */ 659 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 660 peer->obj_state = WLAN_OBJ_STATE_DELETED; 661 /* Move to creation state, since this component 662 deletion alone requested */ 663 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 664 peer->obj_state = WLAN_OBJ_STATE_CREATED; 665 /* Object status is failure */ 666 } else if (obj_status == QDF_STATUS_E_FAILURE) { 667 /*Update the status as Deletion failed, if full object 668 deletion is in progress */ 669 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 670 peer->obj_state = 671 WLAN_OBJ_STATE_DELETION_FAILED; 672 /* Move to creation state, since this component 673 deletion alone requested (do not block other 674 components) */ 675 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 676 peer->obj_state = WLAN_OBJ_STATE_CREATED; 677 } 678 679 /* Delete peer object */ 680 if ((obj_status == QDF_STATUS_SUCCESS) && 681 (peer->obj_state == WLAN_OBJ_STATE_DELETED)) { 682 /* Free the peer object */ 683 return wlan_objmgr_peer_obj_free(peer); 684 } 685 } 686 687 return QDF_STATUS_SUCCESS; 688 } 689 690 qdf_export_symbol(wlan_objmgr_peer_component_obj_detach); 691 wlan_objmgr_trigger_peer_comp_priv_object_creation(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)692 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation( 693 struct wlan_objmgr_peer *peer, 694 enum wlan_umac_comp_id id) 695 { 696 wlan_objmgr_peer_create_handler handler; 697 void *arg; 698 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 699 700 /* Component id is invalid */ 701 if (id >= WLAN_UMAC_MAX_COMPONENTS) 702 return QDF_STATUS_MAXCOMP_FAIL; 703 704 wlan_peer_obj_lock(peer); 705 /* If component object is already created, delete old 706 component object, then invoke creation */ 707 if (peer->peer_comp_priv_obj[id]) { 708 wlan_peer_obj_unlock(peer); 709 return QDF_STATUS_E_FAILURE; 710 } 711 wlan_peer_obj_unlock(peer); 712 713 /* Invoke registered create handlers */ 714 handler = g_umac_glb_obj->peer_create_handler[id]; 715 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 716 if (handler) 717 peer->obj_status[id] = handler(peer, arg); 718 else 719 return QDF_STATUS_E_FAILURE; 720 721 /* If object status is created, then only handle this object status */ 722 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 723 /* Derive object status */ 724 obj_status = wlan_objmgr_peer_object_status(peer); 725 /* Move PDEV object state to Partially created state */ 726 if (obj_status == QDF_STATUS_COMP_ASYNC) { 727 /*TODO atomic */ 728 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 729 } 730 } 731 732 return obj_status; 733 } 734 735 wlan_objmgr_trigger_peer_comp_priv_object_deletion(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)736 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion( 737 struct wlan_objmgr_peer *peer, 738 enum wlan_umac_comp_id id) 739 { 740 wlan_objmgr_peer_destroy_handler handler; 741 void *arg; 742 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 743 744 /* component id is invalid */ 745 if (id >= WLAN_UMAC_MAX_COMPONENTS) 746 return QDF_STATUS_MAXCOMP_FAIL; 747 748 wlan_peer_obj_lock(peer); 749 /* Component object was never created, invalid operation */ 750 if (!peer->peer_comp_priv_obj[id]) { 751 wlan_peer_obj_unlock(peer); 752 return QDF_STATUS_E_FAILURE; 753 } 754 755 wlan_peer_obj_unlock(peer); 756 757 /* Invoke registered destroy handlers */ 758 handler = g_umac_glb_obj->peer_destroy_handler[id]; 759 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 760 if (handler) 761 peer->obj_status[id] = handler(peer, arg); 762 else 763 return QDF_STATUS_E_FAILURE; 764 765 /* If object status is created, then only handle this object status */ 766 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 767 obj_status = wlan_objmgr_peer_object_status(peer); 768 /* move object state to DEL progress */ 769 if (obj_status == QDF_STATUS_COMP_ASYNC) 770 peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 771 } 772 return obj_status; 773 } 774 wlan_objmgr_peer_get_comp_private_obj(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)775 void *wlan_objmgr_peer_get_comp_private_obj( 776 struct wlan_objmgr_peer *peer, 777 enum wlan_umac_comp_id id) 778 { 779 void *comp_priv_obj; 780 781 /* component id is invalid */ 782 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 783 QDF_BUG(0); 784 return NULL; 785 } 786 787 if (!peer) { 788 QDF_BUG(0); 789 return NULL; 790 } 791 792 comp_priv_obj = peer->peer_comp_priv_obj[id]; 793 return comp_priv_obj; 794 } 795 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj); 796 797 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 798 static inline void wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)799 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, 800 wlan_objmgr_ref_dbgid id) 801 { 802 qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]); 803 } 804 #else 805 static inline void wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)806 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, 807 wlan_objmgr_ref_dbgid id) {} 808 #endif 809 810 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 811 static QDF_STATUS wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)812 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, 813 wlan_objmgr_ref_dbgid id) 814 { 815 if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) { 816 uint8_t *macaddr; 817 818 macaddr = wlan_peer_get_macaddr(peer); 819 obj_mgr_err( 820 "peer("QDF_MAC_ADDR_FMT") ref was not taken by %d", 821 QDF_MAC_ADDR_REF(macaddr), id); 822 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, 823 QDF_TRACE_LEVEL_FATAL); 824 WLAN_OBJMGR_BUG(0); 825 return QDF_STATUS_E_FAILURE; 826 } 827 828 qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]); 829 return QDF_STATUS_SUCCESS; 830 } 831 #else 832 static QDF_STATUS wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)833 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, 834 wlan_objmgr_ref_dbgid id) 835 { 836 return QDF_STATUS_SUCCESS; 837 } 838 #endif 839 840 #ifdef WLAN_OBJMGR_REF_ID_TRACE 841 static inline void wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)842 wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer *peer, 843 wlan_objmgr_ref_dbgid id, 844 const char *func, int line) 845 { 846 struct wlan_objmgr_trace *trace; 847 848 trace = &peer->peer_objmgr.trace; 849 850 if (func) 851 wlan_objmgr_trace_ref(&trace->references[id].head, 852 trace, func, line); 853 } 854 855 static inline void wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)856 wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer *peer, 857 wlan_objmgr_ref_dbgid id, 858 const char *func, int line) 859 { 860 struct wlan_objmgr_trace *trace; 861 862 trace = &peer->peer_objmgr.trace; 863 if (func) 864 wlan_objmgr_trace_ref(&trace->dereferences[id].head, 865 trace, func, line); 866 } 867 #endif 868 869 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)870 void wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer *peer, 871 wlan_objmgr_ref_dbgid id, 872 const char *func, int line) 873 { 874 if (!peer) { 875 obj_mgr_err("peer obj is NULL for %d", id); 876 QDF_ASSERT(0); 877 return; 878 } 879 /* Increment ref count */ 880 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); 881 wlan_objmgr_peer_get_debug_id_ref(peer, id); 882 883 wlan_objmgr_peer_ref_trace(peer, id, func, line); 884 return; 885 } 886 887 qdf_export_symbol(wlan_objmgr_peer_get_ref_debug); 888 #else wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)889 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, 890 wlan_objmgr_ref_dbgid id) 891 { 892 if (!peer) { 893 obj_mgr_err("peer obj is NULL for %d", id); 894 QDF_ASSERT(0); 895 return; 896 } 897 /* Increment ref count */ 898 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); 899 wlan_objmgr_peer_get_debug_id_ref(peer, id); 900 } 901 902 qdf_export_symbol(wlan_objmgr_peer_get_ref); 903 #endif 904 905 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)906 QDF_STATUS wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer *peer, 907 wlan_objmgr_ref_dbgid id, 908 const char *func, int line) 909 { 910 if (!peer) { 911 obj_mgr_err("peer obj is NULL for %d", id); 912 QDF_ASSERT(0); 913 return QDF_STATUS_E_FAILURE; 914 } 915 916 wlan_peer_obj_lock(peer); 917 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) { 918 wlan_peer_obj_unlock(peer); 919 if (peer->peer_objmgr.print_cnt++ <= 920 WLAN_OBJMGR_RATELIMIT_THRESH) { 921 uint8_t *macaddr; 922 923 macaddr = wlan_peer_get_macaddr(peer); 924 obj_mgr_debug( 925 "peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)", 926 QDF_MAC_ADDR_REF(macaddr), 927 peer->obj_state); 928 } 929 return QDF_STATUS_E_RESOURCES; 930 } 931 932 wlan_objmgr_peer_get_ref_debug(peer, id, func, line); 933 wlan_peer_obj_unlock(peer); 934 935 return QDF_STATUS_SUCCESS; 936 } 937 938 qdf_export_symbol(wlan_objmgr_peer_try_get_ref_debug); 939 #else wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)940 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, 941 wlan_objmgr_ref_dbgid id) 942 { 943 if (!peer) { 944 obj_mgr_err("peer obj is NULL for %d", id); 945 QDF_ASSERT(0); 946 return QDF_STATUS_E_FAILURE; 947 } 948 949 wlan_peer_obj_lock(peer); 950 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) { 951 wlan_peer_obj_unlock(peer); 952 if (peer->peer_objmgr.print_cnt++ <= 953 WLAN_OBJMGR_RATELIMIT_THRESH) { 954 uint8_t *macaddr; 955 956 macaddr = wlan_peer_get_macaddr(peer); 957 obj_mgr_debug( 958 "peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)", 959 QDF_MAC_ADDR_REF(macaddr), 960 peer->obj_state); 961 } 962 return QDF_STATUS_E_RESOURCES; 963 } 964 965 wlan_objmgr_peer_get_ref(peer, id); 966 wlan_peer_obj_unlock(peer); 967 968 return QDF_STATUS_SUCCESS; 969 } 970 971 qdf_export_symbol(wlan_objmgr_peer_try_get_ref); 972 #endif 973 974 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_peer_get_next_active_peer_of_psoc_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)975 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc_debug( 976 struct wlan_peer_list *peer_list, 977 uint8_t hash_index, 978 struct wlan_objmgr_peer *peer, 979 wlan_objmgr_ref_dbgid dbg_id, 980 const char *func, int line) 981 { 982 struct wlan_objmgr_peer *peer_next = NULL; 983 qdf_list_node_t *psoc_node = NULL; 984 qdf_list_node_t *prev_psoc_node = NULL; 985 qdf_list_t *obj_list; 986 987 qdf_spin_lock_bh(&peer_list->peer_list_lock); 988 obj_list = &peer_list->peer_hash[hash_index]; 989 990 prev_psoc_node = &peer->psoc_peer; 991 while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 992 QDF_STATUS_SUCCESS) { 993 peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 994 psoc_peer); 995 996 if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id, 997 func, line) == 998 QDF_STATUS_SUCCESS) { 999 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1000 return peer_next; 1001 } 1002 1003 prev_psoc_node = psoc_node; 1004 } 1005 1006 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1007 1008 return NULL; 1009 } 1010 #else wlan_peer_get_next_active_peer_of_psoc(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1011 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( 1012 struct wlan_peer_list *peer_list, 1013 uint8_t hash_index, 1014 struct wlan_objmgr_peer *peer, 1015 wlan_objmgr_ref_dbgid dbg_id) 1016 { 1017 struct wlan_objmgr_peer *peer_next = NULL; 1018 qdf_list_node_t *psoc_node = NULL; 1019 qdf_list_node_t *prev_psoc_node = NULL; 1020 qdf_list_t *obj_list; 1021 1022 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1023 obj_list = &peer_list->peer_hash[hash_index]; 1024 1025 prev_psoc_node = &peer->psoc_peer; 1026 while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 1027 QDF_STATUS_SUCCESS) { 1028 peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 1029 psoc_peer); 1030 1031 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == 1032 QDF_STATUS_SUCCESS) { 1033 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1034 return peer_next; 1035 } 1036 1037 prev_psoc_node = psoc_node; 1038 } 1039 1040 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1041 1042 return NULL; 1043 } 1044 #endif 1045 1046 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_vdev_peer_list_peek_active_head_debug(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1047 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head_debug( 1048 struct wlan_objmgr_vdev *vdev, 1049 qdf_list_t *peer_list, 1050 wlan_objmgr_ref_dbgid dbg_id, 1051 const char *func, int line) 1052 { 1053 struct wlan_objmgr_peer *peer; 1054 qdf_list_node_t *vdev_node = NULL; 1055 qdf_list_node_t *prev_vdev_node = NULL; 1056 1057 wlan_vdev_obj_lock(vdev); 1058 1059 if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) { 1060 wlan_vdev_obj_unlock(vdev); 1061 return NULL; 1062 } 1063 1064 do { 1065 peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 1066 vdev_peer); 1067 1068 if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id, 1069 func, line) == 1070 QDF_STATUS_SUCCESS) { 1071 wlan_vdev_obj_unlock(vdev); 1072 return peer; 1073 } 1074 1075 prev_vdev_node = vdev_node; 1076 } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 1077 QDF_STATUS_SUCCESS); 1078 1079 wlan_vdev_obj_unlock(vdev); 1080 1081 return NULL; 1082 } 1083 #else wlan_vdev_peer_list_peek_active_head(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,wlan_objmgr_ref_dbgid dbg_id)1084 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head( 1085 struct wlan_objmgr_vdev *vdev, 1086 qdf_list_t *peer_list, 1087 wlan_objmgr_ref_dbgid dbg_id) 1088 { 1089 struct wlan_objmgr_peer *peer; 1090 qdf_list_node_t *vdev_node = NULL; 1091 qdf_list_node_t *prev_vdev_node = NULL; 1092 1093 wlan_vdev_obj_lock(vdev); 1094 1095 if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) { 1096 wlan_vdev_obj_unlock(vdev); 1097 return NULL; 1098 } 1099 1100 do { 1101 peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 1102 vdev_peer); 1103 1104 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 1105 QDF_STATUS_SUCCESS) { 1106 wlan_vdev_obj_unlock(vdev); 1107 return peer; 1108 } 1109 1110 prev_vdev_node = vdev_node; 1111 } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 1112 QDF_STATUS_SUCCESS); 1113 1114 wlan_vdev_obj_unlock(vdev); 1115 1116 return NULL; 1117 } 1118 #endif 1119 1120 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_peer_get_next_active_peer_of_vdev_debug(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1121 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev_debug( 1122 struct wlan_objmgr_vdev *vdev, 1123 qdf_list_t *peer_list, 1124 struct wlan_objmgr_peer *peer, 1125 wlan_objmgr_ref_dbgid dbg_id, 1126 const char *func, int line) 1127 { 1128 struct wlan_objmgr_peer *peer_next; 1129 qdf_list_node_t *vdev_node = NULL; 1130 qdf_list_node_t *prev_vdev_node = NULL; 1131 1132 if (!peer) 1133 return NULL; 1134 1135 wlan_vdev_obj_lock(vdev); 1136 1137 prev_vdev_node = &peer->vdev_peer; 1138 while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 1139 QDF_STATUS_SUCCESS) { 1140 peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 1141 vdev_peer); 1142 1143 if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id, 1144 func, line) == 1145 QDF_STATUS_SUCCESS) { 1146 wlan_vdev_obj_unlock(vdev); 1147 return peer_next; 1148 } 1149 1150 prev_vdev_node = vdev_node; 1151 } 1152 1153 wlan_vdev_obj_unlock(vdev); 1154 1155 return NULL; 1156 } 1157 #else wlan_peer_get_next_active_peer_of_vdev(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1158 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev( 1159 struct wlan_objmgr_vdev *vdev, 1160 qdf_list_t *peer_list, 1161 struct wlan_objmgr_peer *peer, 1162 wlan_objmgr_ref_dbgid dbg_id) 1163 { 1164 struct wlan_objmgr_peer *peer_next; 1165 qdf_list_node_t *vdev_node = NULL; 1166 qdf_list_node_t *prev_vdev_node = NULL; 1167 1168 if (!peer) 1169 return NULL; 1170 1171 wlan_vdev_obj_lock(vdev); 1172 1173 prev_vdev_node = &peer->vdev_peer; 1174 while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 1175 QDF_STATUS_SUCCESS) { 1176 peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 1177 vdev_peer); 1178 1179 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == 1180 QDF_STATUS_SUCCESS) { 1181 wlan_vdev_obj_unlock(vdev); 1182 return peer_next; 1183 } 1184 1185 prev_vdev_node = vdev_node; 1186 } 1187 1188 wlan_vdev_obj_unlock(vdev); 1189 1190 return NULL; 1191 } 1192 #endif 1193 1194 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_psoc_peer_list_peek_active_head_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1195 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head_debug( 1196 struct wlan_peer_list *peer_list, 1197 uint8_t hash_index, 1198 wlan_objmgr_ref_dbgid dbg_id, 1199 const char *func, int line) 1200 { 1201 struct wlan_objmgr_peer *peer; 1202 qdf_list_node_t *psoc_node = NULL; 1203 qdf_list_node_t *prev_psoc_node = NULL; 1204 qdf_list_t *obj_list; 1205 1206 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1207 obj_list = &peer_list->peer_hash[hash_index]; 1208 1209 if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) { 1210 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1211 return NULL; 1212 } 1213 1214 do { 1215 peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 1216 psoc_peer); 1217 if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id, 1218 func, line) == 1219 QDF_STATUS_SUCCESS) { 1220 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1221 return peer; 1222 } 1223 1224 prev_psoc_node = psoc_node; 1225 } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 1226 QDF_STATUS_SUCCESS); 1227 1228 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1229 return NULL; 1230 } 1231 #else wlan_psoc_peer_list_peek_active_head(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id)1232 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( 1233 struct wlan_peer_list *peer_list, 1234 uint8_t hash_index, 1235 wlan_objmgr_ref_dbgid dbg_id) 1236 { 1237 struct wlan_objmgr_peer *peer; 1238 qdf_list_node_t *psoc_node = NULL; 1239 qdf_list_node_t *prev_psoc_node = NULL; 1240 qdf_list_t *obj_list; 1241 1242 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1243 obj_list = &peer_list->peer_hash[hash_index]; 1244 1245 if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) { 1246 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1247 return NULL; 1248 } 1249 1250 do { 1251 peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 1252 psoc_peer); 1253 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 1254 QDF_STATUS_SUCCESS) { 1255 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1256 return peer; 1257 } 1258 1259 prev_psoc_node = psoc_node; 1260 } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 1261 QDF_STATUS_SUCCESS); 1262 1263 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1264 return NULL; 1265 } 1266 #endif 1267 1268 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_psoc_peer_list_peek_head_ref_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1269 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref_debug( 1270 struct wlan_peer_list *peer_list, 1271 uint8_t hash_index, 1272 wlan_objmgr_ref_dbgid dbg_id, 1273 const char *func, int line) 1274 { 1275 struct wlan_objmgr_peer *peer; 1276 qdf_list_t *obj_list; 1277 1278 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1279 obj_list = &peer_list->peer_hash[hash_index]; 1280 1281 peer = wlan_psoc_peer_list_peek_head(obj_list); 1282 1283 /* This API is invoked by caller, only when caller need to access the 1284 * peer object, though object is not in active state, this API should be 1285 * used carefully, where multiple object frees are not triggered 1286 */ 1287 if (peer) 1288 wlan_objmgr_peer_get_ref_debug(peer, dbg_id, func, line); 1289 1290 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1291 1292 return peer; 1293 } 1294 #else wlan_psoc_peer_list_peek_head_ref(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id)1295 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( 1296 struct wlan_peer_list *peer_list, 1297 uint8_t hash_index, 1298 wlan_objmgr_ref_dbgid dbg_id) 1299 { 1300 struct wlan_objmgr_peer *peer; 1301 qdf_list_t *obj_list; 1302 1303 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1304 obj_list = &peer_list->peer_hash[hash_index]; 1305 1306 peer = wlan_psoc_peer_list_peek_head(obj_list); 1307 1308 /* This API is invoked by caller, only when caller need to access the 1309 * peer object, though object is not in active state, this API should be 1310 * used carefully, where multiple object frees are not triggered 1311 */ 1312 if (peer) 1313 wlan_objmgr_peer_get_ref(peer, dbg_id); 1314 1315 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1316 1317 return peer; 1318 } 1319 #endif 1320 1321 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_peer_get_next_peer_of_psoc_ref_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1322 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref_debug( 1323 struct wlan_peer_list *peer_list, uint8_t hash_index, 1324 struct wlan_objmgr_peer *peer, 1325 wlan_objmgr_ref_dbgid dbg_id, 1326 const char *func, int line) 1327 { 1328 qdf_list_t *obj_list; 1329 struct wlan_objmgr_peer *peer_next; 1330 1331 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1332 obj_list = &peer_list->peer_hash[hash_index]; 1333 1334 peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer); 1335 /* This API is invoked by caller, only when caller need to access the 1336 * peer object, though object is not in active state, this API should be 1337 * used carefully, where multiple free on object are not triggered 1338 */ 1339 if (peer_next) 1340 wlan_objmgr_peer_get_ref_debug(peer_next, dbg_id, func, line); 1341 1342 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1343 1344 return peer_next; 1345 } 1346 #else wlan_peer_get_next_peer_of_psoc_ref(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1347 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( 1348 struct wlan_peer_list *peer_list, uint8_t hash_index, 1349 struct wlan_objmgr_peer *peer, 1350 wlan_objmgr_ref_dbgid dbg_id) 1351 { 1352 qdf_list_t *obj_list; 1353 struct wlan_objmgr_peer *peer_next; 1354 1355 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1356 obj_list = &peer_list->peer_hash[hash_index]; 1357 1358 peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer); 1359 /* This API is invoked by caller, only when caller need to access the 1360 * peer object, though object is not in active state, this API should be 1361 * used carefully, where multiple free on object are not triggered 1362 */ 1363 if (peer_next) 1364 wlan_objmgr_peer_get_ref(peer_next, dbg_id); 1365 1366 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1367 1368 return peer_next; 1369 } 1370 #endif 1371 1372 #ifdef WLAN_OBJMGR_REF_ID_TRACE wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)1373 void wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer *peer, 1374 wlan_objmgr_ref_dbgid id, 1375 const char *func, int line) 1376 { 1377 QDF_STATUS status; 1378 1379 if (!peer) { 1380 obj_mgr_err("peer obj is NULL for %d", id); 1381 QDF_ASSERT(0); 1382 return; 1383 } 1384 1385 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 1386 uint8_t *macaddr; 1387 1388 macaddr = wlan_peer_get_macaddr(peer); 1389 obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0", 1390 QDF_MAC_ADDR_REF(macaddr)); 1391 WLAN_OBJMGR_BUG(0); 1392 return; 1393 } 1394 1395 status = wlan_objmgr_peer_release_debug_id_ref(peer, id); 1396 if (QDF_IS_STATUS_ERROR(status)) 1397 return; 1398 1399 wlan_objmgr_peer_deref_trace(peer, id, func, line); 1400 /* Provide synchronization from the access to add peer 1401 * to logically deleted peer list. 1402 */ 1403 wlan_peer_obj_lock(peer); 1404 /* Decrement ref count, free peer object, if ref count == 0 */ 1405 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { 1406 wlan_peer_obj_unlock(peer); 1407 wlan_objmgr_peer_obj_destroy(peer); 1408 } else { 1409 wlan_peer_obj_unlock(peer); 1410 } 1411 1412 return; 1413 } 1414 1415 qdf_export_symbol(wlan_objmgr_peer_release_ref_debug); 1416 #else wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)1417 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, 1418 wlan_objmgr_ref_dbgid id) 1419 { 1420 QDF_STATUS status; 1421 1422 if (!peer) { 1423 obj_mgr_err("peer obj is NULL for %d", id); 1424 QDF_ASSERT(0); 1425 return; 1426 } 1427 1428 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 1429 uint8_t *macaddr; 1430 1431 macaddr = wlan_peer_get_macaddr(peer); 1432 obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0", 1433 QDF_MAC_ADDR_REF(macaddr)); 1434 WLAN_OBJMGR_BUG(0); 1435 return; 1436 } 1437 1438 status = wlan_objmgr_peer_release_debug_id_ref(peer, id); 1439 if (QDF_IS_STATUS_ERROR(status)) 1440 return; 1441 1442 /* Provide synchronization from the access to add peer 1443 * to logically deleted peer list. 1444 */ 1445 wlan_peer_obj_lock(peer); 1446 /* Decrement ref count, free peer object, if ref count == 0 */ 1447 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { 1448 wlan_peer_obj_unlock(peer); 1449 wlan_objmgr_peer_obj_destroy(peer); 1450 } else { 1451 wlan_peer_obj_unlock(peer); 1452 } 1453 } 1454 1455 qdf_export_symbol(wlan_objmgr_peer_release_ref); 1456 #endif 1457 1458 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 1459 void wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer * peer,QDF_TRACE_LEVEL log_level)1460 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer, 1461 QDF_TRACE_LEVEL log_level) 1462 { 1463 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level); 1464 } 1465 1466 uint32_t wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)1467 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, 1468 enum wlan_umac_comp_id id) 1469 { 1470 return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]); 1471 } 1472 #else 1473 void wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer * peer,QDF_TRACE_LEVEL log_level)1474 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer, 1475 QDF_TRACE_LEVEL log_level) 1476 { 1477 uint32_t pending_ref; 1478 1479 pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt); 1480 obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref); 1481 } 1482 1483 uint32_t wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)1484 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, 1485 enum wlan_umac_comp_id id) 1486 { 1487 return 0; 1488 } 1489 #endif 1490 1491 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE wlan_peer_update_macaddr(struct wlan_objmgr_peer * peer,uint8_t * new_macaddr)1492 QDF_STATUS wlan_peer_update_macaddr(struct wlan_objmgr_peer *peer, 1493 uint8_t *new_macaddr) 1494 { 1495 struct wlan_objmgr_psoc *psoc; 1496 struct wlan_objmgr_vdev *vdev; 1497 uint8_t *macaddr; 1498 QDF_STATUS status; 1499 1500 if (!peer) { 1501 obj_mgr_err("PEER is NULL"); 1502 return QDF_STATUS_E_FAILURE; 1503 } 1504 1505 macaddr = wlan_peer_get_macaddr(peer); 1506 1507 vdev = wlan_peer_get_vdev(peer); 1508 if (!vdev) { 1509 obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")", 1510 QDF_MAC_ADDR_REF(macaddr)); 1511 return QDF_STATUS_E_FAILURE; 1512 } 1513 1514 /* get PSOC from VDEV, if it is NULL, return */ 1515 psoc = wlan_vdev_get_psoc(vdev); 1516 if (!psoc) { 1517 obj_mgr_err("PSOC is NULL for peer(" QDF_MAC_ADDR_FMT ")", 1518 QDF_MAC_ADDR_REF(macaddr)); 1519 return QDF_STATUS_E_FAILURE; 1520 } 1521 1522 status = wlan_objmgr_psoc_peer_detach(psoc, peer); 1523 if (QDF_IS_STATUS_ERROR(status)) { 1524 obj_mgr_err("Failed to detach peer(" QDF_MAC_ADDR_FMT ")", 1525 QDF_MAC_ADDR_REF(macaddr)); 1526 return status; 1527 } 1528 1529 wlan_peer_set_macaddr(peer, new_macaddr); 1530 1531 status = wlan_objmgr_psoc_peer_attach(psoc, peer); 1532 if (QDF_IS_STATUS_ERROR(status)) { 1533 obj_mgr_err("Failed to attach peer(" QDF_MAC_ADDR_FMT ")", 1534 QDF_MAC_ADDR_REF(new_macaddr)); 1535 return status; 1536 } 1537 return QDF_STATUS_SUCCESS; 1538 } 1539 #endif 1540