1 /* 2 * Copyright (c) 2016-2018 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] == NULL) { 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 == NULL) { 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 == NULL) { 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 == NULL) { 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 struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( 136 struct wlan_objmgr_vdev *vdev, 137 enum wlan_peer_type type, 138 uint8_t *macaddr) 139 { 140 struct wlan_objmgr_peer *peer; 141 struct wlan_objmgr_psoc *psoc; 142 wlan_objmgr_peer_create_handler handler; 143 wlan_objmgr_peer_status_handler stat_handler; 144 void *arg; 145 QDF_STATUS obj_status; 146 uint8_t id; 147 148 if (vdev == NULL) { 149 obj_mgr_err( 150 "VDEV is NULL for peer (%02x:%02x:%02x:%02x:%02x:%02x)", 151 macaddr[0], macaddr[1], macaddr[2], 152 macaddr[3], macaddr[4], macaddr[5]); 153 return NULL; 154 } 155 /* Get psoc, if psoc is NULL, return */ 156 psoc = wlan_vdev_get_psoc(vdev); 157 if (psoc == NULL) { 158 obj_mgr_err( 159 "PSOC is NULL for peer (%02x:%02x:%02x:%02x:%02x:%02x)", 160 macaddr[0], macaddr[1], macaddr[2], 161 macaddr[3], macaddr[4], macaddr[5]); 162 return NULL; 163 } 164 /* Allocate memory for peer object */ 165 peer = qdf_mem_malloc(sizeof(*peer)); 166 if (peer == NULL) { 167 obj_mgr_err( 168 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) allocation failure", 169 macaddr[0], macaddr[1], macaddr[2], 170 macaddr[3], macaddr[4], macaddr[5]); 171 return NULL; 172 } 173 peer->obj_state = WLAN_OBJ_STATE_ALLOCATED; 174 qdf_atomic_init(&peer->peer_objmgr.ref_cnt); 175 for (id = 0; id < WLAN_REF_ID_MAX; id++) 176 qdf_atomic_init(&peer->peer_objmgr.ref_id_dbg[id]); 177 wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID); 178 /* set vdev to peer */ 179 wlan_peer_set_vdev(peer, vdev); 180 /* set peer type */ 181 wlan_peer_set_peer_type(peer, type); 182 /* set mac address of peer */ 183 wlan_peer_set_macaddr(peer, macaddr); 184 /* initialize peer state */ 185 wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE); 186 wlan_peer_mlme_reset_seq_num(peer); 187 peer->peer_objmgr.print_cnt = 0; 188 189 qdf_spinlock_create(&peer->peer_lock); 190 /* Attach peer to psoc, psoc maintains the node table for the device */ 191 if (wlan_objmgr_psoc_peer_attach(psoc, peer) != 192 QDF_STATUS_SUCCESS) { 193 obj_mgr_warn( 194 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC attach failure", 195 macaddr[0], macaddr[1], macaddr[2], 196 macaddr[3], macaddr[4], macaddr[5]); 197 qdf_spinlock_destroy(&peer->peer_lock); 198 qdf_mem_free(peer); 199 return NULL; 200 } 201 /* Attach peer to vdev peer table */ 202 if (wlan_objmgr_vdev_peer_attach(vdev, peer) != 203 QDF_STATUS_SUCCESS) { 204 obj_mgr_warn( 205 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) VDEV attach failure", 206 macaddr[0], macaddr[1], macaddr[2], 207 macaddr[3], macaddr[4], macaddr[5]); 208 /* if attach fails, detach from psoc table before free */ 209 wlan_objmgr_psoc_peer_detach(psoc, peer); 210 qdf_spinlock_destroy(&peer->peer_lock); 211 qdf_mem_free(peer); 212 return NULL; 213 } 214 /* Increment ref count for BSS peer, so that BSS peer deletes last*/ 215 if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP) 216 || (type == WLAN_PEER_P2P_CLI)) 217 wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev), 218 WLAN_OBJMGR_ID); 219 /* TODO init other parameters */ 220 /* Invoke registered create handlers */ 221 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 222 handler = g_umac_glb_obj->peer_create_handler[id]; 223 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 224 if (handler != NULL) 225 peer->obj_status[id] = handler(peer, arg); 226 else 227 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; 228 } 229 /* derive the object status */ 230 obj_status = wlan_objmgr_peer_object_status(peer); 231 /* If SUCCESS, Object is created */ 232 if (obj_status == QDF_STATUS_SUCCESS) { 233 peer->obj_state = WLAN_OBJ_STATE_CREATED; 234 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 235 stat_handler = g_umac_glb_obj->peer_status_handler[id]; 236 arg = g_umac_glb_obj->peer_status_handler_arg[id]; 237 if (stat_handler != NULL) 238 stat_handler(peer, arg, 239 QDF_STATUS_SUCCESS); 240 } 241 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 242 /* If any component operates in different context, update it 243 as partially created */ 244 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 245 } else if (obj_status == QDF_STATUS_E_FAILURE) { 246 /* Clean up the peer */ 247 obj_mgr_err( 248 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) comp object alloc fail", 249 macaddr[0], macaddr[1], macaddr[2], 250 macaddr[3], macaddr[4], macaddr[5]); 251 wlan_objmgr_peer_obj_delete(peer); 252 return NULL; 253 } 254 255 obj_mgr_debug("Created peer " QDF_MAC_ADDR_STR, 256 QDF_MAC_ADDR_ARRAY(macaddr)); 257 258 return peer; 259 } 260 261 static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) 262 { 263 uint8_t id; 264 wlan_objmgr_peer_destroy_handler handler; 265 QDF_STATUS obj_status; 266 void *arg; 267 uint8_t *macaddr; 268 269 if (peer == NULL) { 270 obj_mgr_err("PEER is NULL"); 271 return QDF_STATUS_E_FAILURE; 272 } 273 wlan_objmgr_notify_destroy(peer, WLAN_PEER_OP); 274 275 macaddr = wlan_peer_get_macaddr(peer); 276 277 obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_STR, 278 QDF_MAC_ADDR_ARRAY(macaddr)); 279 280 if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 281 obj_mgr_err( 282 "peer(%02x:%02x:%02x:%02x:%02x:%02x) object del is not invoked", 283 macaddr[0], macaddr[1], macaddr[2], 284 macaddr[3], macaddr[4], macaddr[5]); 285 WLAN_OBJMGR_BUG(0); 286 } 287 288 /* Invoke registered destroy handlers */ 289 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 290 handler = g_umac_glb_obj->peer_destroy_handler[id]; 291 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 292 if (handler != NULL) 293 peer->obj_status[id] = handler(peer, arg); 294 else 295 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; 296 } 297 /* Derive the object status */ 298 obj_status = wlan_objmgr_peer_object_status(peer); 299 if (obj_status == QDF_STATUS_E_FAILURE) { 300 /* If it status is failure, memory will not be freed */ 301 QDF_BUG(0); 302 return QDF_STATUS_E_FAILURE; 303 } 304 /* few components deletion is in progress */ 305 if (obj_status == QDF_STATUS_COMP_ASYNC) { 306 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 307 return QDF_STATUS_COMP_ASYNC; 308 } 309 310 /* Free the peer object */ 311 return wlan_objmgr_peer_obj_free(peer); 312 } 313 314 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) 315 { 316 uint8_t print_idx; 317 uint8_t *macaddr; 318 319 if (peer == NULL) { 320 obj_mgr_err("PEER is NULL"); 321 return QDF_STATUS_E_FAILURE; 322 } 323 324 wlan_peer_obj_lock(peer); 325 macaddr = wlan_peer_get_macaddr(peer); 326 wlan_peer_obj_unlock(peer); 327 328 obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_STR, 329 QDF_MAC_ADDR_ARRAY(macaddr)); 330 331 print_idx = qdf_get_pidx(); 332 if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR, 333 QDF_TRACE_LEVEL_DEBUG)) { 334 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg); 335 } 336 337 /** 338 * Update VDEV object state to LOGICALLY DELETED 339 * It prevents further access of this object 340 */ 341 wlan_peer_obj_lock(peer); 342 peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 343 wlan_peer_obj_unlock(peer); 344 wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP); 345 wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID); 346 347 return QDF_STATUS_SUCCESS; 348 } 349 qdf_export_symbol(wlan_objmgr_peer_obj_delete); 350 /** 351 ** APIs to attach/detach component objects 352 */ 353 QDF_STATUS wlan_objmgr_peer_component_obj_attach( 354 struct wlan_objmgr_peer *peer, 355 enum wlan_umac_comp_id id, 356 void *comp_priv_obj, 357 QDF_STATUS status) 358 { 359 wlan_objmgr_peer_status_handler s_hler; 360 void *arg; 361 uint8_t i; 362 QDF_STATUS obj_status; 363 364 /* component id is invalid */ 365 if (id >= WLAN_UMAC_MAX_COMPONENTS) 366 return QDF_STATUS_MAXCOMP_FAIL; 367 368 wlan_peer_obj_lock(peer); 369 /* If there is a valid entry, return failure, 370 valid object needs to be freed first */ 371 if (peer->peer_comp_priv_obj[id] != NULL) { 372 wlan_peer_obj_unlock(peer); 373 return QDF_STATUS_E_FAILURE; 374 } 375 /* Assign component object private pointer(can be NULL also), status */ 376 peer->peer_comp_priv_obj[id] = comp_priv_obj; 377 peer->obj_status[id] = status; 378 wlan_peer_obj_unlock(peer); 379 380 if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 381 return QDF_STATUS_SUCCESS; 382 383 /* If PEER object status is partially created means, this API is 384 invoked with differnt context. this block should be executed for async 385 components only */ 386 /* Derive status */ 387 obj_status = wlan_objmgr_peer_object_status(peer); 388 /* STATUS_SUCCESS means, object is CREATED */ 389 if (obj_status == QDF_STATUS_SUCCESS) 390 peer->obj_state = WLAN_OBJ_STATE_CREATED; 391 /* update state as CREATION failed, caller has to delete the 392 PEER object */ 393 else if (obj_status == QDF_STATUS_E_FAILURE) 394 peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 395 /* Notify components about the CREATION success/failure */ 396 if ((obj_status == QDF_STATUS_SUCCESS) || 397 (obj_status == QDF_STATUS_E_FAILURE)) { 398 /* nofity object status */ 399 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 400 s_hler = g_umac_glb_obj->peer_status_handler[i]; 401 arg = g_umac_glb_obj->peer_status_handler_arg[i]; 402 if (s_hler != NULL) 403 s_hler(peer, arg, obj_status); 404 } 405 } 406 return QDF_STATUS_SUCCESS; 407 } 408 409 QDF_STATUS wlan_objmgr_peer_component_obj_detach( 410 struct wlan_objmgr_peer *peer, 411 enum wlan_umac_comp_id id, 412 void *comp_priv_obj) 413 { 414 QDF_STATUS obj_status; 415 416 /* component id is invalid */ 417 if (id >= WLAN_UMAC_MAX_COMPONENTS) 418 return QDF_STATUS_MAXCOMP_FAIL; 419 420 wlan_peer_obj_lock(peer); 421 /* If there is a invalid entry, return failure */ 422 if (peer->peer_comp_priv_obj[id] != comp_priv_obj) { 423 peer->obj_status[id] = QDF_STATUS_E_FAILURE; 424 wlan_peer_obj_unlock(peer); 425 return QDF_STATUS_E_FAILURE; 426 } 427 /* Reset the pointer to NULL */ 428 peer->peer_comp_priv_obj[id] = NULL; 429 peer->obj_status[id] = QDF_STATUS_SUCCESS; 430 wlan_peer_obj_unlock(peer); 431 432 /* If PEER object status is partially destroyed means, this API is 433 invoked with differnt context, this block should be executed for async 434 components only */ 435 if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 436 (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 437 /* Derive object status */ 438 obj_status = wlan_objmgr_peer_object_status(peer); 439 if (obj_status == QDF_STATUS_SUCCESS) { 440 /*Update the status as Deleted, if full object 441 deletion is in progress */ 442 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 443 peer->obj_state = WLAN_OBJ_STATE_DELETED; 444 /* Move to creation state, since this component 445 deletion alone requested */ 446 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 447 peer->obj_state = WLAN_OBJ_STATE_CREATED; 448 /* Object status is failure */ 449 } else if (obj_status == QDF_STATUS_E_FAILURE) { 450 /*Update the status as Deletion failed, if full object 451 deletion is in progress */ 452 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 453 peer->obj_state = 454 WLAN_OBJ_STATE_DELETION_FAILED; 455 /* Move to creation state, since this component 456 deletion alone requested (do not block other 457 components) */ 458 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 459 peer->obj_state = WLAN_OBJ_STATE_CREATED; 460 } 461 462 /* Delete peer object */ 463 if ((obj_status == QDF_STATUS_SUCCESS) && 464 (peer->obj_state == WLAN_OBJ_STATE_DELETED)) { 465 /* Free the peer object */ 466 return wlan_objmgr_peer_obj_free(peer); 467 } 468 } 469 470 return QDF_STATUS_SUCCESS; 471 } 472 473 474 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation( 475 struct wlan_objmgr_peer *peer, 476 enum wlan_umac_comp_id id) 477 { 478 wlan_objmgr_peer_create_handler handler; 479 void *arg; 480 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 481 482 /* Component id is invalid */ 483 if (id >= WLAN_UMAC_MAX_COMPONENTS) 484 return QDF_STATUS_MAXCOMP_FAIL; 485 486 wlan_peer_obj_lock(peer); 487 /* If component object is already created, delete old 488 component object, then invoke creation */ 489 if (peer->peer_comp_priv_obj[id] != NULL) { 490 wlan_peer_obj_unlock(peer); 491 return QDF_STATUS_E_FAILURE; 492 } 493 wlan_peer_obj_unlock(peer); 494 495 /* Invoke registered create handlers */ 496 handler = g_umac_glb_obj->peer_create_handler[id]; 497 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 498 if (handler != NULL) 499 peer->obj_status[id] = handler(peer, arg); 500 else 501 return QDF_STATUS_E_FAILURE; 502 503 /* If object status is created, then only handle this object status */ 504 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 505 /* Derive object status */ 506 obj_status = wlan_objmgr_peer_object_status(peer); 507 /* Move PDEV object state to Partially created state */ 508 if (obj_status == QDF_STATUS_COMP_ASYNC) { 509 /*TODO atomic */ 510 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 511 } 512 } 513 514 return obj_status; 515 } 516 517 518 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion( 519 struct wlan_objmgr_peer *peer, 520 enum wlan_umac_comp_id id) 521 { 522 wlan_objmgr_peer_destroy_handler handler; 523 void *arg; 524 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 525 526 /* component id is invalid */ 527 if (id >= WLAN_UMAC_MAX_COMPONENTS) 528 return QDF_STATUS_MAXCOMP_FAIL; 529 530 wlan_peer_obj_lock(peer); 531 /* Component object was never created, invalid operation */ 532 if (peer->peer_comp_priv_obj[id] == NULL) { 533 wlan_peer_obj_unlock(peer); 534 return QDF_STATUS_E_FAILURE; 535 } 536 537 wlan_peer_obj_unlock(peer); 538 539 /* Invoke registered destroy handlers */ 540 handler = g_umac_glb_obj->peer_destroy_handler[id]; 541 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 542 if (handler != NULL) 543 peer->obj_status[id] = handler(peer, arg); 544 else 545 return QDF_STATUS_E_FAILURE; 546 547 /* If object status is created, then only handle this object status */ 548 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 549 obj_status = wlan_objmgr_peer_object_status(peer); 550 /* move object state to DEL progress */ 551 if (obj_status == QDF_STATUS_COMP_ASYNC) 552 peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 553 } 554 return obj_status; 555 } 556 557 void *wlan_objmgr_peer_get_comp_private_obj( 558 struct wlan_objmgr_peer *peer, 559 enum wlan_umac_comp_id id) 560 { 561 void *comp_priv_obj; 562 563 /* component id is invalid */ 564 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 565 QDF_BUG(0); 566 return NULL; 567 } 568 569 if (peer == NULL) { 570 QDF_BUG(0); 571 return NULL; 572 } 573 574 comp_priv_obj = peer->peer_comp_priv_obj[id]; 575 return comp_priv_obj; 576 } 577 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj); 578 579 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, 580 wlan_objmgr_ref_dbgid id) 581 { 582 if (peer == NULL) { 583 obj_mgr_err("peer obj is NULL for %d", id); 584 QDF_ASSERT(0); 585 return; 586 } 587 /* Increment ref count */ 588 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); 589 qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]); 590 591 return; 592 } 593 qdf_export_symbol(wlan_objmgr_peer_get_ref); 594 595 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, 596 wlan_objmgr_ref_dbgid id) 597 { 598 599 uint8_t *macaddr; 600 601 if (peer == NULL) { 602 obj_mgr_err("peer obj is NULL for %d", id); 603 QDF_ASSERT(0); 604 return QDF_STATUS_E_FAILURE; 605 } 606 607 wlan_peer_obj_lock(peer); 608 macaddr = wlan_peer_get_macaddr(peer); 609 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) { 610 wlan_peer_obj_unlock(peer); 611 if (peer->peer_objmgr.print_cnt++ <= 612 WLAN_OBJMGR_RATELIMIT_THRESH) 613 obj_mgr_warn( 614 "peer(" QDF_MAC_ADDR_STR ") not in Created st(%d)", 615 QDF_MAC_ADDR_ARRAY(macaddr), 616 peer->obj_state); 617 return QDF_STATUS_E_RESOURCES; 618 } 619 620 wlan_objmgr_peer_get_ref(peer, id); 621 wlan_peer_obj_unlock(peer); 622 623 return QDF_STATUS_SUCCESS; 624 } 625 qdf_export_symbol(wlan_objmgr_peer_try_get_ref); 626 627 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, 628 wlan_objmgr_ref_dbgid id) 629 { 630 631 uint8_t *macaddr; 632 633 if (peer == NULL) { 634 obj_mgr_err("peer obj is NULL for %d", id); 635 QDF_ASSERT(0); 636 return; 637 } 638 639 macaddr = wlan_peer_get_macaddr(peer); 640 641 if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) { 642 obj_mgr_err( 643 "peer(%02x:%02x:%02x:%02x:%02x:%02x) ref was not taken by %d", 644 macaddr[0], macaddr[1], macaddr[2], 645 macaddr[3], macaddr[4], macaddr[5], id); 646 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg); 647 WLAN_OBJMGR_BUG(0); 648 } 649 650 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 651 obj_mgr_err("peer(%02x:%02x:%02x:%02x:%02x:%02x) ref cnt is 0", 652 macaddr[0], macaddr[1], macaddr[2], 653 macaddr[3], macaddr[4], macaddr[5]); 654 WLAN_OBJMGR_BUG(0); 655 return; 656 } 657 qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]); 658 659 /* Provide synchronization from the access to add peer 660 * to logically deleted peer list. 661 */ 662 wlan_peer_obj_lock(peer); 663 /* Decrement ref count, free peer object, if ref count == 0 */ 664 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { 665 wlan_peer_obj_unlock(peer); 666 wlan_objmgr_peer_obj_destroy(peer); 667 } else { 668 wlan_peer_obj_unlock(peer); 669 } 670 671 return; 672 } 673 qdf_export_symbol(wlan_objmgr_peer_release_ref); 674