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