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 #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 == NULL) { 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 == NULL) { 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 == NULL) { 181 obj_mgr_err( 182 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) allocation failure", 183 macaddr[0], macaddr[1], macaddr[2], 184 macaddr[3], macaddr[4], macaddr[5]); 185 return NULL; 186 } 187 peer->obj_state = WLAN_OBJ_STATE_ALLOCATED; 188 qdf_atomic_init(&peer->peer_objmgr.ref_cnt); 189 wlan_objmgr_peer_init_ref_id_debug(peer); 190 wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID); 191 /* set vdev to peer */ 192 wlan_peer_set_vdev(peer, vdev); 193 /* set peer type */ 194 wlan_peer_set_peer_type(peer, type); 195 /* set mac address of peer */ 196 wlan_peer_set_macaddr(peer, macaddr); 197 /* initialize peer state */ 198 wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE); 199 wlan_peer_mlme_reset_seq_num(peer); 200 peer->peer_objmgr.print_cnt = 0; 201 202 qdf_spinlock_create(&peer->peer_lock); 203 /* Attach peer to psoc, psoc maintains the node table for the device */ 204 if (wlan_objmgr_psoc_peer_attach(psoc, peer) != 205 QDF_STATUS_SUCCESS) { 206 obj_mgr_warn( 207 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC attach failure", 208 macaddr[0], macaddr[1], macaddr[2], 209 macaddr[3], macaddr[4], macaddr[5]); 210 qdf_spinlock_destroy(&peer->peer_lock); 211 qdf_mem_free(peer); 212 return NULL; 213 } 214 /* Attach peer to vdev peer table */ 215 if (wlan_objmgr_vdev_peer_attach(vdev, peer) != 216 QDF_STATUS_SUCCESS) { 217 obj_mgr_warn( 218 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) VDEV attach failure", 219 macaddr[0], macaddr[1], macaddr[2], 220 macaddr[3], macaddr[4], macaddr[5]); 221 /* if attach fails, detach from psoc table before free */ 222 wlan_objmgr_psoc_peer_detach(psoc, peer); 223 qdf_spinlock_destroy(&peer->peer_lock); 224 qdf_mem_free(peer); 225 return NULL; 226 } 227 wlan_peer_set_pdev_id(peer, wlan_objmgr_pdev_get_pdev_id( 228 wlan_vdev_get_pdev(vdev))); 229 /* Increment ref count for BSS peer, so that BSS peer deletes last*/ 230 if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP) 231 || (type == WLAN_PEER_P2P_CLI)) 232 wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev), 233 WLAN_OBJMGR_ID); 234 /* TODO init other parameters */ 235 /* Invoke registered create handlers */ 236 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 237 handler = g_umac_glb_obj->peer_create_handler[id]; 238 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 239 if (handler != NULL) 240 peer->obj_status[id] = handler(peer, arg); 241 else 242 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; 243 } 244 /* derive the object status */ 245 obj_status = wlan_objmgr_peer_object_status(peer); 246 /* If SUCCESS, Object is created */ 247 if (obj_status == QDF_STATUS_SUCCESS) { 248 peer->obj_state = WLAN_OBJ_STATE_CREATED; 249 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 250 stat_handler = g_umac_glb_obj->peer_status_handler[id]; 251 arg = g_umac_glb_obj->peer_status_handler_arg[id]; 252 if (stat_handler != NULL) 253 stat_handler(peer, arg, 254 QDF_STATUS_SUCCESS); 255 } 256 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 257 /* If any component operates in different context, update it 258 as partially created */ 259 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 260 } else if (obj_status == QDF_STATUS_E_FAILURE) { 261 /* Clean up the peer */ 262 obj_mgr_err( 263 "Peer(%02x:%02x:%02x:%02x:%02x:%02x) comp object alloc fail", 264 macaddr[0], macaddr[1], macaddr[2], 265 macaddr[3], macaddr[4], macaddr[5]); 266 wlan_objmgr_peer_obj_delete(peer); 267 return NULL; 268 } 269 270 obj_mgr_debug("Created peer " QDF_MAC_ADDR_STR, 271 QDF_MAC_ADDR_ARRAY(macaddr)); 272 273 return peer; 274 } 275 276 static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) 277 { 278 uint8_t id; 279 wlan_objmgr_peer_destroy_handler handler; 280 QDF_STATUS obj_status; 281 void *arg; 282 uint8_t *macaddr; 283 284 if (peer == NULL) { 285 obj_mgr_err("PEER is NULL"); 286 return QDF_STATUS_E_FAILURE; 287 } 288 wlan_objmgr_notify_destroy(peer, WLAN_PEER_OP); 289 290 macaddr = wlan_peer_get_macaddr(peer); 291 292 obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_STR, 293 QDF_MAC_ADDR_ARRAY(macaddr)); 294 295 if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 296 obj_mgr_err("PEER object del is not invoked obj_state:%d peer " 297 QDF_MAC_ADDR_STR, peer->obj_state, 298 QDF_MAC_ADDR_ARRAY(macaddr)); 299 WLAN_OBJMGR_BUG(0); 300 } 301 302 /* Invoke registered destroy handlers */ 303 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 304 handler = g_umac_glb_obj->peer_destroy_handler[id]; 305 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 306 if (handler != NULL) 307 peer->obj_status[id] = handler(peer, arg); 308 else 309 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; 310 } 311 /* Derive the object status */ 312 obj_status = wlan_objmgr_peer_object_status(peer); 313 if (obj_status == QDF_STATUS_E_FAILURE) { 314 /* If it status is failure, memory will not be freed */ 315 QDF_BUG(0); 316 return QDF_STATUS_E_FAILURE; 317 } 318 /* few components deletion is in progress */ 319 if (obj_status == QDF_STATUS_COMP_ASYNC) { 320 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 321 return QDF_STATUS_COMP_ASYNC; 322 } 323 324 /* Free the peer object */ 325 return wlan_objmgr_peer_obj_free(peer); 326 } 327 328 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) 329 { 330 uint8_t print_idx; 331 uint8_t *macaddr; 332 333 if (peer == NULL) { 334 obj_mgr_err("PEER is NULL"); 335 return QDF_STATUS_E_FAILURE; 336 } 337 338 wlan_peer_obj_lock(peer); 339 macaddr = wlan_peer_get_macaddr(peer); 340 wlan_peer_obj_unlock(peer); 341 342 obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_STR, 343 QDF_MAC_ADDR_ARRAY(macaddr)); 344 345 print_idx = qdf_get_pidx(); 346 wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG); 347 /** 348 * Update VDEV object state to LOGICALLY DELETED 349 * It prevents further access of this object 350 */ 351 wlan_peer_obj_lock(peer); 352 peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 353 wlan_peer_obj_unlock(peer); 354 wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP); 355 wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID); 356 357 return QDF_STATUS_SUCCESS; 358 } 359 qdf_export_symbol(wlan_objmgr_peer_obj_delete); 360 /** 361 ** APIs to attach/detach component objects 362 */ 363 QDF_STATUS wlan_objmgr_peer_component_obj_attach( 364 struct wlan_objmgr_peer *peer, 365 enum wlan_umac_comp_id id, 366 void *comp_priv_obj, 367 QDF_STATUS status) 368 { 369 wlan_objmgr_peer_status_handler s_hler; 370 void *arg; 371 uint8_t i; 372 QDF_STATUS obj_status; 373 374 /* component id is invalid */ 375 if (id >= WLAN_UMAC_MAX_COMPONENTS) 376 return QDF_STATUS_MAXCOMP_FAIL; 377 378 wlan_peer_obj_lock(peer); 379 /* If there is a valid entry, return failure, 380 valid object needs to be freed first */ 381 if (peer->peer_comp_priv_obj[id] != NULL) { 382 wlan_peer_obj_unlock(peer); 383 return QDF_STATUS_E_FAILURE; 384 } 385 /* Assign component object private pointer(can be NULL also), status */ 386 peer->peer_comp_priv_obj[id] = comp_priv_obj; 387 peer->obj_status[id] = status; 388 wlan_peer_obj_unlock(peer); 389 390 if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 391 return QDF_STATUS_SUCCESS; 392 393 /* If PEER object status is partially created means, this API is 394 invoked with differnt context. this block should be executed for async 395 components only */ 396 /* Derive status */ 397 obj_status = wlan_objmgr_peer_object_status(peer); 398 /* STATUS_SUCCESS means, object is CREATED */ 399 if (obj_status == QDF_STATUS_SUCCESS) 400 peer->obj_state = WLAN_OBJ_STATE_CREATED; 401 /* update state as CREATION failed, caller has to delete the 402 PEER object */ 403 else if (obj_status == QDF_STATUS_E_FAILURE) 404 peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 405 /* Notify components about the CREATION success/failure */ 406 if ((obj_status == QDF_STATUS_SUCCESS) || 407 (obj_status == QDF_STATUS_E_FAILURE)) { 408 /* nofity object status */ 409 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 410 s_hler = g_umac_glb_obj->peer_status_handler[i]; 411 arg = g_umac_glb_obj->peer_status_handler_arg[i]; 412 if (s_hler != NULL) 413 s_hler(peer, arg, obj_status); 414 } 415 } 416 return QDF_STATUS_SUCCESS; 417 } 418 419 QDF_STATUS wlan_objmgr_peer_component_obj_detach( 420 struct wlan_objmgr_peer *peer, 421 enum wlan_umac_comp_id id, 422 void *comp_priv_obj) 423 { 424 QDF_STATUS obj_status; 425 426 /* component id is invalid */ 427 if (id >= WLAN_UMAC_MAX_COMPONENTS) 428 return QDF_STATUS_MAXCOMP_FAIL; 429 430 wlan_peer_obj_lock(peer); 431 /* If there is a invalid entry, return failure */ 432 if (peer->peer_comp_priv_obj[id] != comp_priv_obj) { 433 peer->obj_status[id] = QDF_STATUS_E_FAILURE; 434 wlan_peer_obj_unlock(peer); 435 return QDF_STATUS_E_FAILURE; 436 } 437 /* Reset the pointer to NULL */ 438 peer->peer_comp_priv_obj[id] = NULL; 439 peer->obj_status[id] = QDF_STATUS_SUCCESS; 440 wlan_peer_obj_unlock(peer); 441 442 /* If PEER object status is partially destroyed means, this API is 443 invoked with differnt context, this block should be executed for async 444 components only */ 445 if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 446 (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 447 /* Derive object status */ 448 obj_status = wlan_objmgr_peer_object_status(peer); 449 if (obj_status == QDF_STATUS_SUCCESS) { 450 /*Update the status as Deleted, if full object 451 deletion is in progress */ 452 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 453 peer->obj_state = WLAN_OBJ_STATE_DELETED; 454 /* Move to creation state, since this component 455 deletion alone requested */ 456 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 457 peer->obj_state = WLAN_OBJ_STATE_CREATED; 458 /* Object status is failure */ 459 } else if (obj_status == QDF_STATUS_E_FAILURE) { 460 /*Update the status as Deletion failed, if full object 461 deletion is in progress */ 462 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 463 peer->obj_state = 464 WLAN_OBJ_STATE_DELETION_FAILED; 465 /* Move to creation state, since this component 466 deletion alone requested (do not block other 467 components) */ 468 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 469 peer->obj_state = WLAN_OBJ_STATE_CREATED; 470 } 471 472 /* Delete peer object */ 473 if ((obj_status == QDF_STATUS_SUCCESS) && 474 (peer->obj_state == WLAN_OBJ_STATE_DELETED)) { 475 /* Free the peer object */ 476 return wlan_objmgr_peer_obj_free(peer); 477 } 478 } 479 480 return QDF_STATUS_SUCCESS; 481 } 482 483 484 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation( 485 struct wlan_objmgr_peer *peer, 486 enum wlan_umac_comp_id id) 487 { 488 wlan_objmgr_peer_create_handler handler; 489 void *arg; 490 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 491 492 /* Component id is invalid */ 493 if (id >= WLAN_UMAC_MAX_COMPONENTS) 494 return QDF_STATUS_MAXCOMP_FAIL; 495 496 wlan_peer_obj_lock(peer); 497 /* If component object is already created, delete old 498 component object, then invoke creation */ 499 if (peer->peer_comp_priv_obj[id] != NULL) { 500 wlan_peer_obj_unlock(peer); 501 return QDF_STATUS_E_FAILURE; 502 } 503 wlan_peer_obj_unlock(peer); 504 505 /* Invoke registered create handlers */ 506 handler = g_umac_glb_obj->peer_create_handler[id]; 507 arg = g_umac_glb_obj->peer_create_handler_arg[id]; 508 if (handler != NULL) 509 peer->obj_status[id] = handler(peer, arg); 510 else 511 return QDF_STATUS_E_FAILURE; 512 513 /* If object status is created, then only handle this object status */ 514 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 515 /* Derive object status */ 516 obj_status = wlan_objmgr_peer_object_status(peer); 517 /* Move PDEV object state to Partially created state */ 518 if (obj_status == QDF_STATUS_COMP_ASYNC) { 519 /*TODO atomic */ 520 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 521 } 522 } 523 524 return obj_status; 525 } 526 527 528 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion( 529 struct wlan_objmgr_peer *peer, 530 enum wlan_umac_comp_id id) 531 { 532 wlan_objmgr_peer_destroy_handler handler; 533 void *arg; 534 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 535 536 /* component id is invalid */ 537 if (id >= WLAN_UMAC_MAX_COMPONENTS) 538 return QDF_STATUS_MAXCOMP_FAIL; 539 540 wlan_peer_obj_lock(peer); 541 /* Component object was never created, invalid operation */ 542 if (peer->peer_comp_priv_obj[id] == NULL) { 543 wlan_peer_obj_unlock(peer); 544 return QDF_STATUS_E_FAILURE; 545 } 546 547 wlan_peer_obj_unlock(peer); 548 549 /* Invoke registered destroy handlers */ 550 handler = g_umac_glb_obj->peer_destroy_handler[id]; 551 arg = g_umac_glb_obj->peer_destroy_handler_arg[id]; 552 if (handler != NULL) 553 peer->obj_status[id] = handler(peer, arg); 554 else 555 return QDF_STATUS_E_FAILURE; 556 557 /* If object status is created, then only handle this object status */ 558 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { 559 obj_status = wlan_objmgr_peer_object_status(peer); 560 /* move object state to DEL progress */ 561 if (obj_status == QDF_STATUS_COMP_ASYNC) 562 peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 563 } 564 return obj_status; 565 } 566 567 void *wlan_objmgr_peer_get_comp_private_obj( 568 struct wlan_objmgr_peer *peer, 569 enum wlan_umac_comp_id id) 570 { 571 void *comp_priv_obj; 572 573 /* component id is invalid */ 574 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 575 QDF_BUG(0); 576 return NULL; 577 } 578 579 if (peer == NULL) { 580 QDF_BUG(0); 581 return NULL; 582 } 583 584 comp_priv_obj = peer->peer_comp_priv_obj[id]; 585 return comp_priv_obj; 586 } 587 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj); 588 589 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 590 static inline void 591 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, 592 wlan_objmgr_ref_dbgid id) 593 { 594 qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]); 595 } 596 #else 597 static inline void 598 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, 599 wlan_objmgr_ref_dbgid id) {} 600 #endif 601 602 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, 603 wlan_objmgr_ref_dbgid id) 604 { 605 if (peer == NULL) { 606 obj_mgr_err("peer obj is NULL for %d", id); 607 QDF_ASSERT(0); 608 return; 609 } 610 /* Increment ref count */ 611 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); 612 wlan_objmgr_peer_get_debug_id_ref(peer, id); 613 614 return; 615 } 616 qdf_export_symbol(wlan_objmgr_peer_get_ref); 617 618 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, 619 wlan_objmgr_ref_dbgid id) 620 { 621 622 uint8_t *macaddr; 623 624 if (peer == NULL) { 625 obj_mgr_err("peer obj is NULL for %d", id); 626 QDF_ASSERT(0); 627 return QDF_STATUS_E_FAILURE; 628 } 629 630 wlan_peer_obj_lock(peer); 631 macaddr = wlan_peer_get_macaddr(peer); 632 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) { 633 wlan_peer_obj_unlock(peer); 634 if (peer->peer_objmgr.print_cnt++ <= 635 WLAN_OBJMGR_RATELIMIT_THRESH) 636 obj_mgr_warn( 637 "peer(" QDF_MAC_ADDR_STR ") not in Created st(%d)", 638 QDF_MAC_ADDR_ARRAY(macaddr), 639 peer->obj_state); 640 return QDF_STATUS_E_RESOURCES; 641 } 642 643 wlan_objmgr_peer_get_ref(peer, id); 644 wlan_peer_obj_unlock(peer); 645 646 return QDF_STATUS_SUCCESS; 647 } 648 qdf_export_symbol(wlan_objmgr_peer_try_get_ref); 649 650 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 651 static void 652 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, 653 wlan_objmgr_ref_dbgid id) 654 { 655 uint8_t *macaddr; 656 657 macaddr = wlan_peer_get_macaddr(peer); 658 if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) { 659 obj_mgr_err( 660 "peer(%02x:%02x:%02x:%02x:%02x:%02x) ref was not taken by %d", 661 macaddr[0], macaddr[1], macaddr[2], 662 macaddr[3], macaddr[4], macaddr[5], id); 663 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, 664 QDF_TRACE_LEVEL_FATAL); 665 WLAN_OBJMGR_BUG(0); 666 } 667 668 qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]); 669 } 670 #else 671 static inline void 672 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, 673 wlan_objmgr_ref_dbgid id) {} 674 #endif 675 676 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, 677 wlan_objmgr_ref_dbgid id) 678 { 679 uint8_t *macaddr; 680 681 if (!peer) { 682 obj_mgr_err("peer obj is NULL for %d", id); 683 QDF_ASSERT(0); 684 return; 685 } 686 687 macaddr = wlan_peer_get_macaddr(peer); 688 689 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { 690 obj_mgr_err("peer(%02x:%02x:%02x:%02x:%02x:%02x) ref cnt is 0", 691 macaddr[0], macaddr[1], macaddr[2], 692 macaddr[3], macaddr[4], macaddr[5]); 693 WLAN_OBJMGR_BUG(0); 694 return; 695 } 696 wlan_objmgr_peer_release_debug_id_ref(peer, id); 697 698 /* Provide synchronization from the access to add peer 699 * to logically deleted peer list. 700 */ 701 wlan_peer_obj_lock(peer); 702 /* Decrement ref count, free peer object, if ref count == 0 */ 703 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { 704 wlan_peer_obj_unlock(peer); 705 wlan_objmgr_peer_obj_destroy(peer); 706 } else { 707 wlan_peer_obj_unlock(peer); 708 } 709 710 return; 711 } 712 qdf_export_symbol(wlan_objmgr_peer_release_ref); 713 714 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head( 715 struct wlan_objmgr_vdev *vdev, 716 qdf_list_t *peer_list, 717 wlan_objmgr_ref_dbgid dbg_id) 718 { 719 struct wlan_objmgr_peer *peer; 720 qdf_list_node_t *vdev_node = NULL; 721 qdf_list_node_t *prev_vdev_node = NULL; 722 723 wlan_vdev_obj_lock(vdev); 724 725 if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) { 726 wlan_vdev_obj_unlock(vdev); 727 return NULL; 728 } 729 730 do { 731 peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 732 vdev_peer); 733 734 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 735 QDF_STATUS_SUCCESS) { 736 wlan_vdev_obj_unlock(vdev); 737 return peer; 738 } 739 740 prev_vdev_node = vdev_node; 741 } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 742 QDF_STATUS_SUCCESS); 743 744 wlan_vdev_obj_unlock(vdev); 745 746 return NULL; 747 } 748 749 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev( 750 struct wlan_objmgr_vdev *vdev, 751 qdf_list_t *peer_list, 752 struct wlan_objmgr_peer *peer, 753 wlan_objmgr_ref_dbgid dbg_id) 754 { 755 struct wlan_objmgr_peer *peer_next; 756 qdf_list_node_t *vdev_node = NULL; 757 qdf_list_node_t *prev_vdev_node = NULL; 758 759 if (peer == NULL) 760 return NULL; 761 762 wlan_vdev_obj_lock(vdev); 763 764 prev_vdev_node = &peer->vdev_peer; 765 while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == 766 QDF_STATUS_SUCCESS) { 767 peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer, 768 vdev_peer); 769 770 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == 771 QDF_STATUS_SUCCESS) { 772 wlan_vdev_obj_unlock(vdev); 773 return peer_next; 774 } 775 776 prev_vdev_node = vdev_node; 777 } 778 779 wlan_vdev_obj_unlock(vdev); 780 781 return NULL; 782 } 783 784 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( 785 struct wlan_peer_list *peer_list, 786 uint8_t hash_index, 787 struct wlan_objmgr_peer *peer, 788 wlan_objmgr_ref_dbgid dbg_id) 789 { 790 struct wlan_objmgr_peer *peer_next = NULL; 791 qdf_list_node_t *psoc_node = NULL; 792 qdf_list_node_t *prev_psoc_node = NULL; 793 qdf_list_t *obj_list; 794 795 qdf_spin_lock_bh(&peer_list->peer_list_lock); 796 obj_list = &peer_list->peer_hash[hash_index]; 797 798 prev_psoc_node = &peer->psoc_peer; 799 while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 800 QDF_STATUS_SUCCESS) { 801 peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 802 psoc_peer); 803 804 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == 805 QDF_STATUS_SUCCESS) { 806 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 807 return peer_next; 808 } 809 810 prev_psoc_node = psoc_node; 811 } 812 813 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 814 815 return NULL; 816 } 817 818 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( 819 struct wlan_peer_list *peer_list, 820 uint8_t hash_index, 821 wlan_objmgr_ref_dbgid dbg_id) 822 { 823 struct wlan_objmgr_peer *peer; 824 qdf_list_node_t *psoc_node = NULL; 825 qdf_list_node_t *prev_psoc_node = NULL; 826 qdf_list_t *obj_list; 827 828 qdf_spin_lock_bh(&peer_list->peer_list_lock); 829 obj_list = &peer_list->peer_hash[hash_index]; 830 831 if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) { 832 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 833 return NULL; 834 } 835 836 do { 837 peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, 838 psoc_peer); 839 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 840 QDF_STATUS_SUCCESS) { 841 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 842 return peer; 843 } 844 845 prev_psoc_node = psoc_node; 846 } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == 847 QDF_STATUS_SUCCESS); 848 849 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 850 return NULL; 851 } 852 853 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( 854 struct wlan_peer_list *peer_list, 855 uint8_t hash_index, 856 wlan_objmgr_ref_dbgid dbg_id) 857 { 858 struct wlan_objmgr_peer *peer; 859 qdf_list_t *obj_list; 860 861 qdf_spin_lock_bh(&peer_list->peer_list_lock); 862 obj_list = &peer_list->peer_hash[hash_index]; 863 864 peer = wlan_psoc_peer_list_peek_head(obj_list); 865 866 /** 867 * This API is invoked by caller, only when caller need to access the 868 * peer object, though object is not in active state, this API should be 869 * used carefully, where multiple object frees are not triggered 870 */ 871 if (peer) 872 wlan_objmgr_peer_get_ref(peer, dbg_id); 873 874 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 875 876 return peer; 877 } 878 879 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( 880 struct wlan_peer_list *peer_list, uint8_t hash_index, 881 struct wlan_objmgr_peer *peer, 882 wlan_objmgr_ref_dbgid dbg_id) 883 { 884 qdf_list_t *obj_list; 885 struct wlan_objmgr_peer *peer_next; 886 887 qdf_spin_lock_bh(&peer_list->peer_list_lock); 888 obj_list = &peer_list->peer_hash[hash_index]; 889 890 peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer); 891 /** 892 * This API is invoked by caller, only when caller need to access the 893 * peer object, though object is not in active state, this API should be 894 * used carefully, where multiple free on object are not triggered 895 */ 896 if (peer_next) 897 wlan_objmgr_peer_get_ref(peer_next, dbg_id); 898 899 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 900 901 return peer_next; 902 } 903 904 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 905 void 906 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer, 907 QDF_TRACE_LEVEL log_level) 908 { 909 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level); 910 } 911 912 uint32_t 913 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, 914 enum wlan_umac_comp_id id) 915 { 916 return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]); 917 } 918 #else 919 void 920 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer, 921 QDF_TRACE_LEVEL log_level) 922 { 923 uint32_t pending_ref; 924 925 pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt); 926 obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref); 927 } 928 929 uint32_t 930 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, 931 enum wlan_umac_comp_id id) 932 { 933 return 0; 934 } 935 #endif 936