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