1 /* 2 * Copyright (c) 2016 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_global_obj_i.h> 25 #include <wlan_objmgr_psoc_obj.h> 26 #include <wlan_objmgr_pdev_obj.h> 27 #include <wlan_objmgr_vdev_obj.h> 28 #include <wlan_objmgr_peer_obj.h> 29 #include <wlan_objmgr_psoc_obj_i.h> 30 #include <wlan_objmgr_pdev_obj_i.h> 31 #include <qdf_mem.h> 32 33 /** 34 ** APIs to Create/Delete Global object APIs 35 */ 36 static QDF_STATUS wlan_objmgr_psoc_object_status( 37 struct wlan_objmgr_psoc *psoc) 38 { 39 uint8_t id; 40 QDF_STATUS status = QDF_STATUS_SUCCESS; 41 42 wlan_psoc_obj_lock(psoc); 43 /* Iterate through all components to derive the object status */ 44 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 45 /* If component disabled, Ignore */ 46 if (psoc->obj_status[id] == QDF_STATUS_COMP_DISABLED) 47 continue; 48 /* If component operates in Async, status is Partially created, 49 break */ 50 else if (psoc->obj_status[id] == QDF_STATUS_COMP_ASYNC) { 51 if (psoc->soc_comp_obj[id] == NULL) { 52 status = QDF_STATUS_COMP_ASYNC; 53 break; 54 } 55 /* 56 * If component failed to allocate its object, treat it as 57 * failure, complete object need to be cleaned up 58 */ 59 } else if ((psoc->obj_status[id] == QDF_STATUS_E_NOMEM) || 60 (psoc->obj_status[id] == QDF_STATUS_E_FAILURE)) { 61 status = QDF_STATUS_E_FAILURE; 62 break; 63 } 64 } 65 wlan_psoc_obj_unlock(psoc); 66 return status; 67 } 68 69 static void wlan_objmgr_psoc_peer_list_init(struct wlan_peer_list *peer_list) 70 { 71 uint8_t i; 72 73 qdf_spinlock_create(&peer_list->peer_list_lock); 74 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) 75 qdf_list_create(&peer_list->peer_hash[i], 76 WLAN_UMAC_PSOC_MAX_PEERS); 77 } 78 79 static void wlan_objmgr_psoc_peer_list_deinit(struct wlan_peer_list *peer_list) 80 { 81 uint8_t i; 82 83 /* deinit the lock */ 84 qdf_spinlock_destroy(&peer_list->peer_list_lock); 85 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) 86 qdf_list_destroy(&peer_list->peer_hash[i]); 87 } 88 /* 89 * wlan_objmgr_psco_create_handler would return following status values 90 */ 91 struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, 92 WLAN_DEV_TYPE dev_type) 93 { 94 uint8_t id; 95 struct wlan_objmgr_psoc *psoc = NULL; 96 wlan_objmgr_psoc_create_handler handler; 97 wlan_objmgr_psoc_status_handler stat_handler; 98 struct wlan_objmgr_psoc_objmgr *objmgr; 99 QDF_STATUS obj_status; 100 void *arg; 101 102 /* Allocate PSOC object's memory */ 103 psoc = qdf_mem_malloc(sizeof(*psoc)); 104 if (psoc == NULL) { 105 qdf_print("%s: PSOC allocation failed\n", __func__); 106 return NULL; 107 } 108 /* Init spinlock */ 109 qdf_spinlock_create(&psoc->psoc_lock); 110 /* Initialize with default values */ 111 objmgr = &psoc->soc_objmgr; 112 objmgr->wlan_pdev_count = 0; 113 objmgr->wlan_vdev_count = 0; 114 objmgr->max_vdev_count = WLAN_UMAC_PSOC_MAX_VDEVS; 115 objmgr->wlan_peer_count = 0; 116 /* set phy version, dev_type in psoc */ 117 wlan_psoc_set_nif_phy_version(psoc, phy_version); 118 wlan_psoc_set_dev_type(psoc, dev_type); 119 /* Initialize peer list */ 120 wlan_objmgr_psoc_peer_list_init(&objmgr->peer_list); 121 /* Invoke registered create handlers */ 122 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 123 handler = g_umac_glb_obj->psoc_create_handler[id]; 124 arg = g_umac_glb_obj->psoc_create_handler_arg[id]; 125 if (handler != NULL) 126 psoc->obj_status[id] = handler(psoc, arg); 127 else 128 psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED; 129 } 130 /* Derive object status */ 131 obj_status = wlan_objmgr_psoc_object_status(psoc); 132 133 if (obj_status == QDF_STATUS_SUCCESS) { 134 /* Object status is SUCCESS, Object is created */ 135 psoc->obj_state = WLAN_OBJ_STATE_CREATED; 136 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 137 stat_handler = g_umac_glb_obj->psoc_status_handler[id]; 138 arg = g_umac_glb_obj->psoc_status_handler_arg[id]; 139 if (stat_handler != NULL) 140 stat_handler(psoc, arg, 141 QDF_STATUS_SUCCESS); 142 } 143 /* 144 * Few components operates in Asynchrous communction, Object state 145 * partially created 146 */ 147 } else if (obj_status == QDF_STATUS_COMP_ASYNC) { 148 psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 149 /* Component object failed to be created, clean up the object */ 150 } else if (obj_status == QDF_STATUS_E_FAILURE) { 151 qdf_print("%s: PSOC component objects allocation failed\n", 152 __func__); 153 /* Clean up the psoc */ 154 wlan_objmgr_psoc_obj_delete(psoc); 155 return NULL; 156 } 157 158 if (wlan_objmgr_psoc_object_attach(psoc) != 159 QDF_STATUS_SUCCESS) { 160 qdf_print("%s: PSOC object attach failed\n", __func__); 161 wlan_objmgr_psoc_obj_delete(psoc); 162 return NULL; 163 } 164 return psoc; 165 } 166 EXPORT_SYMBOL(wlan_objmgr_psoc_obj_create); 167 168 QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc) 169 { 170 uint8_t id; 171 wlan_objmgr_psoc_delete_handler handler; 172 QDF_STATUS obj_status; 173 void *arg; 174 175 /* if PSOC is NULL, return */ 176 if (psoc == NULL) { 177 qdf_print("%s:psoc is NULL\n", __func__); 178 return QDF_STATUS_E_FAILURE; 179 } 180 181 /* Invoke registered create handlers */ 182 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { 183 handler = g_umac_glb_obj->psoc_delete_handler[id]; 184 arg = g_umac_glb_obj->psoc_delete_handler_arg[id]; 185 if (handler != NULL) 186 psoc->obj_status[id] = handler(psoc, arg); 187 else 188 psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED; 189 } 190 /* Derive object status */ 191 obj_status = wlan_objmgr_psoc_object_status(psoc); 192 193 if (obj_status == QDF_STATUS_E_FAILURE) { 194 qdf_print("%s: PSOC component object free failed\n", __func__); 195 /* Ideally should not happen */ 196 /*This leads to memleak ??? how to handle */ 197 QDF_BUG(0); 198 return QDF_STATUS_E_FAILURE; 199 } 200 /* Deletion is in progress */ 201 if (obj_status == QDF_STATUS_COMP_ASYNC) { 202 psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; 203 return QDF_STATUS_COMP_ASYNC; 204 } else { 205 /* Detach PSOC from global object's psoc list */ 206 if (wlan_objmgr_psoc_object_detach(psoc) == 207 QDF_STATUS_E_FAILURE) { 208 qdf_print("%s: PSOC object detach failed\n", __func__); 209 return QDF_STATUS_E_FAILURE; 210 } 211 wlan_objmgr_psoc_peer_list_deinit(&psoc->soc_objmgr.peer_list); 212 /* Destroy spinlock */ 213 qdf_spinlock_destroy(&psoc->psoc_lock); 214 /* Free the memory */ 215 qdf_mem_free(psoc); 216 } 217 return QDF_STATUS_SUCCESS; 218 } 219 EXPORT_SYMBOL(wlan_objmgr_psoc_obj_delete); 220 221 /** 222 ** APIs to attach/detach component objects 223 */ 224 QDF_STATUS wlan_objmgr_psoc_component_obj_attach( 225 struct wlan_objmgr_psoc *psoc, 226 enum wlan_umac_comp_id id, 227 void *comp_objptr, 228 QDF_STATUS status) 229 { 230 wlan_objmgr_psoc_status_handler stat_handler; 231 void *arg = NULL; 232 QDF_STATUS obj_status; 233 uint8_t i; 234 235 /* component id is invalid */ 236 if (id >= WLAN_UMAC_MAX_COMPONENTS) 237 return QDF_STATUS_MAXCOMP_FAIL; 238 239 wlan_psoc_obj_lock(psoc); 240 /* If there is a valid entry, return failure */ 241 if (psoc->soc_comp_obj[id] != NULL) { 242 wlan_psoc_obj_unlock(psoc); 243 return QDF_STATUS_E_FAILURE; 244 } 245 /* Save component's pointer and status */ 246 psoc->soc_comp_obj[id] = comp_objptr; 247 psoc->obj_status[id] = status; 248 wlan_psoc_obj_unlock(psoc); 249 250 if (psoc->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) 251 return QDF_STATUS_SUCCESS; 252 /* If PSOC object status is partially created means, this API is 253 * invoked with differnt context, this block should be executed for 254 * async components only 255 */ 256 /* Derive status */ 257 obj_status = wlan_objmgr_psoc_object_status(psoc); 258 /* STATUS_SUCCESS means, object is CREATED */ 259 if (obj_status == QDF_STATUS_SUCCESS) 260 psoc->obj_state = WLAN_OBJ_STATE_CREATED; 261 /* update state as CREATION failed, caller has to delete the 262 * PSOC object 263 */ 264 else if (obj_status == QDF_STATUS_E_FAILURE) 265 psoc->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; 266 267 /* Notify components about the CREATION success/failure */ 268 if ((obj_status == QDF_STATUS_SUCCESS) || 269 (obj_status == QDF_STATUS_E_FAILURE)) { 270 /* nofity object status */ 271 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { 272 stat_handler = g_umac_glb_obj->psoc_status_handler[i]; 273 arg = g_umac_glb_obj->psoc_status_handler_arg[i]; 274 if (stat_handler != NULL) 275 stat_handler(psoc, arg, obj_status); 276 } 277 } 278 return QDF_STATUS_SUCCESS; 279 } 280 281 QDF_STATUS wlan_objmgr_psoc_component_obj_detach( 282 struct wlan_objmgr_psoc *psoc, 283 enum wlan_umac_comp_id id, 284 void *comp_objptr) 285 { 286 QDF_STATUS obj_status; 287 288 /* component id is invalid */ 289 if (id >= WLAN_UMAC_MAX_COMPONENTS) 290 return QDF_STATUS_MAXCOMP_FAIL; 291 292 wlan_psoc_obj_lock(psoc); 293 /* If there is a valid entry, return failure */ 294 if (psoc->soc_comp_obj[id] != comp_objptr) { 295 psoc->obj_status[id] = QDF_STATUS_E_FAILURE; 296 wlan_psoc_obj_unlock(psoc); 297 return QDF_STATUS_E_FAILURE; 298 } 299 /* Reset pointers to NULL, update the status*/ 300 psoc->soc_comp_obj[id] = NULL; 301 psoc->obj_status[id] = QDF_STATUS_SUCCESS; 302 wlan_psoc_obj_unlock(psoc); 303 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 if ((psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || 309 (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { 310 /* Derive object status */ 311 obj_status = wlan_objmgr_psoc_object_status(psoc); 312 if (obj_status == QDF_STATUS_SUCCESS) { 313 /* Update the status as Deleted, if full object 314 * deletion is in progress 315 */ 316 if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 317 psoc->obj_state = WLAN_OBJ_STATE_DELETED; 318 319 /* Move to creation state, since this component 320 * deletion alone requested 321 */ 322 if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 323 psoc->obj_state = WLAN_OBJ_STATE_CREATED; 324 /* Object status is failure */ 325 } else if (obj_status == QDF_STATUS_E_FAILURE) { 326 /* Update the status as Deletion failed, if full object 327 * deletion is in progress 328 */ 329 if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) 330 psoc->obj_state = 331 WLAN_OBJ_STATE_DELETION_FAILED; 332 333 /* Move to creation state, since this component 334 * deletion alone requested (do not block other 335 * components) 336 */ 337 if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) 338 psoc->obj_state = WLAN_OBJ_STATE_CREATED; 339 } 340 341 /* Delete psoc object */ 342 if ((obj_status == QDF_STATUS_SUCCESS) && 343 (psoc->obj_state == WLAN_OBJ_STATE_DELETED)) { 344 /* Detach PSOC from global object's psoc list */ 345 if (wlan_objmgr_psoc_object_detach(psoc) == 346 QDF_STATUS_E_FAILURE) 347 return QDF_STATUS_E_FAILURE; 348 349 wlan_objmgr_psoc_peer_list_deinit( 350 &psoc->soc_objmgr.peer_list); 351 /* Destroy spinlock */ 352 qdf_spinlock_destroy(&psoc->psoc_lock); 353 /* Free memory */ 354 qdf_mem_free(psoc); 355 } 356 } 357 return QDF_STATUS_SUCCESS; 358 } 359 360 /** 361 ** APIs to operations on psoc objects 362 */ 363 364 QDF_STATUS wlan_objmgr_iterate_obj_list( 365 struct wlan_objmgr_psoc *psoc, 366 enum wlan_objmgr_obj_type obj_type, 367 wlan_objmgr_op_handler handler, 368 void *arg, uint8_t lock_free_op) 369 { 370 uint16_t obj_id; 371 uint8_t i; 372 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 373 struct wlan_peer_list *peer_list; 374 qdf_list_t *obj_list; 375 struct wlan_objmgr_peer *peer; 376 struct wlan_objmgr_peer *peer_next; 377 378 /* If caller requests for lock free opeation, do not acquire, 379 * handler will handle the synchronization 380 */ 381 if (!lock_free_op) 382 wlan_psoc_obj_lock(psoc); 383 384 switch (obj_type) { 385 case WLAN_PDEV_OP: 386 /* Iterate through PDEV list, invoke handler for each pdev */ 387 for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) { 388 if (objmgr->wlan_pdev_list[obj_id] != NULL) { 389 /* TODO increment ref count */ 390 handler(psoc, 391 (void *)objmgr->wlan_pdev_list[obj_id], 392 arg); 393 /* TODO decrement ref count */ 394 } 395 } 396 break; 397 case WLAN_VDEV_OP: 398 /* Iterate through VDEV list, invoke handler for each vdev */ 399 for (obj_id = 0; obj_id < WLAN_UMAC_PSOC_MAX_VDEVS; obj_id++) { 400 if (objmgr->wlan_vdev_list[obj_id] != NULL) { 401 /* TODO increment ref count */ 402 handler(psoc, 403 (void *)objmgr->wlan_vdev_list[obj_id], 404 arg); 405 /* TODO decrement ref count */ 406 } 407 } 408 break; 409 case WLAN_PEER_OP: 410 /* Iterate through PEER list, invoke handler for each peer */ 411 peer_list = &objmgr->peer_list; 412 if (!lock_free_op) 413 qdf_spin_lock_bh(&peer_list->peer_list_lock); 414 /* Since peer list has sublist, iterate through sublists */ 415 for (i = 0; i < WLAN_PEER_HASHSIZE; i++) { 416 obj_list = &peer_list->peer_hash[i]; 417 peer = wlan_psoc_peer_list_peek_head(obj_list); 418 while (peer) { 419 /* Increment ref count, to hold the 420 peer pointer */ 421 wlan_objmgr_peer_ref_peer(peer); 422 handler(psoc, (void *)peer, arg); 423 /* Get next peer */ 424 peer_next = wlan_peer_get_next_peer_of_psoc( 425 obj_list, peer); 426 /* Decrement ref count, this can lead 427 to peer deletion also */ 428 wlan_objmgr_peer_unref_peer(peer); 429 peer = peer_next; 430 } 431 } 432 if (!lock_free_op) 433 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 434 break; 435 default: 436 break; 437 } 438 if (!lock_free_op) 439 wlan_psoc_obj_unlock(psoc); 440 return QDF_STATUS_SUCCESS; 441 } 442 443 void wlan_objmgr_psoc_peer_delete(struct wlan_objmgr_psoc *psoc, void *obj, 444 void *args) 445 { 446 struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj; 447 448 wlan_objmgr_peer_obj_delete(peer); 449 } 450 451 void wlan_objmgr_psoc_vdev_delete(struct wlan_objmgr_psoc *psoc, void *obj, 452 void *args) 453 { 454 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj; 455 456 wlan_objmgr_vdev_obj_delete(vdev); 457 } 458 459 void wlan_objmgr_psoc_pdev_delete(struct wlan_objmgr_psoc *psoc, void *obj, 460 void *args) 461 { 462 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; 463 464 wlan_objmgr_pdev_obj_delete(pdev); 465 } 466 467 QDF_STATUS wlan_objmgr_free_all_objects_per_psoc( 468 struct wlan_objmgr_psoc *psoc) 469 { 470 /* Free all peers */ 471 wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP, 472 wlan_objmgr_psoc_peer_delete, NULL, 1); 473 /* Free all vdevs */ 474 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 475 wlan_objmgr_psoc_vdev_delete, NULL, 1); 476 /* Free all PDEVs */ 477 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 478 wlan_objmgr_psoc_pdev_delete, NULL, 1); 479 return QDF_STATUS_SUCCESS; 480 } 481 482 QDF_STATUS wlan_objmgr_trigger_psoc_comp_object_creation( 483 struct wlan_objmgr_psoc *psoc, 484 enum wlan_umac_comp_id id) 485 { 486 wlan_objmgr_psoc_create_handler handler; 487 void *arg; 488 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 489 490 /* Component id is invalid */ 491 if (id >= WLAN_UMAC_MAX_COMPONENTS) 492 return QDF_STATUS_MAXCOMP_FAIL; 493 494 wlan_psoc_obj_lock(psoc); 495 /* If component object is already created, delete old 496 * component object, then invoke creation 497 */ 498 if (psoc->soc_comp_obj[id] != NULL) { 499 wlan_psoc_obj_unlock(psoc); 500 return QDF_STATUS_E_FAILURE; 501 } 502 wlan_psoc_obj_unlock(psoc); 503 /* Invoke registered create handlers */ 504 handler = g_umac_glb_obj->psoc_create_handler[id]; 505 arg = g_umac_glb_obj->psoc_create_handler_arg[id]; 506 if (handler != NULL) 507 psoc->obj_status[id] = handler(psoc, arg); 508 else 509 return QDF_STATUS_E_FAILURE; 510 511 /* If object status is created, then only handle this object status */ 512 if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) { 513 /* Derive object status */ 514 obj_status = wlan_objmgr_psoc_object_status(psoc); 515 /* Move PSOC object state to Partially created state */ 516 if (obj_status == QDF_STATUS_COMP_ASYNC) { 517 /*TODO atomic */ 518 psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; 519 } 520 } 521 return obj_status; 522 } 523 524 QDF_STATUS wlan_objmgr_trigger_psoc_comp_object_deletion( 525 struct wlan_objmgr_psoc *psoc, 526 enum wlan_umac_comp_id id) 527 { 528 wlan_objmgr_psoc_delete_handler handler; 529 void *arg; 530 QDF_STATUS obj_status = QDF_STATUS_SUCCESS; 531 532 /* component id is invalid */ 533 if (id >= WLAN_UMAC_MAX_COMPONENTS) 534 return QDF_STATUS_MAXCOMP_FAIL; 535 536 wlan_psoc_obj_lock(psoc); 537 /* Component object was never created, invalid operation */ 538 if (psoc->soc_comp_obj[id] == NULL) { 539 wlan_psoc_obj_unlock(psoc); 540 return QDF_STATUS_E_FAILURE; 541 } 542 wlan_psoc_obj_unlock(psoc); 543 /* Invoke registered create handlers */ 544 handler = g_umac_glb_obj->psoc_delete_handler[id]; 545 arg = g_umac_glb_obj->psoc_delete_handler_arg[id]; 546 if (handler != NULL) 547 psoc->obj_status[id] = handler(psoc, arg); 548 else 549 return QDF_STATUS_E_FAILURE; 550 551 /* If object status is created, then only handle this object status */ 552 if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) { 553 obj_status = wlan_objmgr_psoc_object_status(psoc); 554 /* move object state to DEL progress */ 555 if (obj_status == QDF_STATUS_COMP_ASYNC) 556 psoc->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; 557 } 558 return obj_status; 559 } 560 561 /* Util APIs */ 562 563 QDF_STATUS wlan_objmgr_psoc_pdev_attach(struct wlan_objmgr_psoc *psoc, 564 struct wlan_objmgr_pdev *pdev) 565 { 566 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 567 uint8_t id = 0; 568 QDF_STATUS status; 569 570 wlan_psoc_obj_lock(psoc); 571 /* 572 * Derive pdev id from pdev map 573 * First free pdev id is assigned 574 */ 575 while ((id < WLAN_UMAC_MAX_PDEVS) && 576 (objmgr->wlan_pdev_id_map & (1<<id))) 577 id++; 578 579 if (id == WLAN_UMAC_MAX_PDEVS) { 580 status = QDF_STATUS_E_FAILURE; 581 } else { 582 /* Update the map for reserving the id */ 583 objmgr->wlan_pdev_id_map |= (1<<id); 584 /* store pdev in pdev list */ 585 objmgr->wlan_pdev_list[id] = pdev; 586 /* Increment pdev count */ 587 objmgr->wlan_pdev_count++; 588 /* save pdev id */ 589 pdev->pdev_objmgr.wlan_pdev_id = id; 590 status = QDF_STATUS_SUCCESS; 591 } 592 wlan_psoc_obj_unlock(psoc); 593 return status; 594 } 595 596 QDF_STATUS wlan_objmgr_psoc_pdev_detach(struct wlan_objmgr_psoc *psoc, 597 struct wlan_objmgr_pdev *pdev) 598 { 599 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 600 uint8_t id; 601 602 id = pdev->pdev_objmgr.wlan_pdev_id; 603 /* If id is invalid, return */ 604 if (id >= WLAN_UMAC_MAX_PDEVS) 605 return QDF_STATUS_E_FAILURE; 606 607 wlan_psoc_obj_lock(psoc); 608 /* Free pdev id slot */ 609 objmgr->wlan_pdev_id_map &= ~(1<<id); 610 objmgr->wlan_pdev_list[id] = NULL; 611 objmgr->wlan_pdev_count--; 612 pdev->pdev_objmgr.wlan_pdev_id = 0xff; 613 wlan_psoc_obj_unlock(psoc); 614 615 return QDF_STATUS_E_FAILURE; 616 } 617 618 struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id( 619 struct wlan_objmgr_psoc *psoc, uint8_t id) 620 { 621 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 622 struct wlan_objmgr_pdev *pdev = NULL; 623 624 wlan_psoc_obj_lock(psoc); 625 /* get pdev from pdev list */ 626 pdev = objmgr->wlan_pdev_list[id]; 627 wlan_psoc_obj_unlock(psoc); 628 return pdev; 629 } 630 631 QDF_STATUS wlan_objmgr_psoc_vdev_attach(struct wlan_objmgr_psoc *psoc, 632 struct wlan_objmgr_vdev *vdev) 633 { 634 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 635 uint8_t id = 0; 636 uint8_t map_index = 0; 637 uint8_t map_entry_size = 32; 638 uint8_t adjust_ix = 0; 639 QDF_STATUS status; 640 641 wlan_psoc_obj_lock(psoc); 642 /* Find first free vdev id */ 643 while ((id < objmgr->max_vdev_count) && 644 (objmgr->wlan_vdev_id_map[map_index] & (1<<(id - adjust_ix)))) { 645 id++; 646 /* 647 * The map is two DWORDS(32 bits), so, map_index 648 * adjust_ix derived based on the id value 649 */ 650 if (id == ((map_index+1)*map_entry_size)) { 651 adjust_ix = map_index*map_entry_size; 652 map_index++; 653 } 654 } 655 /* If no free slot, return failure */ 656 if (id == objmgr->max_vdev_count) { 657 status = QDF_STATUS_E_FAILURE; 658 } else { 659 /* set free vdev id index */ 660 objmgr->wlan_vdev_id_map[map_index] |= (1<<(id-adjust_ix)); 661 /* store vdev pointer in vdev list */ 662 objmgr->wlan_vdev_list[id] = vdev; 663 /* increment vdev counter */ 664 objmgr->wlan_vdev_count++; 665 /* save vdev id */ 666 vdev->vdev_objmgr.vdev_id = id; 667 status = QDF_STATUS_SUCCESS; 668 } 669 wlan_psoc_obj_unlock(psoc); 670 return status; 671 } 672 673 QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc, 674 struct wlan_objmgr_vdev *vdev) 675 { 676 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 677 uint8_t id = 0; 678 uint8_t map_index = 0; 679 uint8_t map_entry_size = 32; 680 uint8_t adjust_ix = 0; 681 682 id = vdev->vdev_objmgr.vdev_id; 683 /* Invalid vdev id */ 684 if (id >= WLAN_UMAC_PSOC_MAX_VDEVS) 685 return QDF_STATUS_E_FAILURE; 686 /* 687 * Derive map_index and adjust_ix to find actual DWORD 688 * the id map is present 689 */ 690 while ((id - adjust_ix) >= map_entry_size) { 691 map_index++; 692 adjust_ix = map_index * map_entry_size; 693 } 694 wlan_psoc_obj_lock(psoc); 695 /* unset bit, to free the slot */ 696 objmgr->wlan_vdev_id_map[map_index] &= ~(1<<(id-adjust_ix)); 697 /* reset VDEV pointer to NULL in VDEV list array */ 698 objmgr->wlan_vdev_list[id] = NULL; 699 /* decrement vdev count */ 700 objmgr->wlan_vdev_count--; 701 vdev->vdev_objmgr.vdev_id = 0xff; 702 wlan_psoc_obj_unlock(psoc); 703 return QDF_STATUS_SUCCESS; 704 } 705 706 707 struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc( 708 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) 709 { 710 struct wlan_objmgr_vdev *vdev; 711 712 /* if PSOC is NULL, return */ 713 if (psoc == NULL) 714 return NULL; 715 /* vdev id is invalid */ 716 if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) 717 return NULL; 718 719 wlan_psoc_obj_lock(psoc); 720 /* retrieve vdev pointer from vdev list */ 721 vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; 722 wlan_psoc_obj_unlock(psoc); 723 return vdev; 724 } 725 726 struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc( 727 struct wlan_objmgr_psoc *psoc, uint8_t *macaddr) 728 { 729 struct wlan_objmgr_vdev *vdev; 730 uint8_t id; 731 732 /* if PSOC is NULL, return */ 733 if (psoc == NULL) 734 return NULL; 735 736 wlan_psoc_obj_lock(psoc); 737 /* Iterate through PSOC's vdev list */ 738 for (id = 0; id < WLAN_UMAC_PSOC_MAX_VDEVS; id++) { 739 vdev = psoc->soc_objmgr.wlan_vdev_list[id]; 740 if (vdev == NULL) 741 continue; 742 /* MAC address matches, break */ 743 if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) 744 == QDF_STATUS_SUCCESS) { 745 wlan_psoc_obj_unlock(psoc); 746 return vdev; 747 } 748 } 749 wlan_psoc_obj_unlock(psoc); 750 return NULL; 751 } 752 753 static void wlan_obj_psoc_peerlist_add_tail(qdf_list_t *obj_list, 754 struct wlan_objmgr_peer *obj) 755 { 756 qdf_list_insert_back(obj_list, &obj->psoc_peer); 757 } 758 759 static QDF_STATUS wlan_obj_psoc_peerlist_remove_peer( 760 qdf_list_t *obj_list, 761 struct wlan_objmgr_peer *peer) 762 { 763 qdf_list_node_t *psoc_node = NULL; 764 765 if (peer == NULL) 766 return QDF_STATUS_E_FAILURE; 767 /* get vdev list node element */ 768 psoc_node = &peer->psoc_peer; 769 /* list is empty, return failure */ 770 if (qdf_list_remove_node(obj_list, psoc_node) != QDF_STATUS_SUCCESS) 771 return QDF_STATUS_E_FAILURE; 772 773 return QDF_STATUS_SUCCESS; 774 } 775 776 struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( 777 qdf_list_t *obj_list, 778 uint8_t *macaddr) 779 { 780 struct wlan_objmgr_peer *peer; 781 struct wlan_objmgr_peer *peer_temp; 782 783 /* Iterate through hash list to get the peer */ 784 peer = wlan_psoc_peer_list_peek_head(obj_list); 785 while (peer != NULL) { 786 /* For peer, macaddr is key */ 787 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) 788 == QDF_STATUS_SUCCESS) { 789 /* Increment ref count for access */ 790 wlan_objmgr_peer_ref_peer(peer); 791 return peer; 792 } 793 /* Move to next peer */ 794 peer_temp = peer; 795 peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); 796 } 797 /* Not found, return NULL */ 798 return NULL; 799 } 800 801 QDF_STATUS wlan_objmgr_psoc_peer_attach(struct wlan_objmgr_psoc *psoc, 802 struct wlan_objmgr_peer *peer) 803 { 804 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 805 uint8_t hash_index; 806 807 wlan_psoc_obj_lock(psoc); 808 /* Max peer limit is reached, return failure */ 809 if (objmgr->wlan_peer_count > WLAN_UMAC_PSOC_MAX_PEERS) { 810 wlan_psoc_obj_unlock(psoc); 811 return QDF_STATUS_E_FAILURE; 812 } 813 /* Derive hash index from mac address */ 814 hash_index = WLAN_PEER_HASH(peer->macaddr); 815 /* add peer to hash peer list */ 816 wlan_obj_psoc_peerlist_add_tail( 817 &objmgr->peer_list.peer_hash[hash_index], 818 peer); 819 /* Increment peer count */ 820 objmgr->wlan_peer_count++; 821 822 wlan_psoc_obj_unlock(psoc); 823 return QDF_STATUS_SUCCESS; 824 } 825 826 QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc, 827 struct wlan_objmgr_peer *peer) 828 { 829 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 830 uint8_t hash_index; 831 832 wlan_psoc_obj_lock(psoc); 833 /* if list is empty, return */ 834 if (objmgr->wlan_peer_count == 0) { 835 wlan_psoc_obj_unlock(psoc); 836 return QDF_STATUS_E_FAILURE; 837 } 838 /* Get hash index, to locate the actual peer list */ 839 hash_index = WLAN_PEER_HASH(peer->macaddr); 840 /* removes the peer from peer_list */ 841 if (wlan_obj_psoc_peerlist_remove_peer( 842 &objmgr->peer_list.peer_hash[hash_index], 843 peer) == 844 QDF_STATUS_E_FAILURE) { 845 wlan_psoc_obj_unlock(psoc); 846 qdf_print("%s: Failed to detach peer\n", __func__); 847 return QDF_STATUS_E_FAILURE; 848 } 849 /* Decrement peer count */ 850 objmgr->wlan_peer_count--; 851 852 wlan_psoc_obj_unlock(psoc); 853 return QDF_STATUS_SUCCESS; 854 } 855 856 struct wlan_objmgr_peer *wlan_objmgr_find_peer( 857 struct wlan_objmgr_psoc *psoc, uint8_t *macaddr) 858 { 859 struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; 860 uint8_t hash_index; 861 struct wlan_objmgr_peer *peer = NULL; 862 struct wlan_peer_list *peer_list; 863 864 wlan_psoc_obj_lock(psoc); 865 /* List is empty, return NULL */ 866 if (objmgr->wlan_peer_count == 0) { 867 wlan_psoc_obj_unlock(psoc); 868 return NULL; 869 } 870 /* reduce the search window, with hash key */ 871 hash_index = WLAN_PEER_HASH(macaddr); 872 peer_list = &objmgr->peer_list; 873 qdf_spin_lock_bh(&peer_list->peer_list_lock); 874 /* Iterate through peer list, get peer */ 875 peer = wlan_obj_psoc_peerlist_get_peer( 876 &peer_list->peer_hash[hash_index], macaddr); 877 qdf_spin_unlock_bh(&peer_list->peer_list_lock); 878 wlan_psoc_obj_unlock(psoc); 879 return peer; 880 } 881