1 /* 2 * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 /** 19 * DOC: Public APIs to perform operations on Peer object 20 */ 21 #include <wlan_objmgr_cmn.h> 22 #include <wlan_objmgr_global_obj.h> 23 #include <wlan_objmgr_psoc_obj.h> 24 #include <wlan_objmgr_pdev_obj.h> 25 #include <wlan_objmgr_vdev_obj.h> 26 #include <wlan_objmgr_peer_obj.h> 27 #include <qdf_mem.h> 28 #include <qdf_module.h> 29 #include "wlan_objmgr_global_obj_i.h" 30 #include "wlan_objmgr_psoc_obj_i.h" 31 #include "wlan_objmgr_pdev_obj_i.h" 32 #include "wlan_objmgr_vdev_obj_i.h" 33 34 35 /** 36 ** APIs to Create/Delete Peer object APIs 37 */ 38 static QDF_STATUS wlan_objmgr_peer_object_status( 39 struct wlan_objmgr_peer *peer) 40 { 41 uint8_t id; 42 QDF_STATUS status = QDF_STATUS_SUCCESS; 43 44 wlan_peer_obj_lock(peer); 45 /* Iterate through all components to derive the object status */ 46 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 47 /* If component disabled, Ignore */ 48 if (peer->obj_status[id] == QDF_STATUS_COMP_DISABLED) 49 continue; 50 /* If component operates in Async, status is Partially created, 51 break */ 52 else if (peer->obj_status[id] == QDF_STATUS_COMP_ASYNC) { 53 if (!peer->peer_comp_priv_obj[id]) { 54 status = QDF_STATUS_COMP_ASYNC; 55 break; 56 } 57 /* If component failed to allocate its object, treat it as 58 failure, complete object need to be cleaned up */ 59 } else if ((peer->obj_status[id] == QDF_STATUS_E_NOMEM) || 60 (peer->obj_status[id] == QDF_STATUS_E_FAILURE)) { 61 obj_mgr_err("Peer comp object(id:%d) alloc fail", id); 62 status = QDF_STATUS_E_FAILURE; 63 break; 64 } 65 } 66 wlan_peer_obj_unlock(peer); 67 return status; 68 } 69 70 static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer) 71 { 72 struct wlan_objmgr_psoc *psoc; 73 struct wlan_objmgr_vdev *vdev; 74 uint8_t *macaddr; 75 uint8_t vdev_id; 76 77 if (!peer) { 78 obj_mgr_err("PEER is NULL"); 79 return QDF_STATUS_E_FAILURE; 80 } 81 82 macaddr = wlan_peer_get_macaddr(peer); 83 84 vdev = wlan_peer_get_vdev(peer); 85 if (!vdev) { 86 obj_mgr_err( 87 "VDEV is NULL for peer(%02x:%02x:%02x:%02x:%02x:%02x)", 88 macaddr[0], macaddr[1], macaddr[2], 89 macaddr[3], macaddr[4], macaddr[5]); 90 return QDF_STATUS_E_FAILURE; 91 } 92 93 vdev_id = wlan_vdev_get_id(vdev); 94 95 /* get PSOC from VDEV, if it is NULL, return */ 96 psoc = wlan_vdev_get_psoc(vdev); 97 if (!psoc) { 98 obj_mgr_err( 99 "PSOC is NULL for peer(%02x:%02x:%02x:%02x:%02x:%02x)", 100 macaddr[0], macaddr[1], macaddr[2], 101 macaddr[3], macaddr[4], macaddr[5]); 102 return QDF_STATUS_E_FAILURE; 103 } 104 105 /* Decrement ref count for BSS peer, so that BSS peer deletes last*/ 106 if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) || 107 (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP) || 108 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_CLI)) 109 wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev), 110 WLAN_OBJMGR_ID); 111 112 /* Detach peer from VDEV's peer list */ 113 if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) { 114 obj_mgr_err( 115 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) VDEV detach fail, vdev id: %d", 116 macaddr[0], macaddr[1], macaddr[2], 117 macaddr[3], macaddr[4], macaddr[5], vdev_id); 118 return QDF_STATUS_E_FAILURE; 119 } 120 /* Detach peer from PSOC's peer list */ 121 if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) { 122 obj_mgr_err( 123 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC detach failure", 124 macaddr[0], macaddr[1], macaddr[2], 125 macaddr[3], macaddr[4], macaddr[5]); 126 return QDF_STATUS_E_FAILURE; 127 } 128 qdf_spinlock_destroy(&peer->peer_lock); 129 qdf_mem_free(peer); 130 131 return QDF_STATUS_SUCCESS; 132 133 } 134 135 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 136 static void 137 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) 138 { 139 uint8_t id; 140 141 for (id = 0; id < WLAN_REF_ID_MAX; id++) 142 qdf_atomic_init(&peer->peer_objmgr.ref_id_dbg[id]); 143 } 144 #else 145 static inline void 146 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) {} 147 #endif 148 149 struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( 150 struct wlan_objmgr_vdev *vdev, 151 enum wlan_peer_type type, 152 uint8_t *macaddr) 153 { 154 struct wlan_objmgr_peer *peer; 155 struct wlan_objmgr_psoc *psoc; 156 wlan_objmgr_peer_create_handler handler; 157 wlan_objmgr_peer_status_handler stat_handler; 158 void *arg; 159 QDF_STATUS obj_status; 160 uint8_t id; 161 162 if (!vdev) { 163 obj_mgr_err( 164 "VDEV is NULL for peer (%02x:%02x:%02x:%02x:%02x:%02x)", 165 macaddr[0], macaddr[1], macaddr[2], 166 macaddr[3], macaddr[4], macaddr[5]); 167 return NULL; 168 } 169 /* Get psoc, if psoc is NULL, return */ 170 psoc = wlan_vdev_get_psoc(vdev); 171 if (!psoc) { 172 obj_mgr_err( 173 "PSOC is NULL for peer (%02x:%02x:%02x:%02x:%02x:%02x)", 174 macaddr[0], macaddr[1], macaddr[2], 175 macaddr[3], macaddr[4], macaddr[5]); 176 return NULL; 177 } 178 /* Allocate memory for peer object */ 179 peer = qdf_mem_malloc(sizeof(*peer)); 180 if (!peer) 181 return NULL; 182 183 peer->obj_state = WLAN_OBJ_STATE_ALLOCATED; 184 qdf_atomic_init(&peer->peer_objmgr.ref_cnt); 185 wlan_objmgr_peer_init_ref_id_debug(peer); 186 wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID); 187 /* set vdev to peer */ 188 wlan_peer_set_vdev(peer, vdev); 189 /* set peer type */ 190 wlan_peer_set_peer_type(peer, type); 191 /* set mac address of peer */ 192 wlan_peer_set_macaddr(peer, macaddr); 193 /* initialize peer state */ 194 wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE); 195 wlan_peer_mlme_reset_seq_num(peer); 196 peer->peer_objmgr.print_cnt = 0; 197 198 qdf_spinlock_create(&peer->peer_lock); 199 /* Attach peer to psoc, psoc maintains the node table for the device */ 200 if (wlan_objmgr_psoc_peer_attach(psoc, peer) != 201 QDF_STATUS_SUCCESS) { 202 obj_mgr_warn( 203 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC attach failure", 204 macaddr[0], macaddr[1], macaddr[2], 205 macaddr[3], macaddr[4], macaddr[5]); 206 qdf_spinlock_destroy(&peer->peer_lock); 207 qdf_mem_free(peer); 208 return NULL; 209 } 210 /* Attach peer to vdev peer table */ 211 if (wlan_objmgr_vdev_peer_attach(vdev, peer) != 212 QDF_STATUS_SUCCESS) { 213 obj_mgr_warn( 214 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) VDEV attach failure", 215 macaddr[0], macaddr[1], macaddr[2], 216 macaddr[3], macaddr[4], macaddr[5]); 217 /* if attach fails, detach from psoc table before free */ 218 wlan_objmgr_psoc_peer_detach(psoc, peer); 219 qdf_spinlock_destroy(&peer->peer_lock); 220 qdf_mem_free(peer); 221 return NULL; 222 } 223 wlan_peer_set_pdev_id(peer, wlan_objmgr_pdev_get_pdev_id( 224 wlan_vdev_get_pdev(vdev))); 225 /* Increment ref count for BSS peer, so that BSS peer deletes last*/ 226 if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP) 227 || (type == WLAN_PEER_P2P_CLI)) 228 wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev), 229 WLAN_OBJMGR_ID); 230 /* TODO init other parameters */ 231 /* Invoke registered create handlers */ 232 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 233 handler = g_umac_glb_obj->peer_create_handler[id]; 234 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 235 if (handler) 236 peer->obj_status[id] = handler(peer, arg); 237 else 238 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; 239 } 240 /* derive the object status */ 241 obj_status = wlan_objmgr_peer_object_status(peer); 242 /* If SUCCESS, Object is created */ 243 if (obj_status == QDF_STATUS_SUCCESS) { 244 peer->obj_state = WLAN_OBJ_STATE_CREATED; 245 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 246 stat_handler = g_umac_glb_obj->peer_status_handler[id]; 247 arg = g_umac_glb_obj->peer_status_handler_arg[id]; 248 if (stat_handler) 249 stat_handler(peer, arg, 250 QDF_STATUS_SUCCESS); 251 } 252 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 253 /* If any component operates in different context, update it 254 as partially created */ 255 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 256 } else if (obj_status == QDF_STATUS_E_FAILURE) { 257 /* Clean up the peer */ 258 obj_mgr_err( 259 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) comp object alloc fail", 260 macaddr[0], macaddr[1], macaddr[2], 261 macaddr[3], macaddr[4], macaddr[5]); 262 wlan_objmgr_peer_obj_delete(peer); 263 return NULL; 264 } 265 266 obj_mgr_debug("Created peer " QDF_MAC_ADDR_STR, 267 QDF_MAC_ADDR_ARRAY(macaddr)); 268 269 return peer; 270 } 271 272 static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) 273 { 274 uint8_t id; 275 wlan_objmgr_peer_destroy_handler handler; 276 QDF_STATUS obj_status; 277 void *arg; 278 uint8_t *macaddr; 279 280 if (!peer) { 281 obj_mgr_err("PEER is NULL"); 282 return QDF_STATUS_E_FAILURE; 283 } 284 wlan_objmgr_notify_destroy(peer, WLAN_PEER_OP); 285 286 macaddr = wlan_peer_get_macaddr(peer); 287 288 obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_STR, 289 QDF_MAC_ADDR_ARRAY(macaddr)); 290 291 if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 292 obj_mgr_err("PEER object del is not invoked obj_state:%d peer " 293 QDF_MAC_ADDR_STR, peer->obj_state, 294 QDF_MAC_ADDR_ARRAY(macaddr)); 295 WLAN_OBJMGR_BUG(0); 296 } 297 298 /* Invoke registered destroy handlers */ 299 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 300 handler = g_umac_glb_obj->peer_destroy_handler[id]; 301 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 302 if (handler && 303 (peer->obj_status[id] == QDF_STATUS_SUCCESS || 304 peer->obj_status[id] == QDF_STATUS_COMP_ASYNC)) 305 peer->obj_status[id] = handler(peer, arg); 306 else 307 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; 308 } 309 /* Derive the object status */ 310 obj_status = wlan_objmgr_peer_object_status(peer); 311 if (obj_status == QDF_STATUS_E_FAILURE) { 312 /* If it status is failure, memory will not be freed */ 313 QDF_BUG(0); 314 return QDF_STATUS_E_FAILURE; 315 } 316 /* few components deletion is in progress */ 317 if (obj_status == QDF_STATUS_COMP_ASYNC) { 318 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 319 return QDF_STATUS_COMP_ASYNC; 320 } 321 322 /* Free the peer object */ 323 return wlan_objmgr_peer_obj_free(peer); 324 } 325 326 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) 327 { 328 uint8_t print_idx; 329 uint8_t *macaddr; 330 331 if (!peer) { 332 obj_mgr_err("PEER is NULL"); 333 return QDF_STATUS_E_FAILURE; 334 } 335 336 wlan_peer_obj_lock(peer); 337 macaddr = wlan_peer_get_macaddr(peer); 338 wlan_peer_obj_unlock(peer); 339 340 obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_STR, 341 QDF_MAC_ADDR_ARRAY(macaddr)); 342 343 print_idx = qdf_get_pidx(); 344 wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG); 345 /** 346 * Update VDEV object state to LOGICALLY DELETED 347 * It prevents further access of this object 348 */ 349 wlan_peer_obj_lock(peer); 350 peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 351 wlan_peer_obj_unlock(peer); 352 wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP); 353 wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID); 354 355 return QDF_STATUS_SUCCESS; 356 } 357 qdf_export_symbol(wlan_objmgr_peer_obj_delete); 358 /** 359 ** APIs to attach/detach component objects 360 */ 361 QDF_STATUS wlan_objmgr_peer_component_obj_attach( 362 struct wlan_objmgr_peer *peer, 363 enum wlan_umac_comp_id id, 364 void *comp_priv_obj, 365 QDF_STATUS status) 366 { 367 wlan_objmgr_peer_status_handler s_hler; 368 void *arg; 369 uint8_t i; 370 QDF_STATUS obj_status; 371 372 /* component id is invalid */ 373 if (id >= WLAN_UMAC_MAX_COMPONENTS) 374 return QDF_STATUS_MAXCOMP_FAIL; 375 376 wlan_peer_obj_lock(peer); 377 /* If there is a valid entry, return failure, 378 valid object needs to be freed first */ 379 if (peer->peer_comp_priv_obj[id]) { 380 wlan_peer_obj_unlock(peer); 381 return QDF_STATUS_E_FAILURE; 382 } 383 /* Assign component object private pointer(can be NULL also), status */ 384 peer->peer_comp_priv_obj[id] = comp_priv_obj; 385 peer->obj_status[id] = status; 386 wlan_peer_obj_unlock(peer); 387 388 if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 389 return QDF_STATUS_SUCCESS; 390 391 /* If PEER object status is partially created means, this API is 392 invoked with differnt context. this block should be executed for async 393 components only */ 394 /* Derive status */ 395 obj_status = wlan_objmgr_peer_object_status(peer); 396 /* STATUS_SUCCESS means, object is CREATED */ 397 if (obj_status == QDF_STATUS_SUCCESS) 398 peer->obj_state = WLAN_OBJ_STATE_CREATED; 399 /* update state as CREATION failed, caller has to delete the 400 PEER object */ 401 else if (obj_status == QDF_STATUS_E_FAILURE) 402 peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 403 /* Notify components about the CREATION success/failure */ 404 if ((obj_status == QDF_STATUS_SUCCESS) || 405 (obj_status == QDF_STATUS_E_FAILURE)) { 406 /* nofity object status */ 407 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 408 s_hler = g_umac_glb_obj->peer_status_handler[i]; 409 arg = g_umac_glb_obj->peer_status_handler_arg[i]; 410 if (s_hler) 411 s_hler(peer, arg, obj_status); 412 } 413 } 414 return QDF_STATUS_SUCCESS; 415 } 416 417 QDF_STATUS wlan_objmgr_peer_component_obj_detach( 418 struct wlan_objmgr_peer *peer, 419 enum wlan_umac_comp_id id, 420 void *comp_priv_obj) 421 { 422 QDF_STATUS obj_status; 423 424 /* component id is invalid */ 425 if (id >= WLAN_UMAC_MAX_COMPONENTS) 426 return QDF_STATUS_MAXCOMP_FAIL; 427 428 wlan_peer_obj_lock(peer); 429 /* If there is a invalid entry, return failure */ 430 if (peer->peer_comp_priv_obj[id] != comp_priv_obj) { 431 peer->obj_status[id] = QDF_STATUS_E_FAILURE; 432 wlan_peer_obj_unlock(peer); 433 return QDF_STATUS_E_FAILURE; 434 } 435 /* Reset the pointer to NULL */ 436 peer->peer_comp_priv_obj[id] = NULL; 437 peer->obj_status[id] = QDF_STATUS_SUCCESS; 438 wlan_peer_obj_unlock(peer); 439 440 /* If PEER object status is partially destroyed means, this API is 441 invoked with differnt context, this block should be executed for async 442 components only */ 443 if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 444 (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 445 /* Derive object status */ 446 obj_status = wlan_objmgr_peer_object_status(peer); 447 if (obj_status == QDF_STATUS_SUCCESS) { 448 /*Update the status as Deleted, if full object 449 deletion is in progress */ 450 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 451 peer->obj_state = WLAN_OBJ_STATE_DELETED; 452 /* Move to creation state, since this component 453 deletion alone requested */ 454 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 455 peer->obj_state = WLAN_OBJ_STATE_CREATED; 456 /* Object status is failure */ 457 } else if (obj_status == QDF_STATUS_E_FAILURE) { 458 /*Update the status as Deletion failed, if full object 459 deletion is in progress */ 460 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 461 peer->obj_state = 462 WLAN_OBJ_STATE_DELETION_FAILED; 463 /* Move to creation state, since this component 464 deletion alone requested (do not block other 465 components) */ 466 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 467 peer->obj_state = WLAN_OBJ_STATE_CREATED; 468 } 469 470 /* Delete peer object */ 471 if ((obj_status == QDF_STATUS_SUCCESS) && 472 (peer->obj_state == WLAN_OBJ_STATE_DELETED)) { 473 /* Free the peer object */ 474 return wlan_objmgr_peer_obj_free(peer); 475 } 476 } 477 478 return QDF_STATUS_SUCCESS; 479 } 480 481 482 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation( 483 struct wlan_objmgr_peer *peer, 484 enum wlan_umac_comp_id id) 485 { 486 wlan_objmgr_peer_create_handler handler; 487 void *arg; 488 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 489 490 /* Component id is invalid */ 491 if (id >= WLAN_UMAC_MAX_COMPONENTS) 492 return QDF_STATUS_MAXCOMP_FAIL; 493 494 wlan_peer_obj_lock(peer); 495 /* If component object is already created, delete old 496 component object, then invoke creation */ 497 if (peer->peer_comp_priv_obj[id]) { 498 wlan_peer_obj_unlock(peer); 499 return QDF_STATUS_E_FAILURE; 500 } 501 wlan_peer_obj_unlock(peer); 502 503 /* Invoke registered create handlers */ 504 handler = g_umac_glb_obj->peer_create_handler[id]; 505 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 506 if (handler) 507 peer->obj_status[id] = handler(peer, arg); 508 else 509 return QDF_STATUS_E_FAILURE; 510 511 /* If object status is created, then only handle this object status */ 512 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 513 /* Derive object status */ 514 obj_status = wlan_objmgr_peer_object_status(peer); 515 /* Move PDEV object state to Partially created state */ 516 if (obj_status == QDF_STATUS_COMP_ASYNC) { 517 /*TODO atomic */ 518 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 519 } 520 } 521 522 return obj_status; 523 } 524 525 526 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion( 527 struct wlan_objmgr_peer *peer, 528 enum wlan_umac_comp_id id) 529 { 530 wlan_objmgr_peer_destroy_handler handler; 531 void *arg; 532 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 533 534 /* component id is invalid */ 535 if (id >= WLAN_UMAC_MAX_COMPONENTS) 536 return QDF_STATUS_MAXCOMP_FAIL; 537 538 wlan_peer_obj_lock(peer); 539 /* Component object was never created, invalid operation */ 540 if (!peer->peer_comp_priv_obj[id]) { 541 wlan_peer_obj_unlock(peer); 542 return QDF_STATUS_E_FAILURE; 543 } 544 545 wlan_peer_obj_unlock(peer); 546 547 /* Invoke registered destroy handlers */ 548 handler = g_umac_glb_obj->peer_destroy_handler[id]; 549 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 550 if (handler) 551 peer->obj_status[id] = handler(peer, arg); 552 else 553 return QDF_STATUS_E_FAILURE; 554 555 /* If object status is created, then only handle this object status */ 556 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 557 obj_status = wlan_objmgr_peer_object_status(peer); 558 /* move object state to DEL progress */ 559 if (obj_status == QDF_STATUS_COMP_ASYNC) 560 peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 561 } 562 return obj_status; 563 } 564 565 void *wlan_objmgr_peer_get_comp_private_obj( 566 struct wlan_objmgr_peer *peer, 567 enum wlan_umac_comp_id id) 568 { 569 void *comp_priv_obj; 570 571 /* component id is invalid */ 572 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 573 QDF_BUG(0); 574 return NULL; 575 } 576 577 if (!peer) { 578 QDF_BUG(0); 579 return NULL; 580 } 581 582 comp_priv_obj = peer->peer_comp_priv_obj[id]; 583 return comp_priv_obj; 584 } 585 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj); 586 587 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 588 static inline void 589 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, 590 wlan_objmgr_ref_dbgid id) 591 { 592 qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]); 593 } 594 #else 595 static inline void 596 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, 597 wlan_objmgr_ref_dbgid id) {} 598 #endif 599 600 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, 601 wlan_objmgr_ref_dbgid id) 602 { 603 if (!peer) { 604 obj_mgr_err("peer obj is NULL for %d", id); 605 QDF_ASSERT(0); 606 return; 607 } 608 /* Increment ref count */ 609 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); 610 wlan_objmgr_peer_get_debug_id_ref(peer, id); 611 612 return; 613 } 614 qdf_export_symbol(wlan_objmgr_peer_get_ref); 615 616 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, 617 wlan_objmgr_ref_dbgid id) 618 { 619 if (!peer) { 620 obj_mgr_err("peer obj is NULL for %d", id); 621 QDF_ASSERT(0); 622 return QDF_STATUS_E_FAILURE; 623 } 624 625 wlan_peer_obj_lock(peer); 626 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) { 627 wlan_peer_obj_unlock(peer); 628 if (peer->peer_objmgr.print_cnt++ <= 629 WLAN_OBJMGR_RATELIMIT_THRESH) { 630 uint8_t *macaddr; 631 632 macaddr = wlan_peer_get_macaddr(peer); 633 obj_mgr_debug( 634 "peer(" QDF_MAC_ADDR_STR ") not in Created st(%d)", 635 QDF_MAC_ADDR_ARRAY(macaddr), 636 peer->obj_state); 637 } 638 return QDF_STATUS_E_RESOURCES; 639 } 640 641 wlan_objmgr_peer_get_ref(peer, id); 642 wlan_peer_obj_unlock(peer); 643 644 return QDF_STATUS_SUCCESS; 645 } 646 qdf_export_symbol(wlan_objmgr_peer_try_get_ref); 647 648 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 649 static QDF_STATUS 650 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, 651 wlan_objmgr_ref_dbgid id) 652 { 653 if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) { 654 uint8_t *macaddr; 655 656 macaddr = wlan_peer_get_macaddr(peer); 657 obj_mgr_err( 658 "peer(%02x:%02x:%02x:%02x:%02x:%02x) ref was not taken by %d", 659 macaddr[0], macaddr[1], macaddr[2], 660 macaddr[3], macaddr[4], macaddr[5], id); 661 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, 662 QDF_TRACE_LEVEL_FATAL); 663 WLAN_OBJMGR_BUG(0); 664 return QDF_STATUS_E_FAILURE; 665 } 666 667 qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]); 668 return QDF_STATUS_SUCCESS; 669 } 670 #else 671 static QDF_STATUS 672 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, 673 wlan_objmgr_ref_dbgid id) 674 { 675 return QDF_STATUS_SUCCESS; 676 } 677 #endif 678 679 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, 680 wlan_objmgr_ref_dbgid id) 681 { 682 QDF_STATUS status; 683 684 if (!peer) { 685 obj_mgr_err("peer obj is NULL for %d", id); 686 QDF_ASSERT(0); 687 return; 688 } 689 690 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 691 uint8_t *macaddr; 692 693 macaddr = wlan_peer_get_macaddr(peer); 694 obj_mgr_err("peer(%02x:%02x:%02x:%02x:%02x:%02x) ref cnt is 0", 695 macaddr[0], macaddr[1], macaddr[2], 696 macaddr[3], macaddr[4], macaddr[5]); 697 WLAN_OBJMGR_BUG(0); 698 return; 699 } 700 701 status = wlan_objmgr_peer_release_debug_id_ref(peer, id); 702 if (QDF_IS_STATUS_ERROR(status)) 703 return; 704 705 /* Provide synchronization from the access to add peer 706 * to logically deleted peer list. 707 */ 708 wlan_peer_obj_lock(peer); 709 /* Decrement ref count, free peer object, if ref count == 0 */ 710 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { 711 wlan_peer_obj_unlock(peer); 712 wlan_objmgr_peer_obj_destroy(peer); 713 } else { 714 wlan_peer_obj_unlock(peer); 715 } 716 717 return; 718 } 719 qdf_export_symbol(wlan_objmgr_peer_release_ref); 720 721 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head( 722 struct wlan_objmgr_vdev *vdev, 723 qdf_list_t *peer_list, 724 wlan_objmgr_ref_dbgid dbg_id) 725 { 726 struct wlan_objmgr_peer *peer; 727 qdf_list_node_t *vdev_node = NULL; 728 qdf_list_node_t *prev_vdev_node = NULL; 729 730 wlan_vdev_obj_lock(vdev); 731 732 if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) { 733 wlan_vdev_obj_unlock(vdev); 734 return NULL; 735 } 736 737 do { 738 peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 739 vdev_peer); 740 741 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 742 QDF_STATUS_SUCCESS) { 743 wlan_vdev_obj_unlock(vdev); 744 return peer; 745 } 746 747 prev_vdev_node = vdev_node; 748 } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 749 QDF_STATUS_SUCCESS); 750 751 wlan_vdev_obj_unlock(vdev); 752 753 return NULL; 754 } 755 756 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev( 757 struct wlan_objmgr_vdev *vdev, 758 qdf_list_t *peer_list, 759 struct wlan_objmgr_peer *peer, 760 wlan_objmgr_ref_dbgid dbg_id) 761 { 762 struct wlan_objmgr_peer *peer_next; 763 qdf_list_node_t *vdev_node = NULL; 764 qdf_list_node_t *prev_vdev_node = NULL; 765 766 if (!peer) 767 return NULL; 768 769 wlan_vdev_obj_lock(vdev); 770 771 prev_vdev_node = &peer->vdev_peer; 772 while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 773 QDF_STATUS_SUCCESS) { 774 peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 775 vdev_peer); 776 777 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == 778 QDF_STATUS_SUCCESS) { 779 wlan_vdev_obj_unlock(vdev); 780 return peer_next; 781 } 782 783 prev_vdev_node = vdev_node; 784 } 785 786 wlan_vdev_obj_unlock(vdev); 787 788 return NULL; 789 } 790 791 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( 792 struct wlan_peer_list *peer_list, 793 uint8_t hash_index, 794 struct wlan_objmgr_peer *peer, 795 wlan_objmgr_ref_dbgid dbg_id) 796 { 797 struct wlan_objmgr_peer *peer_next = NULL; 798 qdf_list_node_t *psoc_node = NULL; 799 qdf_list_node_t *prev_psoc_node = NULL; 800 qdf_list_t *obj_list; 801 802 qdf_spin_lock_bh(&peer_list->peer_list_lock); 803 obj_list = &peer_list->peer_hash[hash_index]; 804 805 prev_psoc_node = &peer->psoc_peer; 806 while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 807 QDF_STATUS_SUCCESS) { 808 peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 809 psoc_peer); 810 811 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == 812 QDF_STATUS_SUCCESS) { 813 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 814 return peer_next; 815 } 816 817 prev_psoc_node = psoc_node; 818 } 819 820 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 821 822 return NULL; 823 } 824 825 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( 826 struct wlan_peer_list *peer_list, 827 uint8_t hash_index, 828 wlan_objmgr_ref_dbgid dbg_id) 829 { 830 struct wlan_objmgr_peer *peer; 831 qdf_list_node_t *psoc_node = NULL; 832 qdf_list_node_t *prev_psoc_node = NULL; 833 qdf_list_t *obj_list; 834 835 qdf_spin_lock_bh(&peer_list->peer_list_lock); 836 obj_list = &peer_list->peer_hash[hash_index]; 837 838 if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) { 839 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 840 return NULL; 841 } 842 843 do { 844 peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 845 psoc_peer); 846 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 847 QDF_STATUS_SUCCESS) { 848 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 849 return peer; 850 } 851 852 prev_psoc_node = psoc_node; 853 } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 854 QDF_STATUS_SUCCESS); 855 856 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 857 return NULL; 858 } 859 860 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( 861 struct wlan_peer_list *peer_list, 862 uint8_t hash_index, 863 wlan_objmgr_ref_dbgid dbg_id) 864 { 865 struct wlan_objmgr_peer *peer; 866 qdf_list_t *obj_list; 867 868 qdf_spin_lock_bh(&peer_list->peer_list_lock); 869 obj_list = &peer_list->peer_hash[hash_index]; 870 871 peer = wlan_psoc_peer_list_peek_head(obj_list); 872 873 /** 874 * This API is invoked by caller, only when caller need to access the 875 * peer object, though object is not in active state, this API should be 876 * used carefully, where multiple object frees are not triggered 877 */ 878 if (peer) 879 wlan_objmgr_peer_get_ref(peer, dbg_id); 880 881 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 882 883 return peer; 884 } 885 886 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( 887 struct wlan_peer_list *peer_list, uint8_t hash_index, 888 struct wlan_objmgr_peer *peer, 889 wlan_objmgr_ref_dbgid dbg_id) 890 { 891 qdf_list_t *obj_list; 892 struct wlan_objmgr_peer *peer_next; 893 894 qdf_spin_lock_bh(&peer_list->peer_list_lock); 895 obj_list = &peer_list->peer_hash[hash_index]; 896 897 peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer); 898 /** 899 * This API is invoked by caller, only when caller need to access the 900 * peer object, though object is not in active state, this API should be 901 * used carefully, where multiple free on object are not triggered 902 */ 903 if (peer_next) 904 wlan_objmgr_peer_get_ref(peer_next, dbg_id); 905 906 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 907 908 return peer_next; 909 } 910 911 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 912 void 913 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer, 914 QDF_TRACE_LEVEL log_level) 915 { 916 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level); 917 } 918 919 uint32_t 920 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, 921 enum wlan_umac_comp_id id) 922 { 923 return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]); 924 } 925 #else 926 void 927 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer, 928 QDF_TRACE_LEVEL log_level) 929 { 930 uint32_t pending_ref; 931 932 pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt); 933 obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref); 934 } 935 936 uint32_t 937 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, 938 enum wlan_umac_comp_id id) 939 { 940 return 0; 941 } 942 #endif 943