1 /* 2 * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 /** 19 * DOC: Public APIs to perform operations on Global objects 20 */ 21 22 #include <wlan_objmgr_cmn.h> 23 #include <wlan_objmgr_global_obj.h> 24 #include <wlan_objmgr_psoc_obj.h> 25 #include <wlan_objmgr_pdev_obj.h> 26 #include <wlan_objmgr_vdev_obj.h> 27 #include <wlan_objmgr_peer_obj.h> 28 #include <qdf_mem.h> 29 #include <qdf_types.h> 30 #include <qdf_module.h> 31 #include "wlan_objmgr_global_obj_i.h" 32 #include "wlan_objmgr_psoc_obj_i.h" 33 #include "wlan_objmgr_pdev_obj_i.h" 34 #include "wlan_objmgr_vdev_obj_i.h" 35 36 /** 37 ** APIs to Create/Delete Global object APIs 38 */ 39 static QDF_STATUS wlan_objmgr_psoc_object_status( 40 struct wlan_objmgr_psoc *psoc) 41 { 42 uint8_t id; 43 QDF_STATUS status = QDF_STATUS_SUCCESS; 44 45 wlan_psoc_obj_lock(psoc); 46 /* Iterate through all components to derive the object status */ 47 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 48 /* If component disabled, Ignore */ 49 if (psoc->obj_status[id] == QDF_STATUS_COMP_DISABLED) 50 continue; 51 /* If component operates in Async, status is Partially created, 52 * break 53 */ 54 else if (psoc->obj_status[id] == QDF_STATUS_COMP_ASYNC) { 55 if (!psoc->soc_comp_priv_obj[id]) { 56 status = QDF_STATUS_COMP_ASYNC; 57 break; 58 } 59 /* 60 * If component failed to allocate its object, treat it as 61 * failure, complete object need to be cleaned up 62 */ 63 } else if ((psoc->obj_status[id] == QDF_STATUS_E_NOMEM) || 64 (psoc->obj_status[id] == QDF_STATUS_E_FAILURE)) { 65 status = QDF_STATUS_E_FAILURE; 66 break; 67 } 68 } 69 wlan_psoc_obj_unlock(psoc); 70 71 return status; 72 } 73 74 static void wlan_objmgr_psoc_peer_list_init(struct wlan_peer_list *peer_list) 75 { 76 uint8_t i; 77 78 qdf_spinlock_create(&peer_list->peer_list_lock); 79 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) 80 qdf_list_create(&peer_list->peer_hash[i], 81 WLAN_UMAC_PSOC_MAX_PEERS + 82 WLAN_MAX_PSOC_TEMP_PEERS); 83 } 84 85 static void wlan_objmgr_psoc_peer_list_deinit(struct wlan_peer_list *peer_list) 86 { 87 uint8_t i; 88 89 /* deinit the lock */ 90 qdf_spinlock_destroy(&peer_list->peer_list_lock); 91 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) 92 qdf_list_destroy(&peer_list->peer_hash[i]); 93 } 94 95 static QDF_STATUS wlan_objmgr_psoc_obj_free(struct wlan_objmgr_psoc *psoc) 96 { 97 /* Detach PSOC from global object's psoc list */ 98 if (wlan_objmgr_psoc_object_detach(psoc) == QDF_STATUS_E_FAILURE) { 99 obj_mgr_err("PSOC object detach failed"); 100 return QDF_STATUS_E_FAILURE; 101 } 102 wlan_objmgr_psoc_peer_list_deinit(&psoc->soc_objmgr.peer_list); 103 104 qdf_spinlock_destroy(&psoc->psoc_lock); 105 qdf_mem_free(psoc); 106 107 return QDF_STATUS_SUCCESS; 108 } 109 110 struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, 111 WLAN_DEV_TYPE dev_type) 112 { 113 uint8_t id; 114 struct wlan_objmgr_psoc *psoc = NULL; 115 wlan_objmgr_psoc_create_handler handler; 116 wlan_objmgr_psoc_status_handler stat_handler; 117 struct wlan_objmgr_psoc_objmgr *objmgr; 118 QDF_STATUS obj_status; 119 void *arg; 120 121 psoc = qdf_mem_malloc(sizeof(*psoc)); 122 if (!psoc) 123 return NULL; 124 125 psoc->obj_state = WLAN_OBJ_STATE_ALLOCATED; 126 qdf_spinlock_create(&psoc->psoc_lock); 127 /* Initialize with default values */ 128 objmgr = &psoc->soc_objmgr; 129 objmgr->wlan_pdev_count = 0; 130 objmgr->wlan_vdev_count = 0; 131 objmgr->max_vdev_count = WLAN_UMAC_PSOC_MAX_VDEVS; 132 objmgr->wlan_peer_count = 0; 133 objmgr->temp_peer_count = 0; 134 objmgr->max_peer_count = WLAN_UMAC_PSOC_MAX_PEERS; 135 qdf_atomic_init(&objmgr->ref_cnt); 136 objmgr->print_cnt = 0; 137 /* set phy version, dev_type in psoc */ 138 wlan_psoc_set_nif_phy_version(psoc, phy_version); 139 wlan_psoc_set_dev_type(psoc, dev_type); 140 /* Initialize peer list */ 141 wlan_objmgr_psoc_peer_list_init(&objmgr->peer_list); 142 wlan_objmgr_psoc_get_ref(psoc, WLAN_OBJMGR_ID); 143 /* Invoke registered create handlers */ 144 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 145 handler = g_umac_glb_obj->psoc_create_handler[id]; 146 arg = g_umac_glb_obj->psoc_create_handler_arg[id]; 147 if (handler) 148 psoc->obj_status[id] = handler(psoc, arg); 149 else 150 psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED; 151 } 152 /* Derive object status */ 153 obj_status = wlan_objmgr_psoc_object_status(psoc); 154 155 if (obj_status == QDF_STATUS_SUCCESS) { 156 /* Object status is SUCCESS, Object is created */ 157 psoc->obj_state = WLAN_OBJ_STATE_CREATED; 158 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 159 stat_handler = g_umac_glb_obj->psoc_status_handler[id]; 160 arg = g_umac_glb_obj->psoc_status_handler_arg[id]; 161 if (stat_handler) 162 stat_handler(psoc, arg, 163 QDF_STATUS_SUCCESS); 164 } 165 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 166 /* 167 * Few components operates in Asynchrous communction 168 * Object state partially created 169 */ 170 psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 171 } else if (obj_status == QDF_STATUS_E_FAILURE) { 172 /* Component object failed to be created, clean up the object */ 173 obj_mgr_err("PSOC component objects allocation failed"); 174 /* Clean up the psoc */ 175 wlan_objmgr_psoc_obj_delete(psoc); 176 return NULL; 177 } 178 179 if (wlan_objmgr_psoc_object_attach(psoc) != 180 QDF_STATUS_SUCCESS) { 181 obj_mgr_err("PSOC object attach failed"); 182 wlan_objmgr_psoc_obj_delete(psoc); 183 return NULL; 184 } 185 186 obj_mgr_info("Created psoc %d", psoc->soc_objmgr.psoc_id); 187 188 return psoc; 189 } 190 qdf_export_symbol(wlan_objmgr_psoc_obj_create); 191 192 static QDF_STATUS wlan_objmgr_psoc_obj_destroy(struct wlan_objmgr_psoc *psoc) 193 { 194 uint8_t id; 195 wlan_objmgr_psoc_destroy_handler handler; 196 QDF_STATUS obj_status; 197 void *arg; 198 199 if (!psoc) { 200 obj_mgr_err("psoc is NULL"); 201 return QDF_STATUS_E_FAILURE; 202 } 203 wlan_objmgr_notify_destroy(psoc, WLAN_PSOC_OP); 204 205 obj_mgr_info("Physically deleting psoc %d", psoc->soc_objmgr.psoc_id); 206 207 if (psoc->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { 208 obj_mgr_err("PSOC object delete is not invoked obj_state:%d", 209 psoc->obj_state); 210 WLAN_OBJMGR_BUG(0); 211 } 212 213 /* Invoke registered create handlers */ 214 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 215 handler = g_umac_glb_obj->psoc_destroy_handler[id]; 216 arg = g_umac_glb_obj->psoc_destroy_handler_arg[id]; 217 if (handler && 218 (psoc->obj_status[id] == QDF_STATUS_SUCCESS || 219 psoc->obj_status[id] == QDF_STATUS_COMP_ASYNC)) 220 psoc->obj_status[id] = handler(psoc, arg); 221 else 222 psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED; 223 } 224 /* Derive object status */ 225 obj_status = wlan_objmgr_psoc_object_status(psoc); 226 227 if (obj_status == QDF_STATUS_E_FAILURE) { 228 obj_mgr_err("PSOC component object free failed"); 229 /* Ideally should not happen 230 * This leads to memleak, BUG_ON to find which component 231 * delete notification failed and fix it. 232 */ 233 QDF_BUG(0); 234 return QDF_STATUS_E_FAILURE; 235 } 236 /* Deletion is in progress */ 237 if (obj_status == QDF_STATUS_COMP_ASYNC) { 238 psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 239 return QDF_STATUS_COMP_ASYNC; 240 } 241 242 /* Free psoc object */ 243 return wlan_objmgr_psoc_obj_free(psoc); 244 } 245 246 247 QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc) 248 { 249 uint8_t print_idx; 250 251 if (!psoc) { 252 obj_mgr_err("psoc is NULL"); 253 return QDF_STATUS_E_FAILURE; 254 } 255 256 obj_mgr_info("Logically deleting psoc %d", psoc->soc_objmgr.psoc_id); 257 258 print_idx = qdf_get_pidx(); 259 wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg, 260 QDF_TRACE_LEVEL_DEBUG); 261 /* 262 * Update PSOC object state to LOGICALLY DELETED 263 * It prevents further access of this object 264 */ 265 wlan_psoc_obj_lock(psoc); 266 psoc->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED; 267 wlan_psoc_obj_unlock(psoc); 268 wlan_objmgr_notify_log_delete(psoc, WLAN_PSOC_OP); 269 wlan_objmgr_psoc_release_ref(psoc, WLAN_OBJMGR_ID); 270 271 return QDF_STATUS_SUCCESS; 272 } 273 qdf_export_symbol(wlan_objmgr_psoc_obj_delete); 274 275 QDF_STATUS wlan_objmgr_psoc_component_obj_attach( 276 struct wlan_objmgr_psoc *psoc, 277 enum wlan_umac_comp_id id, 278 void *comp_priv_obj, 279 QDF_STATUS status) 280 { 281 wlan_objmgr_psoc_status_handler stat_handler; 282 void *arg = NULL; 283 QDF_STATUS obj_status; 284 uint8_t i; 285 286 /* component id is invalid */ 287 if (id >= WLAN_UMAC_MAX_COMPONENTS) 288 return QDF_STATUS_MAXCOMP_FAIL; 289 290 wlan_psoc_obj_lock(psoc); 291 /* If there is a valid entry, return failure */ 292 if (psoc->soc_comp_priv_obj[id]) { 293 wlan_psoc_obj_unlock(psoc); 294 return QDF_STATUS_E_FAILURE; 295 } 296 /* Save component's pointer and status */ 297 psoc->soc_comp_priv_obj[id] = comp_priv_obj; 298 psoc->obj_status[id] = status; 299 300 wlan_psoc_obj_unlock(psoc); 301 302 if (psoc->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 303 return QDF_STATUS_SUCCESS; 304 /* If PSOC object status is partially created means, this API is 305 * invoked with differnt context, this block should be executed for 306 * async components only 307 */ 308 /* Derive status */ 309 obj_status = wlan_objmgr_psoc_object_status(psoc); 310 /* STATUS_SUCCESS means, object is CREATED */ 311 if (obj_status == QDF_STATUS_SUCCESS) 312 psoc->obj_state = WLAN_OBJ_STATE_CREATED; 313 /* update state as CREATION failed, caller has to delete the 314 * PSOC object 315 */ 316 else if (obj_status == QDF_STATUS_E_FAILURE) 317 psoc->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 318 319 /* Notify components about the CREATION success/failure */ 320 if ((obj_status == QDF_STATUS_SUCCESS) || 321 (obj_status == QDF_STATUS_E_FAILURE)) { 322 /* nofity object status */ 323 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 324 stat_handler = g_umac_glb_obj->psoc_status_handler[i]; 325 arg = g_umac_glb_obj->psoc_status_handler_arg[i]; 326 if (stat_handler) 327 stat_handler(psoc, arg, obj_status); 328 } 329 } 330 331 return QDF_STATUS_SUCCESS; 332 } 333 qdf_export_symbol(wlan_objmgr_psoc_component_obj_attach); 334 335 QDF_STATUS wlan_objmgr_psoc_component_obj_detach( 336 struct wlan_objmgr_psoc *psoc, 337 enum wlan_umac_comp_id id, 338 void *comp_priv_obj) 339 { 340 QDF_STATUS obj_status; 341 342 /* component id is invalid */ 343 if (id >= WLAN_UMAC_MAX_COMPONENTS) 344 return QDF_STATUS_MAXCOMP_FAIL; 345 346 wlan_psoc_obj_lock(psoc); 347 /* If there is a valid entry, return failure */ 348 if (psoc->soc_comp_priv_obj[id] != comp_priv_obj) { 349 psoc->obj_status[id] = QDF_STATUS_E_FAILURE; 350 wlan_psoc_obj_unlock(psoc); 351 return QDF_STATUS_E_FAILURE; 352 } 353 /* Reset pointers to NULL, update the status*/ 354 psoc->soc_comp_priv_obj[id] = NULL; 355 psoc->obj_status[id] = QDF_STATUS_SUCCESS; 356 wlan_psoc_obj_unlock(psoc); 357 358 /* If PSOC object status is partially created means, this API is 359 * invoked with differnt context, this block should be executed for 360 * async components only 361 */ 362 if ((psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 363 (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 364 /* Derive object status */ 365 obj_status = wlan_objmgr_psoc_object_status(psoc); 366 if (obj_status == QDF_STATUS_SUCCESS) { 367 /* Update the status as Deleted, if full object 368 * deletion is in progress 369 */ 370 if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 371 psoc->obj_state = WLAN_OBJ_STATE_DELETED; 372 373 /* Move to creation state, since this component 374 * deletion alone requested 375 */ 376 if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 377 psoc->obj_state = WLAN_OBJ_STATE_CREATED; 378 /* Object status is failure */ 379 } else if (obj_status == QDF_STATUS_E_FAILURE) { 380 /* Update the status as Deletion failed, if full object 381 * deletion is in progress 382 */ 383 if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 384 psoc->obj_state = 385 WLAN_OBJ_STATE_DELETION_FAILED; 386 387 /* Move to creation state, since this component 388 * deletion alone requested (do not block other 389 * components) 390 */ 391 if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 392 psoc->obj_state = WLAN_OBJ_STATE_CREATED; 393 } 394 395 /* Delete psoc object */ 396 if ((obj_status == QDF_STATUS_SUCCESS) && 397 (psoc->obj_state == WLAN_OBJ_STATE_DELETED)) { 398 /* Free psoc object */ 399 return wlan_objmgr_psoc_obj_free(psoc); 400 } 401 } 402 403 return QDF_STATUS_SUCCESS; 404 } 405 qdf_export_symbol(wlan_objmgr_psoc_component_obj_detach); 406 407 QDF_STATUS wlan_objmgr_iterate_obj_list( 408 struct wlan_objmgr_psoc *psoc, 409 enum wlan_objmgr_obj_type obj_type, 410 wlan_objmgr_op_handler handler, 411 void *arg, uint8_t lock_free_op, 412 wlan_objmgr_ref_dbgid dbg_id) 413 { 414 uint16_t obj_id; 415 uint8_t i; 416 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 417 struct wlan_peer_list *peer_list; 418 struct wlan_objmgr_pdev *pdev; 419 struct wlan_objmgr_vdev *vdev; 420 struct wlan_objmgr_peer *peer; 421 struct wlan_objmgr_peer *peer_next; 422 uint16_t max_vdev_cnt; 423 424 switch (obj_type) { 425 case WLAN_PDEV_OP: 426 /* Iterate through PDEV list, invoke handler for each pdev */ 427 for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) { 428 pdev = wlan_objmgr_get_pdev_by_id(psoc, obj_id, dbg_id); 429 if (pdev) { 430 handler(psoc, (void *)pdev, arg); 431 wlan_objmgr_pdev_release_ref(pdev, dbg_id); 432 } 433 } 434 break; 435 case WLAN_VDEV_OP: 436 /* Iterate through VDEV list, invoke handler for each vdev */ 437 max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc); 438 for (obj_id = 0; obj_id < max_vdev_cnt; obj_id++) { 439 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 440 obj_id, dbg_id); 441 if (vdev) { 442 handler(psoc, vdev, arg); 443 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 444 } 445 } 446 break; 447 case WLAN_PEER_OP: 448 /* Iterate through PEER list, invoke handler for each peer */ 449 peer_list = &objmgr->peer_list; 450 /* Since peer list has sublist, iterate through sublists */ 451 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) { 452 peer = wlan_psoc_peer_list_peek_active_head(peer_list, 453 i, dbg_id); 454 while (peer) { 455 handler(psoc, (void *)peer, arg); 456 /* Get next peer */ 457 peer_next = 458 wlan_peer_get_next_active_peer_of_psoc( 459 peer_list, i, peer, dbg_id); 460 wlan_objmgr_peer_release_ref(peer, dbg_id); 461 peer = peer_next; 462 } 463 } 464 break; 465 default: 466 break; 467 } 468 469 return QDF_STATUS_SUCCESS; 470 } 471 qdf_export_symbol(wlan_objmgr_iterate_obj_list); 472 473 QDF_STATUS wlan_objmgr_iterate_obj_list_all( 474 struct wlan_objmgr_psoc *psoc, 475 enum wlan_objmgr_obj_type obj_type, 476 wlan_objmgr_op_handler handler, 477 void *arg, uint8_t lock_free_op, 478 wlan_objmgr_ref_dbgid dbg_id) 479 { 480 uint16_t obj_id; 481 uint8_t i; 482 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 483 struct wlan_peer_list *peer_list; 484 struct wlan_objmgr_pdev *pdev; 485 struct wlan_objmgr_vdev *vdev; 486 struct wlan_objmgr_peer *peer; 487 struct wlan_objmgr_peer *peer_next; 488 uint16_t max_vdev_cnt; 489 490 /* If caller requests for lock free opeation, do not acquire, 491 * handler will handle the synchronization 492 */ 493 494 switch (obj_type) { 495 case WLAN_PDEV_OP: 496 /* Iterate through PDEV list, invoke handler for each pdev */ 497 for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) { 498 pdev = wlan_objmgr_get_pdev_by_id_no_state(psoc, 499 obj_id, dbg_id); 500 if (pdev) { 501 handler(psoc, (void *)pdev, arg); 502 wlan_objmgr_pdev_release_ref(pdev, dbg_id); 503 } 504 } 505 break; 506 case WLAN_VDEV_OP: 507 /* Iterate through VDEV list, invoke handler for each vdev */ 508 max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc); 509 for (obj_id = 0; obj_id < max_vdev_cnt; obj_id++) { 510 vdev = wlan_objmgr_get_vdev_by_id_from_psoc_no_state( 511 psoc, obj_id, dbg_id); 512 if (vdev) { 513 handler(psoc, vdev, arg); 514 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 515 } 516 } 517 break; 518 case WLAN_PEER_OP: 519 /* Iterate through PEER list, invoke handler for each peer */ 520 peer_list = &objmgr->peer_list; 521 /* Since peer list has sublist, iterate through sublists */ 522 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) { 523 peer = wlan_psoc_peer_list_peek_head_ref(peer_list, i, 524 dbg_id); 525 526 while (peer) { 527 handler(psoc, (void *)peer, arg); 528 /* Get next peer */ 529 peer_next = wlan_peer_get_next_peer_of_psoc_ref( 530 peer_list, i, 531 peer, dbg_id); 532 wlan_objmgr_peer_release_ref(peer, dbg_id); 533 peer = peer_next; 534 } 535 } 536 break; 537 default: 538 break; 539 } 540 541 return QDF_STATUS_SUCCESS; 542 } 543 qdf_export_symbol(wlan_objmgr_iterate_obj_list_all); 544 545 /** 546 * wlan_objmgr_iterate_obj_list_all_noref() - iterate through all psoc objects 547 * without taking ref 548 * @psoc: PSOC object 549 * @obj_type: PDEV_OP/VDEV_OP/PEER_OP 550 * @handler: the handler will be called for each object of requested type 551 * the handler should be implemented to perform required operation 552 * @arg: agruments passed by caller 553 * 554 * API to be used for performing the operations on all PDEV/VDEV/PEER objects 555 * of psoc with lock protected 556 * 557 * Return: SUCCESS/FAILURE 558 */ 559 static QDF_STATUS wlan_objmgr_iterate_obj_list_all_noref( 560 struct wlan_objmgr_psoc *psoc, 561 enum wlan_objmgr_obj_type obj_type, 562 wlan_objmgr_op_handler handler, 563 void *arg) 564 { 565 uint16_t obj_id; 566 uint8_t i; 567 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 568 struct wlan_peer_list *peer_list; 569 qdf_list_t *obj_list; 570 struct wlan_objmgr_pdev *pdev; 571 struct wlan_objmgr_vdev *vdev; 572 struct wlan_objmgr_peer *peer; 573 struct wlan_objmgr_peer *peer_next; 574 uint16_t max_vdev_cnt; 575 576 /* If caller requests for lock free opeation, do not acquire, 577 * handler will handle the synchronization 578 */ 579 wlan_psoc_obj_lock(psoc); 580 581 switch (obj_type) { 582 case WLAN_PDEV_OP: 583 /* Iterate through PDEV list, invoke handler for each pdev */ 584 for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) { 585 pdev = objmgr->wlan_pdev_list[obj_id]; 586 if (pdev) 587 handler(psoc, (void *)pdev, arg); 588 } 589 break; 590 case WLAN_VDEV_OP: 591 /* Iterate through VDEV list, invoke handler for each vdev */ 592 max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc); 593 for (obj_id = 0; obj_id < max_vdev_cnt; obj_id++) { 594 vdev = objmgr->wlan_vdev_list[obj_id]; 595 if (vdev) 596 handler(psoc, vdev, arg); 597 } 598 break; 599 case WLAN_PEER_OP: 600 /* Iterate through PEER list, invoke handler for each peer */ 601 peer_list = &objmgr->peer_list; 602 /* psoc lock should be taken before list lock */ 603 qdf_spin_lock_bh(&peer_list->peer_list_lock); 604 /* Since peer list has sublist, iterate through sublists */ 605 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) { 606 obj_list = &peer_list->peer_hash[i]; 607 peer = wlan_psoc_peer_list_peek_head(obj_list); 608 while (peer) { 609 /* Get next peer */ 610 peer_next = wlan_peer_get_next_peer_of_psoc( 611 obj_list, peer); 612 handler(psoc, (void *)peer, arg); 613 peer = peer_next; 614 } 615 } 616 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 617 break; 618 default: 619 break; 620 } 621 wlan_psoc_obj_unlock(psoc); 622 623 return QDF_STATUS_SUCCESS; 624 } 625 626 static void wlan_objmgr_psoc_peer_delete(struct wlan_objmgr_psoc *psoc, 627 void *obj, void *args) 628 { 629 struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj; 630 631 wlan_objmgr_peer_obj_delete(peer); 632 } 633 634 static void wlan_objmgr_psoc_vdev_delete(struct wlan_objmgr_psoc *psoc, 635 void *obj, void *args) 636 { 637 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj; 638 639 wlan_objmgr_vdev_obj_delete(vdev); 640 } 641 642 static void wlan_objmgr_psoc_pdev_delete(struct wlan_objmgr_psoc *psoc, 643 void *obj, void *args) 644 { 645 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; 646 647 wlan_objmgr_pdev_obj_delete(pdev); 648 } 649 650 QDF_STATUS wlan_objmgr_free_all_objects_per_psoc( 651 struct wlan_objmgr_psoc *psoc) 652 { 653 /* Free all peers */ 654 wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP, 655 wlan_objmgr_psoc_peer_delete, NULL, 1, 656 WLAN_OBJMGR_ID); 657 /* Free all vdevs */ 658 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 659 wlan_objmgr_psoc_vdev_delete, NULL, 1, 660 WLAN_OBJMGR_ID); 661 /* Free all PDEVs */ 662 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 663 wlan_objmgr_psoc_pdev_delete, NULL, 1, 664 WLAN_OBJMGR_ID); 665 666 return QDF_STATUS_SUCCESS; 667 } 668 669 QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_creation( 670 struct wlan_objmgr_psoc *psoc, 671 enum wlan_umac_comp_id id) 672 { 673 wlan_objmgr_psoc_create_handler handler; 674 void *arg; 675 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 676 677 /* Component id is invalid */ 678 if (id >= WLAN_UMAC_MAX_COMPONENTS) 679 return QDF_STATUS_MAXCOMP_FAIL; 680 681 wlan_psoc_obj_lock(psoc); 682 /* If component object is already created, delete old 683 * component object, then invoke creation 684 */ 685 if (psoc->soc_comp_priv_obj[id]) { 686 wlan_psoc_obj_unlock(psoc); 687 return QDF_STATUS_E_FAILURE; 688 } 689 wlan_psoc_obj_unlock(psoc); 690 /* Invoke registered create handlers */ 691 handler = g_umac_glb_obj->psoc_create_handler[id]; 692 arg = g_umac_glb_obj->psoc_create_handler_arg[id]; 693 if (handler) 694 psoc->obj_status[id] = handler(psoc, arg); 695 else 696 return QDF_STATUS_E_FAILURE; 697 698 /* If object status is created, then only handle this object status */ 699 if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) { 700 /* Derive object status */ 701 obj_status = wlan_objmgr_psoc_object_status(psoc); 702 /* Move PSOC object state to Partially created state */ 703 if (obj_status == QDF_STATUS_COMP_ASYNC) { 704 /*TODO atomic */ 705 psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 706 } 707 } 708 709 return obj_status; 710 } 711 712 QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion( 713 struct wlan_objmgr_psoc *psoc, 714 enum wlan_umac_comp_id id) 715 { 716 wlan_objmgr_psoc_destroy_handler handler; 717 void *arg; 718 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 719 720 /* component id is invalid */ 721 if (id >= WLAN_UMAC_MAX_COMPONENTS) 722 return QDF_STATUS_MAXCOMP_FAIL; 723 724 wlan_psoc_obj_lock(psoc); 725 /* Component object was never created, invalid operation */ 726 if (!psoc->soc_comp_priv_obj[id]) { 727 wlan_psoc_obj_unlock(psoc); 728 return QDF_STATUS_E_FAILURE; 729 } 730 wlan_psoc_obj_unlock(psoc); 731 /* Invoke registered create handlers */ 732 handler = g_umac_glb_obj->psoc_destroy_handler[id]; 733 arg = g_umac_glb_obj->psoc_destroy_handler_arg[id]; 734 if (handler) 735 psoc->obj_status[id] = handler(psoc, arg); 736 else 737 return QDF_STATUS_E_FAILURE; 738 739 /* If object status is created, then only handle this object status */ 740 if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) { 741 obj_status = wlan_objmgr_psoc_object_status(psoc); 742 /* move object state to DEL progress */ 743 if (obj_status == QDF_STATUS_COMP_ASYNC) 744 psoc->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 745 } 746 747 return obj_status; 748 } 749 750 /* Util APIs */ 751 752 QDF_STATUS wlan_objmgr_psoc_pdev_attach(struct wlan_objmgr_psoc *psoc, 753 struct wlan_objmgr_pdev *pdev) 754 { 755 struct wlan_objmgr_psoc_objmgr *objmgr; 756 uint8_t id = 0; 757 QDF_STATUS status; 758 759 wlan_psoc_obj_lock(psoc); 760 objmgr = &psoc->soc_objmgr; 761 /* 762 * Derive pdev id from pdev map 763 * First free pdev id is assigned 764 */ 765 while ((id < WLAN_UMAC_MAX_PDEVS) && 766 (objmgr->wlan_pdev_id_map & (1<<id))) 767 id++; 768 769 if (id == WLAN_UMAC_MAX_PDEVS) { 770 status = QDF_STATUS_E_FAILURE; 771 } else { 772 /* Update the map for reserving the id */ 773 objmgr->wlan_pdev_id_map |= (1<<id); 774 /* store pdev in pdev list */ 775 objmgr->wlan_pdev_list[id] = pdev; 776 /* Increment pdev count */ 777 objmgr->wlan_pdev_count++; 778 /* save pdev id */ 779 pdev->pdev_objmgr.wlan_pdev_id = id; 780 status = QDF_STATUS_SUCCESS; 781 /* Inrement psoc ref count to block its free before pdev */ 782 wlan_objmgr_psoc_get_ref(psoc, WLAN_OBJMGR_ID); 783 } 784 wlan_psoc_obj_unlock(psoc); 785 786 return status; 787 } 788 789 QDF_STATUS wlan_objmgr_psoc_pdev_detach(struct wlan_objmgr_psoc *psoc, 790 struct wlan_objmgr_pdev *pdev) 791 { 792 struct wlan_objmgr_psoc_objmgr *objmgr; 793 uint8_t id; 794 795 id = pdev->pdev_objmgr.wlan_pdev_id; 796 /* If id is invalid, return */ 797 if (id >= WLAN_UMAC_MAX_PDEVS) 798 return QDF_STATUS_E_FAILURE; 799 800 wlan_psoc_obj_lock(psoc); 801 objmgr = &psoc->soc_objmgr; 802 /* Free pdev id slot */ 803 objmgr->wlan_pdev_id_map &= ~(1<<id); 804 objmgr->wlan_pdev_list[id] = NULL; 805 objmgr->wlan_pdev_count--; 806 pdev->pdev_objmgr.wlan_pdev_id = 0xff; 807 wlan_psoc_obj_unlock(psoc); 808 /* Release ref count of psoc */ 809 wlan_objmgr_psoc_release_ref(psoc, WLAN_OBJMGR_ID); 810 811 return QDF_STATUS_SUCCESS; 812 } 813 814 struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id( 815 struct wlan_objmgr_psoc *psoc, uint8_t id, 816 wlan_objmgr_ref_dbgid dbg_id) 817 { 818 struct wlan_objmgr_psoc_objmgr *objmgr; 819 struct wlan_objmgr_pdev *pdev = NULL; 820 821 /* If id is invalid, return */ 822 if (id >= WLAN_UMAC_MAX_PDEVS) 823 return NULL; 824 825 wlan_psoc_obj_lock(psoc); 826 objmgr = &psoc->soc_objmgr; 827 /* get pdev from pdev list */ 828 pdev = objmgr->wlan_pdev_list[id]; 829 /* Do not return object, if it is not CREATED state */ 830 if (pdev) { 831 if (wlan_objmgr_pdev_try_get_ref(pdev, dbg_id) != 832 QDF_STATUS_SUCCESS) 833 pdev = NULL; 834 } 835 836 wlan_psoc_obj_unlock(psoc); 837 838 return pdev; 839 } 840 qdf_export_symbol(wlan_objmgr_get_pdev_by_id); 841 842 struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id_no_state( 843 struct wlan_objmgr_psoc *psoc, uint8_t id, 844 wlan_objmgr_ref_dbgid dbg_id) 845 { 846 struct wlan_objmgr_psoc_objmgr *objmgr; 847 struct wlan_objmgr_pdev *pdev = NULL; 848 849 /* If id is invalid, return */ 850 if (id >= WLAN_UMAC_MAX_PDEVS) 851 return NULL; 852 853 wlan_psoc_obj_lock(psoc); 854 objmgr = &psoc->soc_objmgr; 855 /* get pdev from pdev list */ 856 pdev = objmgr->wlan_pdev_list[id]; 857 /* Do not return object, if it is not CREATED state */ 858 if (pdev) 859 wlan_objmgr_pdev_get_ref(pdev, dbg_id); 860 861 wlan_psoc_obj_unlock(psoc); 862 863 return pdev; 864 } 865 QDF_STATUS wlan_objmgr_psoc_vdev_attach(struct wlan_objmgr_psoc *psoc, 866 struct wlan_objmgr_vdev *vdev) 867 { 868 struct wlan_objmgr_psoc_objmgr *objmgr; 869 uint8_t id = 0; 870 uint8_t map_index = 0; 871 uint8_t map_entry_size = 32; 872 uint8_t adjust_ix = 0; 873 QDF_STATUS status; 874 875 wlan_psoc_obj_lock(psoc); 876 objmgr = &psoc->soc_objmgr; 877 /* Find first free vdev id */ 878 while ((id < objmgr->max_vdev_count) && 879 (objmgr->wlan_vdev_id_map[map_index] & (1<<(id - adjust_ix)))) { 880 id++; 881 /* 882 * The map is two DWORDS(32 bits), so, map_index 883 * adjust_ix derived based on the id value 884 */ 885 if (id == ((map_index + 1) * map_entry_size)) { 886 map_index++; 887 adjust_ix = map_index * map_entry_size; 888 } 889 } 890 /* If no free slot, return failure */ 891 if (id == objmgr->max_vdev_count) { 892 status = QDF_STATUS_E_FAILURE; 893 } else { 894 /* set free vdev id index */ 895 objmgr->wlan_vdev_id_map[map_index] |= (1<<(id-adjust_ix)); 896 /* store vdev pointer in vdev list */ 897 objmgr->wlan_vdev_list[id] = vdev; 898 /* increment vdev counter */ 899 objmgr->wlan_vdev_count++; 900 /* save vdev id */ 901 vdev->vdev_objmgr.vdev_id = id; 902 status = QDF_STATUS_SUCCESS; 903 } 904 wlan_psoc_obj_unlock(psoc); 905 906 return status; 907 } 908 909 QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc, 910 struct wlan_objmgr_vdev *vdev) 911 { 912 struct wlan_objmgr_psoc_objmgr *objmgr; 913 uint8_t id = 0; 914 uint8_t map_index = 0; 915 uint8_t map_entry_size = 32; 916 uint8_t adjust_ix = 0; 917 918 id = vdev->vdev_objmgr.vdev_id; 919 /* Invalid vdev id */ 920 if (id >= wlan_psoc_get_max_vdev_count(psoc)) 921 return QDF_STATUS_E_FAILURE; 922 /* 923 * Derive map_index and adjust_ix to find actual DWORD 924 * the id map is present 925 */ 926 while ((id - adjust_ix) >= map_entry_size) { 927 map_index++; 928 adjust_ix = map_index * map_entry_size; 929 } 930 wlan_psoc_obj_lock(psoc); 931 objmgr = &psoc->soc_objmgr; 932 /* unset bit, to free the slot */ 933 objmgr->wlan_vdev_id_map[map_index] &= ~(1<<(id-adjust_ix)); 934 /* reset VDEV pointer to NULL in VDEV list array */ 935 objmgr->wlan_vdev_list[id] = NULL; 936 /* decrement vdev count */ 937 objmgr->wlan_vdev_count--; 938 vdev->vdev_objmgr.vdev_id = 0xff; 939 wlan_psoc_obj_unlock(psoc); 940 941 return QDF_STATUS_SUCCESS; 942 } 943 944 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc( 945 struct wlan_objmgr_psoc *psoc, 946 enum QDF_OPMODE opmode, 947 wlan_objmgr_ref_dbgid dbg_id) 948 { 949 struct wlan_objmgr_vdev *vdev = NULL; 950 int vdev_cnt = 0; 951 uint16_t max_vdev_cnt; 952 953 /* if PSOC is NULL, return */ 954 if (!psoc) 955 return NULL; 956 957 wlan_psoc_obj_lock(psoc); 958 959 max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc); 960 /* retrieve vdev pointer from vdev list */ 961 while (vdev_cnt < max_vdev_cnt) { 962 vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_cnt]; 963 vdev_cnt++; 964 if (!vdev) 965 continue; 966 wlan_vdev_obj_lock(vdev); 967 if (vdev->vdev_mlme.vdev_opmode == opmode) { 968 wlan_vdev_obj_unlock(vdev); 969 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != 970 QDF_STATUS_SUCCESS) { 971 vdev = NULL; 972 continue; 973 } 974 break; 975 } 976 wlan_vdev_obj_unlock(vdev); 977 } 978 wlan_psoc_obj_unlock(psoc); 979 980 return vdev; 981 } 982 983 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc( 984 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 985 wlan_objmgr_ref_dbgid dbg_id) 986 { 987 struct wlan_objmgr_vdev *vdev; 988 989 /* if PSOC is NULL, return */ 990 if (!psoc) 991 return NULL; 992 /* vdev id is invalid */ 993 if (vdev_id >= wlan_psoc_get_max_vdev_count(psoc)) 994 return NULL; 995 996 wlan_psoc_obj_lock(psoc); 997 /* retrieve vdev pointer from vdev list */ 998 vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; 999 if (vdev) { 1000 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != 1001 QDF_STATUS_SUCCESS) 1002 vdev = NULL; 1003 } 1004 wlan_psoc_obj_unlock(psoc); 1005 1006 return vdev; 1007 } 1008 qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_psoc); 1009 1010 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state( 1011 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 1012 wlan_objmgr_ref_dbgid dbg_id) 1013 { 1014 struct wlan_objmgr_vdev *vdev; 1015 1016 /* if PSOC is NULL, return */ 1017 if (!psoc) 1018 return NULL; 1019 /* vdev id is invalid */ 1020 if (vdev_id >= wlan_psoc_get_max_vdev_count(psoc)) 1021 return NULL; 1022 1023 wlan_psoc_obj_lock(psoc); 1024 /* retrieve vdev pointer from vdev list */ 1025 vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; 1026 if (vdev) 1027 wlan_objmgr_vdev_get_ref(vdev, dbg_id); 1028 1029 wlan_psoc_obj_unlock(psoc); 1030 1031 return vdev; 1032 } 1033 qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_psoc_no_state); 1034 1035 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc( 1036 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, 1037 uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) 1038 { 1039 struct wlan_objmgr_vdev *vdev; 1040 struct wlan_objmgr_pdev *pdev; 1041 1042 /* if PSOC is NULL, return */ 1043 if (!psoc) 1044 return NULL; 1045 1046 if (!macaddr) 1047 return NULL; 1048 1049 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, dbg_id); 1050 if (!pdev) { 1051 obj_mgr_err("pdev is null"); 1052 return NULL; 1053 } 1054 vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev(pdev, macaddr, dbg_id); 1055 wlan_objmgr_pdev_release_ref(pdev, dbg_id); 1056 1057 return vdev; 1058 } 1059 qdf_export_symbol(wlan_objmgr_get_vdev_by_macaddr_from_psoc); 1060 1061 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state( 1062 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, 1063 uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) 1064 { 1065 struct wlan_objmgr_vdev *vdev; 1066 struct wlan_objmgr_pdev *pdev; 1067 1068 /* if PSOC is NULL, return */ 1069 if (!psoc) 1070 return NULL; 1071 1072 if (!macaddr) 1073 return NULL; 1074 1075 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, dbg_id); 1076 if (!pdev) { 1077 obj_mgr_err("pdev is null"); 1078 return NULL; 1079 } 1080 vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state(pdev, macaddr, dbg_id); 1081 wlan_objmgr_pdev_release_ref(pdev, dbg_id); 1082 1083 return vdev; 1084 } 1085 qdf_export_symbol(wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state); 1086 1087 static void wlan_obj_psoc_peerlist_add_tail(qdf_list_t *obj_list, 1088 struct wlan_objmgr_peer *obj) 1089 { 1090 qdf_list_insert_back(obj_list, &obj->psoc_peer); 1091 } 1092 1093 static QDF_STATUS wlan_obj_psoc_peerlist_remove_peer( 1094 qdf_list_t *obj_list, 1095 struct wlan_objmgr_peer *peer) 1096 { 1097 qdf_list_node_t *psoc_node = NULL; 1098 1099 if (!peer) 1100 return QDF_STATUS_E_FAILURE; 1101 /* get vdev list node element */ 1102 psoc_node = &peer->psoc_peer; 1103 /* list is empty, return failure */ 1104 if (qdf_list_remove_node(obj_list, psoc_node) != QDF_STATUS_SUCCESS) 1105 return QDF_STATUS_E_FAILURE; 1106 1107 return QDF_STATUS_SUCCESS; 1108 } 1109 1110 static QDF_STATUS wlan_peer_bssid_match(struct wlan_objmgr_peer *peer, 1111 uint8_t *bssid) 1112 { 1113 struct wlan_objmgr_vdev *vdev = wlan_peer_get_vdev(peer); 1114 uint8_t *peer_bssid = wlan_vdev_mlme_get_macaddr(vdev); 1115 1116 if (WLAN_ADDR_EQ(peer_bssid, bssid) == QDF_STATUS_SUCCESS) 1117 return QDF_STATUS_SUCCESS; 1118 else 1119 return QDF_STATUS_E_FAILURE; 1120 } 1121 1122 /** 1123 * wlan_obj_psoc_peerlist_get_peer_logically_deleted() - get peer 1124 * from psoc peer list 1125 * @psoc: PSOC object 1126 * @macaddr: MAC address 1127 * 1128 * API to finds peer object pointer of logically deleted peer 1129 * 1130 * Return: peer pointer 1131 * NULL on FAILURE 1132 */ 1133 static struct wlan_objmgr_peer * 1134 wlan_obj_psoc_peerlist_get_peer_logically_deleted( 1135 qdf_list_t *obj_list, uint8_t *macaddr, 1136 wlan_objmgr_ref_dbgid dbg_id) 1137 { 1138 struct wlan_objmgr_peer *peer; 1139 struct wlan_objmgr_peer *peer_temp; 1140 1141 /* Iterate through hash list to get the peer */ 1142 peer = wlan_psoc_peer_list_peek_head(obj_list); 1143 while (peer) { 1144 /* For peer, macaddr is key */ 1145 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) 1146 == QDF_STATUS_SUCCESS) { 1147 /* Return peer in logically deleted state */ 1148 if (peer->obj_state == 1149 WLAN_OBJ_STATE_LOGICALLY_DELETED) { 1150 wlan_objmgr_peer_get_ref(peer, dbg_id); 1151 1152 return peer; 1153 } 1154 1155 } 1156 /* Move to next peer */ 1157 peer_temp = peer; 1158 peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); 1159 } 1160 1161 /* Not found, return NULL */ 1162 return NULL; 1163 } 1164 1165 /** 1166 * wlan_obj_psoc_peerlist_get_peer() - get peer from psoc peer list 1167 * @psoc: PSOC object 1168 * @macaddr: MAC address 1169 * 1170 * API to finds peer object pointer by MAC addr from hash list 1171 * 1172 * Return: peer pointer 1173 * NULL on FAILURE 1174 */ 1175 static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( 1176 qdf_list_t *obj_list, uint8_t *macaddr, 1177 wlan_objmgr_ref_dbgid dbg_id) 1178 { 1179 struct wlan_objmgr_peer *peer; 1180 struct wlan_objmgr_peer *peer_temp; 1181 1182 /* Iterate through hash list to get the peer */ 1183 peer = wlan_psoc_peer_list_peek_head(obj_list); 1184 while (peer) { 1185 /* For peer, macaddr is key */ 1186 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) 1187 == QDF_STATUS_SUCCESS) { 1188 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 1189 QDF_STATUS_SUCCESS) { 1190 return peer; 1191 } 1192 } 1193 /* Move to next peer */ 1194 peer_temp = peer; 1195 peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); 1196 } 1197 1198 /* Not found, return NULL */ 1199 return NULL; 1200 } 1201 1202 /** 1203 * wlan_obj_psoc_peerlist_get_peer_by_pdev_id() - get peer from psoc peer list 1204 * @psoc: PSOC object 1205 * @macaddr: MAC address 1206 * #pdev_id: Pdev id 1207 * 1208 * API to finds peer object pointer by MAC addr and pdev id from hash list 1209 * 1210 * Return: peer pointer 1211 * NULL on FAILURE 1212 */ 1213 static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_pdev_id( 1214 qdf_list_t *obj_list, uint8_t *macaddr, 1215 uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id) 1216 { 1217 struct wlan_objmgr_peer *peer; 1218 struct wlan_objmgr_peer *peer_temp; 1219 1220 /* Iterate through hash list to get the peer */ 1221 peer = wlan_psoc_peer_list_peek_head(obj_list); 1222 while (peer) { 1223 /* For peer, macaddr is key */ 1224 if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) 1225 == QDF_STATUS_SUCCESS) && 1226 (wlan_peer_get_pdev_id(peer) == pdev_id)) { 1227 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == 1228 QDF_STATUS_SUCCESS) { 1229 return peer; 1230 } 1231 } 1232 /* Move to next peer */ 1233 peer_temp = peer; 1234 peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); 1235 } 1236 1237 /* Not found, return NULL */ 1238 return NULL; 1239 } 1240 1241 static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state( 1242 qdf_list_t *obj_list, uint8_t *macaddr, 1243 uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id) 1244 { 1245 struct wlan_objmgr_peer *peer; 1246 struct wlan_objmgr_peer *peer_temp; 1247 1248 /* Iterate through hash list to get the peer */ 1249 peer = wlan_psoc_peer_list_peek_head(obj_list); 1250 while (peer) { 1251 /* For peer, macaddr and pdev_id is key */ 1252 if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) 1253 == QDF_STATUS_SUCCESS) && 1254 (wlan_peer_get_pdev_id(peer) == pdev_id)) { 1255 wlan_objmgr_peer_get_ref(peer, dbg_id); 1256 1257 return peer; 1258 } 1259 /* Move to next peer */ 1260 peer_temp = peer; 1261 peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); 1262 } 1263 1264 /* Not found, return NULL */ 1265 return NULL; 1266 } 1267 1268 /** 1269 * wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid() - get peer 1270 * from psoc peer list using 1271 * mac and vdev self mac 1272 * @obj_list: peer object list 1273 * @macaddr: MAC address 1274 * @bssid: BSSID address 1275 * @dbg_id: id of the caller 1276 * 1277 * API to finds peer object pointer by MAC addr and BSSID from 1278 * peer hash list for a node which is in logically deleted state, 1279 * bssid check is done on matching peer 1280 * 1281 * Caller to free the list allocated in this function 1282 * 1283 * Return: list of peer pointers 1284 * NULL on FAILURE 1285 */ 1286 static qdf_list_t 1287 *wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid( 1288 qdf_list_t *obj_list, uint8_t *macaddr, 1289 uint8_t *bssid, uint8_t pdev_id, 1290 wlan_objmgr_ref_dbgid dbg_id) 1291 { 1292 struct wlan_objmgr_peer *peer; 1293 struct wlan_objmgr_peer *peer_temp; 1294 struct wlan_logically_del_peer *peer_list = NULL; 1295 qdf_list_t *logical_del_peer_list = NULL; 1296 bool lock_released = false; 1297 1298 logical_del_peer_list = qdf_mem_malloc(sizeof(*logical_del_peer_list)); 1299 if (!logical_del_peer_list) 1300 return NULL; 1301 1302 qdf_list_create(logical_del_peer_list, WLAN_UMAC_PSOC_MAX_PEERS); 1303 1304 /* Iterate through hash list to get the peer */ 1305 peer = wlan_psoc_peer_list_peek_head(obj_list); 1306 while (peer) { 1307 wlan_peer_obj_lock(peer); 1308 /* For peer, macaddr and pdev id are keys */ 1309 if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) 1310 == QDF_STATUS_SUCCESS) && 1311 (wlan_peer_get_pdev_id(peer) == pdev_id)) { 1312 /* 1313 * if BSSID not NULL, 1314 * then match is requested by caller, check BSSID 1315 * (vdev mac == bssid) -- return peer 1316 * (vdev mac != bssid) -- perform next iteration 1317 */ 1318 if ((!bssid) || 1319 (wlan_peer_bssid_match(peer, bssid) == 1320 QDF_STATUS_SUCCESS)) { 1321 /* Return peer in logically deleted state */ 1322 if ((peer->obj_state == 1323 WLAN_OBJ_STATE_LOGICALLY_DELETED) && 1324 qdf_atomic_read( 1325 &peer->peer_objmgr.ref_cnt)) { 1326 1327 wlan_objmgr_peer_get_ref(peer, dbg_id); 1328 wlan_peer_obj_unlock(peer); 1329 lock_released = true; 1330 1331 peer_list = 1332 qdf_mem_malloc( 1333 sizeof(struct wlan_logically_del_peer)); 1334 if (!peer_list) { 1335 wlan_objmgr_peer_release_ref(peer, dbg_id); 1336 /* Lock is already released */ 1337 WLAN_OBJMGR_BUG(0); 1338 break; 1339 } 1340 1341 peer_list->peer = peer; 1342 1343 qdf_list_insert_front( 1344 logical_del_peer_list, 1345 &peer_list->list); 1346 } 1347 } 1348 } 1349 1350 if (!lock_released) 1351 wlan_peer_obj_unlock(peer); 1352 1353 /* Move to next peer */ 1354 peer_temp = peer; 1355 peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); 1356 lock_released = false; 1357 } 1358 1359 /* Not found, return NULL */ 1360 if (qdf_list_empty(logical_del_peer_list)) { 1361 qdf_mem_free(logical_del_peer_list); 1362 return NULL; 1363 } else { 1364 return logical_del_peer_list; 1365 } 1366 1367 } 1368 1369 /** 1370 * wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid() - get peer from psoc peer 1371 * list using mac and vdev 1372 * self mac 1373 * @psoc: PSOC object 1374 * @macaddr: MAC address 1375 * @bssid: BSSID address 1376 * 1377 * API to finds peer object pointer by MAC addr and BSSID from 1378 * peer hash list, bssid check is done on matching peer 1379 * 1380 * Return: peer pointer 1381 * NULL on FAILURE 1382 */ 1383 static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( 1384 qdf_list_t *obj_list, uint8_t *macaddr, 1385 uint8_t *bssid, uint8_t pdev_id, 1386 wlan_objmgr_ref_dbgid dbg_id) 1387 { 1388 struct wlan_objmgr_peer *peer; 1389 struct wlan_objmgr_peer *peer_temp; 1390 1391 /* Iterate through hash list to get the peer */ 1392 peer = wlan_psoc_peer_list_peek_head(obj_list); 1393 while (peer) { 1394 /* For peer, macaddr is key */ 1395 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) 1396 == QDF_STATUS_SUCCESS) { 1397 /* 1398 * BSSID match is requested by caller, check BSSID 1399 * (vdev mac == bssid) -- return peer 1400 * (vdev mac != bssid) -- perform next iteration 1401 */ 1402 if ((wlan_peer_bssid_match(peer, bssid) == 1403 QDF_STATUS_SUCCESS) && 1404 (wlan_peer_get_pdev_id(peer) == pdev_id)) { 1405 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) 1406 == QDF_STATUS_SUCCESS) { 1407 return peer; 1408 } 1409 } 1410 } 1411 /* Move to next peer */ 1412 peer_temp = peer; 1413 peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); 1414 } 1415 /* Not found, return NULL */ 1416 return NULL; 1417 } 1418 1419 static struct wlan_objmgr_peer 1420 *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state( 1421 qdf_list_t *obj_list, uint8_t *macaddr, 1422 uint8_t *bssid, 1423 uint8_t pdev_id, 1424 wlan_objmgr_ref_dbgid dbg_id) 1425 { 1426 struct wlan_objmgr_peer *peer; 1427 struct wlan_objmgr_peer *peer_temp; 1428 1429 /* Iterate through hash list to get the peer */ 1430 peer = wlan_psoc_peer_list_peek_head(obj_list); 1431 while (peer) { 1432 /* For peer, macaddr is key */ 1433 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) 1434 == QDF_STATUS_SUCCESS) { 1435 /* 1436 * BSSID match is requested by caller, check BSSID 1437 * (vdev mac == bssid) -- return peer 1438 * (vdev mac != bssid) -- perform next iteration 1439 */ 1440 if ((wlan_peer_bssid_match(peer, bssid) == 1441 QDF_STATUS_SUCCESS) && 1442 (wlan_peer_get_pdev_id(peer) == pdev_id)) { 1443 wlan_objmgr_peer_get_ref(peer, dbg_id); 1444 1445 return peer; 1446 } 1447 } 1448 /* Move to next peer */ 1449 peer_temp = peer; 1450 peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); 1451 } 1452 1453 /* Not found, return NULL */ 1454 return NULL; 1455 } 1456 1457 QDF_STATUS wlan_objmgr_psoc_peer_attach(struct wlan_objmgr_psoc *psoc, 1458 struct wlan_objmgr_peer *peer) 1459 { 1460 struct wlan_objmgr_psoc_objmgr *objmgr; 1461 uint8_t hash_index; 1462 struct wlan_peer_list *peer_list; 1463 1464 wlan_psoc_obj_lock(psoc); 1465 objmgr = &psoc->soc_objmgr; 1466 /* Max temporary peer limit is reached, return failure */ 1467 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) { 1468 if (objmgr->temp_peer_count >= WLAN_MAX_PSOC_TEMP_PEERS) { 1469 wlan_psoc_obj_unlock(psoc); 1470 return QDF_STATUS_E_FAILURE; 1471 } 1472 } else { 1473 /* Max peer limit is reached, return failure */ 1474 if (objmgr->wlan_peer_count 1475 >= wlan_psoc_get_max_peer_count(psoc)) { 1476 wlan_psoc_obj_unlock(psoc); 1477 return QDF_STATUS_E_FAILURE; 1478 } 1479 } 1480 1481 /* Derive hash index from mac address */ 1482 hash_index = WLAN_PEER_HASH(peer->macaddr); 1483 peer_list = &objmgr->peer_list; 1484 /* psoc lock should be taken before list lock */ 1485 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1486 /* add peer to hash peer list */ 1487 wlan_obj_psoc_peerlist_add_tail( 1488 &peer_list->peer_hash[hash_index], 1489 peer); 1490 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1491 /* Increment peer count */ 1492 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 1493 objmgr->temp_peer_count++; 1494 else 1495 objmgr->wlan_peer_count++; 1496 1497 wlan_psoc_obj_unlock(psoc); 1498 1499 return QDF_STATUS_SUCCESS; 1500 } 1501 1502 QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc, 1503 struct wlan_objmgr_peer *peer) 1504 { 1505 struct wlan_objmgr_psoc_objmgr *objmgr; 1506 uint8_t hash_index; 1507 struct wlan_peer_list *peer_list; 1508 1509 wlan_psoc_obj_lock(psoc); 1510 objmgr = &psoc->soc_objmgr; 1511 /* if list is empty, return */ 1512 if (objmgr->wlan_peer_count == 0) { 1513 wlan_psoc_obj_unlock(psoc); 1514 return QDF_STATUS_E_FAILURE; 1515 } 1516 /* Get hash index, to locate the actual peer list */ 1517 hash_index = WLAN_PEER_HASH(peer->macaddr); 1518 peer_list = &objmgr->peer_list; 1519 /* psoc lock should be taken before list lock */ 1520 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1521 /* removes the peer from peer_list */ 1522 if (wlan_obj_psoc_peerlist_remove_peer( 1523 &peer_list->peer_hash[hash_index], 1524 peer) == 1525 QDF_STATUS_E_FAILURE) { 1526 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1527 wlan_psoc_obj_unlock(psoc); 1528 obj_mgr_err("Failed to detach peer"); 1529 return QDF_STATUS_E_FAILURE; 1530 } 1531 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1532 /* Decrement peer count */ 1533 if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) 1534 objmgr->temp_peer_count--; 1535 else 1536 objmgr->wlan_peer_count--; 1537 wlan_psoc_obj_unlock(psoc); 1538 1539 return QDF_STATUS_SUCCESS; 1540 } 1541 1542 struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted( 1543 struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, 1544 wlan_objmgr_ref_dbgid dbg_id) 1545 { 1546 struct wlan_objmgr_psoc_objmgr *objmgr; 1547 uint8_t hash_index; 1548 struct wlan_objmgr_peer *peer = NULL; 1549 struct wlan_peer_list *peer_list; 1550 1551 /* psoc lock should be taken before peer list lock */ 1552 wlan_psoc_obj_lock(psoc); 1553 objmgr = &psoc->soc_objmgr; 1554 /* List is empty, return NULL */ 1555 if (objmgr->wlan_peer_count == 0) { 1556 wlan_psoc_obj_unlock(psoc); 1557 return NULL; 1558 } 1559 /* reduce the search window, with hash key */ 1560 hash_index = WLAN_PEER_HASH(macaddr); 1561 peer_list = &objmgr->peer_list; 1562 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1563 /* Iterate through peer list, get peer */ 1564 peer = wlan_obj_psoc_peerlist_get_peer_logically_deleted( 1565 &peer_list->peer_hash[hash_index], macaddr, dbg_id); 1566 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1567 wlan_psoc_obj_unlock(psoc); 1568 1569 return peer; 1570 } 1571 1572 struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac( 1573 struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, 1574 wlan_objmgr_ref_dbgid dbg_id) 1575 { 1576 struct wlan_objmgr_psoc_objmgr *objmgr; 1577 uint8_t hash_index; 1578 struct wlan_objmgr_peer *peer = NULL; 1579 struct wlan_peer_list *peer_list; 1580 1581 if (!macaddr) 1582 return NULL; 1583 1584 /* psoc lock should be taken before peer list lock */ 1585 wlan_psoc_obj_lock(psoc); 1586 objmgr = &psoc->soc_objmgr; 1587 /* List is empty, return NULL */ 1588 if (objmgr->wlan_peer_count == 0) { 1589 wlan_psoc_obj_unlock(psoc); 1590 return NULL; 1591 } 1592 /* reduce the search window, with hash key */ 1593 hash_index = WLAN_PEER_HASH(macaddr); 1594 peer_list = &objmgr->peer_list; 1595 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1596 /* Iterate through peer list, get peer */ 1597 peer = wlan_obj_psoc_peerlist_get_peer( 1598 &peer_list->peer_hash[hash_index], macaddr, dbg_id); 1599 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1600 wlan_psoc_obj_unlock(psoc); 1601 1602 return peer; 1603 } 1604 qdf_export_symbol(wlan_objmgr_get_peer_by_mac); 1605 1606 struct wlan_objmgr_peer *wlan_objmgr_get_peer( 1607 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, 1608 uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) 1609 { 1610 struct wlan_objmgr_psoc_objmgr *objmgr; 1611 uint8_t hash_index; 1612 struct wlan_objmgr_peer *peer = NULL; 1613 struct wlan_peer_list *peer_list; 1614 1615 if (pdev_id >= WLAN_UMAC_MAX_PDEVS) 1616 QDF_ASSERT(0); 1617 1618 if (!macaddr) 1619 return NULL; 1620 1621 /* psoc lock should be taken before peer list lock */ 1622 wlan_psoc_obj_lock(psoc); 1623 objmgr = &psoc->soc_objmgr; 1624 /* List is empty, return NULL */ 1625 if (objmgr->wlan_peer_count == 0) { 1626 wlan_psoc_obj_unlock(psoc); 1627 return NULL; 1628 } 1629 /* reduce the search window, with hash key */ 1630 hash_index = WLAN_PEER_HASH(macaddr); 1631 peer_list = &objmgr->peer_list; 1632 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1633 /* Iterate through peer list, get peer */ 1634 peer = wlan_obj_psoc_peerlist_get_peer_by_pdev_id( 1635 &peer_list->peer_hash[hash_index], macaddr, pdev_id, dbg_id); 1636 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1637 wlan_psoc_obj_unlock(psoc); 1638 1639 return peer; 1640 } 1641 qdf_export_symbol(wlan_objmgr_get_peer); 1642 1643 struct wlan_objmgr_peer *wlan_objmgr_get_peer_nolock( 1644 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, 1645 uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) 1646 { 1647 struct wlan_objmgr_psoc_objmgr *objmgr; 1648 uint8_t hash_index; 1649 struct wlan_objmgr_peer *peer = NULL; 1650 struct wlan_peer_list *peer_list; 1651 1652 /* psoc lock should be taken before peer list lock */ 1653 objmgr = &psoc->soc_objmgr; 1654 /* List is empty, return NULL */ 1655 if (objmgr->wlan_peer_count == 0) 1656 return NULL; 1657 1658 /* reduce the search window, with hash key */ 1659 hash_index = WLAN_PEER_HASH(macaddr); 1660 peer_list = &objmgr->peer_list; 1661 /* Iterate through peer list, get peer */ 1662 peer = wlan_obj_psoc_peerlist_get_peer_by_pdev_id( 1663 &peer_list->peer_hash[hash_index], macaddr, pdev_id, dbg_id); 1664 1665 return peer; 1666 } 1667 qdf_export_symbol(wlan_objmgr_get_peer_nolock); 1668 1669 1670 struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state( 1671 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, 1672 uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) 1673 { 1674 struct wlan_objmgr_psoc_objmgr *objmgr; 1675 uint8_t hash_index; 1676 struct wlan_objmgr_peer *peer = NULL; 1677 struct wlan_peer_list *peer_list; 1678 1679 /* psoc lock should be taken before peer list lock */ 1680 wlan_psoc_obj_lock(psoc); 1681 objmgr = &psoc->soc_objmgr; 1682 /* List is empty, return NULL */ 1683 if (objmgr->wlan_peer_count == 0) { 1684 wlan_psoc_obj_unlock(psoc); 1685 return NULL; 1686 } 1687 /* reduce the search window, with hash key */ 1688 hash_index = WLAN_PEER_HASH(macaddr); 1689 peer_list = &objmgr->peer_list; 1690 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1691 /* Iterate through peer list, get peer */ 1692 peer = wlan_obj_psoc_peerlist_get_peer_no_state( 1693 &peer_list->peer_hash[hash_index], macaddr, pdev_id, dbg_id); 1694 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1695 wlan_psoc_obj_unlock(psoc); 1696 1697 return peer; 1698 } 1699 qdf_export_symbol(wlan_objmgr_get_peer_no_state); 1700 1701 struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev( 1702 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, 1703 uint8_t *bssid, uint8_t *macaddr, 1704 wlan_objmgr_ref_dbgid dbg_id) 1705 { 1706 struct wlan_objmgr_psoc_objmgr *objmgr; 1707 uint8_t hash_index; 1708 struct wlan_objmgr_peer *peer = NULL; 1709 struct wlan_peer_list *peer_list; 1710 1711 /* psoc lock should be taken before peer list lock */ 1712 wlan_psoc_obj_lock(psoc); 1713 objmgr = &psoc->soc_objmgr; 1714 /* List is empty, return NULL */ 1715 if (objmgr->wlan_peer_count == 0) { 1716 wlan_psoc_obj_unlock(psoc); 1717 return NULL; 1718 } 1719 /* reduce the search window, with hash key */ 1720 hash_index = WLAN_PEER_HASH(macaddr); 1721 peer_list = &objmgr->peer_list; 1722 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1723 /* Iterate through peer list, get peer */ 1724 peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( 1725 &peer_list->peer_hash[hash_index], macaddr, bssid, 1726 pdev_id, dbg_id); 1727 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1728 wlan_psoc_obj_unlock(psoc); 1729 1730 return peer; 1731 } 1732 qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev); 1733 1734 1735 /** 1736 * wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev() - get peer from psoc 1737 * peer list using 1738 * mac and vdev 1739 * self mac 1740 * @psoc: PSOC object 1741 * @pdev_id: Pdev id 1742 * @macaddr: MAC address 1743 * @bssid: BSSID address. NULL mac means search all. 1744 * @dbg_id: id of the caller 1745 * 1746 * API to finds peer object pointer by MAC addr and BSSID from 1747 * peer hash list, bssid check is done on matching peer 1748 * 1749 * Return: list of peer pointer pointers 1750 * NULL on FAILURE 1751 */ 1752 1753 qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev( 1754 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, 1755 uint8_t *bssid, uint8_t *macaddr, 1756 wlan_objmgr_ref_dbgid dbg_id) 1757 { 1758 struct wlan_objmgr_psoc_objmgr *objmgr; 1759 uint8_t hash_index; 1760 struct wlan_peer_list *peer_list = NULL; 1761 qdf_list_t *logical_del_peer_list = NULL; 1762 1763 /* psoc lock should be taken before peer list lock */ 1764 wlan_psoc_obj_lock(psoc); 1765 objmgr = &psoc->soc_objmgr; 1766 /* List is empty, return NULL */ 1767 if (objmgr->wlan_peer_count == 0) { 1768 wlan_psoc_obj_unlock(psoc); 1769 return NULL; 1770 } 1771 /* reduce the search window, with hash key */ 1772 hash_index = WLAN_PEER_HASH(macaddr); 1773 peer_list = &objmgr->peer_list; 1774 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1775 1776 /* Iterate through peer list, get peer */ 1777 logical_del_peer_list = 1778 wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid( 1779 &peer_list->peer_hash[hash_index], macaddr, 1780 bssid, pdev_id, dbg_id); 1781 1782 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1783 wlan_psoc_obj_unlock(psoc); 1784 1785 return logical_del_peer_list; 1786 } 1787 qdf_export_symbol(wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev); 1788 1789 struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state( 1790 struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, 1791 uint8_t *bssid, uint8_t *macaddr, 1792 wlan_objmgr_ref_dbgid dbg_id) 1793 { 1794 struct wlan_objmgr_psoc_objmgr *objmgr; 1795 uint8_t hash_index; 1796 struct wlan_objmgr_peer *peer = NULL; 1797 struct wlan_peer_list *peer_list; 1798 1799 /* psoc lock should be taken before peer list lock */ 1800 wlan_psoc_obj_lock(psoc); 1801 objmgr = &psoc->soc_objmgr; 1802 /* List is empty, return NULL */ 1803 if (objmgr->wlan_peer_count == 0) { 1804 wlan_psoc_obj_unlock(psoc); 1805 return NULL; 1806 } 1807 /* reduce the search window, with hash key */ 1808 hash_index = WLAN_PEER_HASH(macaddr); 1809 peer_list = &objmgr->peer_list; 1810 qdf_spin_lock_bh(&peer_list->peer_list_lock); 1811 /* Iterate through peer list, get peer */ 1812 peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state( 1813 &peer_list->peer_hash[hash_index], macaddr, bssid, 1814 pdev_id, dbg_id); 1815 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 1816 wlan_psoc_obj_unlock(psoc); 1817 1818 return peer; 1819 } 1820 qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev_no_state); 1821 1822 void *wlan_objmgr_psoc_get_comp_private_obj(struct wlan_objmgr_psoc *psoc, 1823 enum wlan_umac_comp_id id) 1824 { 1825 void *comp_private_obj; 1826 1827 /* component id is invalid */ 1828 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 1829 QDF_BUG(0); 1830 return NULL; 1831 } 1832 1833 if (!psoc) { 1834 QDF_BUG(0); 1835 return NULL; 1836 } 1837 1838 comp_private_obj = psoc->soc_comp_priv_obj[id]; 1839 1840 return comp_private_obj; 1841 } 1842 qdf_export_symbol(wlan_objmgr_psoc_get_comp_private_obj); 1843 1844 void wlan_objmgr_psoc_get_ref(struct wlan_objmgr_psoc *psoc, 1845 wlan_objmgr_ref_dbgid id) 1846 { 1847 if (!psoc) { 1848 obj_mgr_err("psoc obj is NULL for id:%d", id); 1849 QDF_ASSERT(0); 1850 return; 1851 } 1852 /* Increment ref count */ 1853 qdf_atomic_inc(&psoc->soc_objmgr.ref_cnt); 1854 qdf_atomic_inc(&psoc->soc_objmgr.ref_id_dbg[id]); 1855 return; 1856 } 1857 qdf_export_symbol(wlan_objmgr_psoc_get_ref); 1858 1859 QDF_STATUS wlan_objmgr_psoc_try_get_ref(struct wlan_objmgr_psoc *psoc, 1860 wlan_objmgr_ref_dbgid id) 1861 { 1862 if (!psoc) { 1863 obj_mgr_err("psoc obj is NULL for id:%d", id); 1864 QDF_ASSERT(0); 1865 return QDF_STATUS_E_FAILURE; 1866 } 1867 1868 wlan_psoc_obj_lock(psoc); 1869 if (psoc->obj_state != WLAN_OBJ_STATE_CREATED) { 1870 wlan_psoc_obj_unlock(psoc); 1871 if (psoc->soc_objmgr.print_cnt++ <= 1872 WLAN_OBJMGR_RATELIMIT_THRESH) 1873 obj_mgr_err( 1874 "[Ref id: %d] psoc is not in Created state(%d)", 1875 id, psoc->obj_state); 1876 1877 return QDF_STATUS_E_RESOURCES; 1878 } 1879 1880 /* Increment ref count */ 1881 wlan_objmgr_psoc_get_ref(psoc, id); 1882 wlan_psoc_obj_unlock(psoc); 1883 1884 return QDF_STATUS_SUCCESS; 1885 } 1886 qdf_export_symbol(wlan_objmgr_psoc_try_get_ref); 1887 1888 void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc, 1889 wlan_objmgr_ref_dbgid id) 1890 { 1891 if (!psoc) { 1892 obj_mgr_err("psoc obj is NULL for id:%d", id); 1893 QDF_ASSERT(0); 1894 return; 1895 } 1896 1897 if (!qdf_atomic_read(&psoc->soc_objmgr.ref_id_dbg[id])) { 1898 obj_mgr_err("psoc ref cnt was not taken by %d", id); 1899 wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg, 1900 QDF_TRACE_LEVEL_FATAL); 1901 WLAN_OBJMGR_BUG(0); 1902 } 1903 1904 if (!qdf_atomic_read(&psoc->soc_objmgr.ref_cnt)) { 1905 obj_mgr_err("psoc ref cnt is 0"); 1906 WLAN_OBJMGR_BUG(0); 1907 return; 1908 } 1909 1910 qdf_atomic_dec(&psoc->soc_objmgr.ref_id_dbg[id]); 1911 /* Decrement ref count, free psoc, if ref count == 0 */ 1912 if (qdf_atomic_dec_and_test(&psoc->soc_objmgr.ref_cnt)) 1913 wlan_objmgr_psoc_obj_destroy(psoc); 1914 1915 return; 1916 } 1917 qdf_export_symbol(wlan_objmgr_psoc_release_ref); 1918 1919 static void wlan_objmgr_psoc_peer_ref_print(struct wlan_objmgr_psoc *psoc, 1920 void *obj, void *args) 1921 { 1922 struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj; 1923 WLAN_OBJ_STATE obj_state; 1924 uint8_t vdev_id; 1925 uint8_t *macaddr; 1926 1927 wlan_peer_obj_lock(peer); 1928 macaddr = wlan_peer_get_macaddr(peer); 1929 obj_state = peer->obj_state; 1930 vdev_id = wlan_vdev_get_id(wlan_peer_get_vdev(peer)); 1931 wlan_peer_obj_unlock(peer); 1932 1933 obj_mgr_alert("Peer MAC:%02x:%02x:%02x:%02x:%02x:%02x state:%d vdev_id:%d", 1934 macaddr[0], macaddr[1], macaddr[2], macaddr[3], 1935 macaddr[4], macaddr[5], obj_state, vdev_id); 1936 wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_FATAL); 1937 } 1938 1939 static void wlan_objmgr_psoc_vdev_ref_print(struct wlan_objmgr_psoc *psoc, 1940 void *obj, void *args) 1941 { 1942 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj; 1943 WLAN_OBJ_STATE obj_state; 1944 uint8_t id; 1945 1946 wlan_vdev_obj_lock(vdev); 1947 id = wlan_vdev_get_id(vdev); 1948 obj_state = vdev->obj_state; 1949 wlan_vdev_obj_unlock(vdev); 1950 obj_mgr_alert("Vdev ID is %d, state %d", id, obj_state); 1951 1952 wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, 1953 QDF_TRACE_LEVEL_FATAL); 1954 } 1955 1956 static void wlan_objmgr_psoc_pdev_ref_print(struct wlan_objmgr_psoc *psoc, 1957 void *obj, void *args) 1958 { 1959 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; 1960 uint8_t id; 1961 1962 wlan_pdev_obj_lock(pdev); 1963 id = wlan_objmgr_pdev_get_pdev_id(pdev); 1964 wlan_pdev_obj_unlock(pdev); 1965 obj_mgr_alert("pdev ID is %d", id); 1966 1967 wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg, 1968 QDF_TRACE_LEVEL_FATAL); 1969 } 1970 1971 QDF_STATUS wlan_objmgr_print_ref_all_objects_per_psoc( 1972 struct wlan_objmgr_psoc *psoc) 1973 { 1974 obj_mgr_alert("Ref counts of PEER"); 1975 wlan_objmgr_iterate_obj_list_all_noref(psoc, WLAN_PEER_OP, 1976 wlan_objmgr_psoc_peer_ref_print, NULL); 1977 obj_mgr_alert("Ref counts of VDEV"); 1978 wlan_objmgr_iterate_obj_list_all_noref(psoc, WLAN_VDEV_OP, 1979 wlan_objmgr_psoc_vdev_ref_print, NULL); 1980 obj_mgr_alert("Ref counts of PDEV"); 1981 wlan_objmgr_iterate_obj_list_all_noref(psoc, WLAN_PDEV_OP, 1982 wlan_objmgr_psoc_pdev_ref_print, NULL); 1983 1984 obj_mgr_alert(" Ref counts of PSOC"); 1985 wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg, 1986 QDF_TRACE_LEVEL_FATAL); 1987 1988 return QDF_STATUS_SUCCESS; 1989 } 1990 qdf_export_symbol(wlan_objmgr_print_ref_all_objects_per_psoc); 1991 1992 QDF_STATUS wlan_objmgr_psoc_set_user_config(struct wlan_objmgr_psoc *psoc, 1993 struct wlan_objmgr_psoc_user_config *user_config_data) 1994 { 1995 if (!user_config_data) { 1996 obj_mgr_err("user_config_data is NULL"); 1997 QDF_BUG(0); 1998 return QDF_STATUS_E_FAILURE; 1999 } 2000 wlan_psoc_obj_lock(psoc); 2001 qdf_mem_copy(&psoc->soc_nif.user_config, user_config_data, 2002 sizeof(psoc->soc_nif.user_config)); 2003 wlan_psoc_obj_unlock(psoc); 2004 2005 return QDF_STATUS_SUCCESS; 2006 } 2007 2008 void wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc) 2009 { 2010 struct wlan_objmgr_psoc_objmgr *_psoc; 2011 struct wlan_objmgr_pdev *pdev; 2012 int pdev_id; 2013 uint32_t leaks = 0; 2014 2015 QDF_BUG(psoc); 2016 if (!psoc) 2017 return; 2018 2019 wlan_psoc_obj_lock(psoc); 2020 _psoc = &psoc->soc_objmgr; 2021 if (!_psoc->wlan_pdev_count) { 2022 wlan_psoc_obj_unlock(psoc); 2023 return; 2024 } 2025 2026 obj_mgr_alert("objmgr pdev leaks detected for psoc %u!", 2027 _psoc->psoc_id); 2028 obj_mgr_alert("----------------------------------------------------"); 2029 obj_mgr_alert("Pdev Id Refs Module"); 2030 obj_mgr_alert("----------------------------------------------------"); 2031 2032 wlan_objmgr_for_each_psoc_pdev(psoc, pdev_id, pdev) { 2033 qdf_atomic_t *ref_id_dbg; 2034 int ref_id; 2035 int32_t refs; 2036 2037 wlan_pdev_obj_lock(pdev); 2038 ref_id_dbg = pdev->pdev_objmgr.ref_id_dbg; 2039 wlan_objmgr_for_each_refs(ref_id_dbg, ref_id, refs) { 2040 leaks++; 2041 obj_mgr_alert("%7u %4u %s", 2042 pdev_id, refs, 2043 string_from_dbgid(ref_id)); 2044 } 2045 wlan_pdev_obj_unlock(pdev); 2046 } 2047 2048 QDF_DEBUG_PANIC("%u objmgr pdev leaks detected for psoc %u!", 2049 leaks, _psoc->psoc_id); 2050 2051 wlan_psoc_obj_unlock(psoc); 2052 } 2053 qdf_export_symbol(wlan_objmgr_psoc_check_for_pdev_leaks); 2054 2055 void wlan_objmgr_psoc_check_for_vdev_leaks(struct wlan_objmgr_psoc *psoc) 2056 { 2057 struct wlan_objmgr_psoc_objmgr *_psoc; 2058 struct wlan_objmgr_vdev *vdev; 2059 int vdev_id; 2060 uint32_t leaks = 0; 2061 2062 QDF_BUG(psoc); 2063 if (!psoc) 2064 return; 2065 2066 wlan_psoc_obj_lock(psoc); 2067 _psoc = &psoc->soc_objmgr; 2068 if (!_psoc->wlan_vdev_count) { 2069 wlan_psoc_obj_unlock(psoc); 2070 return; 2071 } 2072 2073 obj_mgr_alert("objmgr vdev leaks detected for psoc %u!", 2074 _psoc->psoc_id); 2075 obj_mgr_alert("----------------------------------------------------"); 2076 obj_mgr_alert("Vdev Id Refs Module"); 2077 obj_mgr_alert("----------------------------------------------------"); 2078 2079 wlan_objmgr_for_each_psoc_vdev(psoc, vdev_id, vdev) { 2080 qdf_atomic_t *ref_id_dbg; 2081 int ref_id; 2082 int32_t refs; 2083 2084 wlan_vdev_obj_lock(vdev); 2085 ref_id_dbg = vdev->vdev_objmgr.ref_id_dbg; 2086 wlan_objmgr_for_each_refs(ref_id_dbg, ref_id, refs) { 2087 leaks++; 2088 obj_mgr_alert("%7u %4u %s", 2089 vdev_id, refs, string_from_dbgid(ref_id)); 2090 } 2091 wlan_vdev_obj_unlock(vdev); 2092 } 2093 2094 QDF_DEBUG_PANIC("%u objmgr vdev leaks detected for psoc %u!", 2095 leaks, _psoc->psoc_id); 2096 2097 wlan_psoc_obj_unlock(psoc); 2098 } 2099 qdf_export_symbol(wlan_objmgr_psoc_check_for_vdev_leaks); 2100 2101 #ifdef WLAN_OBJMGR_REF_ID_DEBUG 2102 static void 2103 wlan_objmgr_print_peer_ref_leaks(struct wlan_objmgr_peer *peer, int vdev_id) 2104 { 2105 qdf_atomic_t *ref_id_dbg; 2106 int32_t refs; 2107 int ref_id; 2108 2109 ref_id_dbg = peer->peer_objmgr.ref_id_dbg; 2110 wlan_objmgr_for_each_refs(ref_id_dbg, ref_id, refs) { 2111 obj_mgr_alert(QDF_MAC_ADDR_STR " %7u %4u %s", 2112 QDF_MAC_ADDR_ARRAY(peer->macaddr), 2113 vdev_id, 2114 refs, 2115 string_from_dbgid(ref_id)); 2116 } 2117 } 2118 #else 2119 static inline void 2120 wlan_objmgr_print_peer_ref_leaks(struct wlan_objmgr_peer *peer, int vdev_id) 2121 { 2122 obj_mgr_alert(QDF_MAC_ADDR_STR " %7u %4u %s", 2123 QDF_MAC_ADDR_ARRAY(peer->macaddr), 2124 vdev_id, 2125 qdf_atomic_read(&peer->peer_objmgr.ref_cnt), 2126 "TOTAL_REF_COUNT"); 2127 } 2128 #endif 2129 2130 void wlan_objmgr_psoc_check_for_peer_leaks(struct wlan_objmgr_psoc *psoc) 2131 { 2132 struct wlan_objmgr_psoc_objmgr *_psoc; 2133 struct wlan_objmgr_vdev *vdev; 2134 int vdev_id; 2135 uint32_t leaks = 0; 2136 2137 QDF_BUG(psoc); 2138 if (!psoc) 2139 return; 2140 2141 wlan_psoc_obj_lock(psoc); 2142 _psoc = &psoc->soc_objmgr; 2143 if (!_psoc->temp_peer_count && !_psoc->wlan_peer_count) { 2144 wlan_psoc_obj_unlock(psoc); 2145 return; 2146 } 2147 2148 obj_mgr_alert("objmgr peer leaks detected for psoc %u!", 2149 _psoc->psoc_id); 2150 obj_mgr_alert("----------------------------------------------------"); 2151 obj_mgr_alert("Peer MAC Vdev Id Refs Module"); 2152 obj_mgr_alert("----------------------------------------------------"); 2153 2154 wlan_objmgr_for_each_psoc_vdev(psoc, vdev_id, vdev) { 2155 struct wlan_objmgr_peer *peer; 2156 2157 wlan_vdev_obj_lock(vdev); 2158 wlan_objmgr_for_each_vdev_peer(vdev, peer) { 2159 wlan_peer_obj_lock(peer); 2160 leaks += qdf_atomic_read(&peer->peer_objmgr.ref_cnt); 2161 wlan_objmgr_print_peer_ref_leaks(peer, vdev_id); 2162 wlan_peer_obj_unlock(peer); 2163 } 2164 wlan_vdev_obj_unlock(vdev); 2165 } 2166 2167 QDF_DEBUG_PANIC("%u objmgr peer leaks detected for psoc %u!", 2168 leaks, _psoc->psoc_id); 2169 2170 wlan_psoc_obj_unlock(psoc); 2171 } 2172 qdf_export_symbol(wlan_objmgr_psoc_check_for_peer_leaks); 2173