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