1 /* 2 * Copyright (c) 2016-2021 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_global_obj_i.h" 23 #include <wlan_objmgr_global_obj.h> 24 #include "wlan_objmgr_debug.h" 25 #include "wlan_objmgr_psoc_obj.h" 26 #include "qdf_mem.h" 27 #include <qdf_module.h> 28 29 /* Global object, it is declared globally */ 30 struct wlan_objmgr_global *g_umac_glb_obj; 31 32 qdf_export_symbol(g_umac_glb_obj); 33 34 /* 35 ** APIs to Create/Delete Global object APIs 36 */ 37 QDF_STATUS wlan_objmgr_global_obj_init(void) 38 { 39 struct wlan_objmgr_global *umac_global_obj; 40 41 /* If it is already created, ignore */ 42 if (g_umac_glb_obj) { 43 obj_mgr_err("Global object is already created"); 44 return QDF_STATUS_E_FAILURE; 45 } 46 47 /* Allocation of memory for Global object */ 48 umac_global_obj = (struct wlan_objmgr_global *)qdf_mem_malloc( 49 sizeof(*umac_global_obj)); 50 if (!umac_global_obj) 51 return QDF_STATUS_E_NOMEM; 52 53 /* Store Global object pointer in Global variable */ 54 g_umac_glb_obj = umac_global_obj; 55 /* Initialize spinlock */ 56 qdf_spinlock_create(&g_umac_glb_obj->global_lock); 57 wlan_objmgr_debug_info_init(); 58 59 return QDF_STATUS_SUCCESS; 60 } 61 qdf_export_symbol(wlan_objmgr_global_obj_init); 62 63 QDF_STATUS wlan_objmgr_global_obj_deinit(void) 64 { 65 /* If it is already destroyed */ 66 if (!g_umac_glb_obj) { 67 obj_mgr_err("Global object is not allocated"); 68 return QDF_STATUS_E_FAILURE; 69 } 70 71 wlan_objmgr_debug_info_deinit(); 72 73 if (QDF_STATUS_SUCCESS == wlan_objmgr_global_obj_can_destroyed()) { 74 qdf_spinlock_destroy(&g_umac_glb_obj->global_lock); 75 qdf_mem_free(g_umac_glb_obj); 76 g_umac_glb_obj = NULL; 77 } else { 78 obj_mgr_err("PSOCs are leaked can't free global objmgr ctx"); 79 WLAN_OBJMGR_BUG(0); 80 } 81 82 return QDF_STATUS_SUCCESS; 83 } 84 qdf_export_symbol(wlan_objmgr_global_obj_deinit); 85 86 /** 87 ** APIs to register/unregister handlers 88 */ 89 QDF_STATUS wlan_objmgr_register_psoc_create_handler( 90 enum wlan_umac_comp_id id, 91 wlan_objmgr_psoc_create_handler handler, 92 void *arg) 93 { 94 /* If id is not within valid range, return */ 95 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 96 obj_mgr_err("Component %d is out of range", id); 97 return QDF_STATUS_MAXCOMP_FAIL; 98 } 99 100 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 101 /* If there is a valid entry, return failure */ 102 if (g_umac_glb_obj->psoc_create_handler[id]) { 103 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 104 obj_mgr_err("Callback for comp %d is already registered", id); 105 QDF_ASSERT(0); 106 return QDF_STATUS_E_FAILURE; 107 } 108 /* Store handler and args in Global object table */ 109 g_umac_glb_obj->psoc_create_handler[id] = handler; 110 g_umac_glb_obj->psoc_create_handler_arg[id] = arg; 111 112 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 113 return QDF_STATUS_SUCCESS; 114 } 115 qdf_export_symbol(wlan_objmgr_register_psoc_create_handler); 116 117 QDF_STATUS wlan_objmgr_unregister_psoc_create_handler( 118 enum wlan_umac_comp_id id, 119 wlan_objmgr_psoc_create_handler handler, 120 void *arg) 121 { 122 /* If id is not within valid range, return */ 123 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 124 obj_mgr_err("Component %d is out of range", id); 125 return QDF_STATUS_MAXCOMP_FAIL; 126 } 127 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 128 /* If there is an invalid entry, return failure */ 129 if (g_umac_glb_obj->psoc_create_handler[id] != handler) { 130 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 131 obj_mgr_err("Callback for comp %d is not registered", id); 132 QDF_ASSERT(0); 133 return QDF_STATUS_E_FAILURE; 134 } 135 /* Reset handlers, and args to NULL */ 136 g_umac_glb_obj->psoc_create_handler[id] = NULL; 137 g_umac_glb_obj->psoc_create_handler_arg[id] = NULL; 138 139 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 140 return QDF_STATUS_SUCCESS; 141 } 142 qdf_export_symbol(wlan_objmgr_unregister_psoc_create_handler); 143 144 QDF_STATUS wlan_objmgr_register_psoc_destroy_handler( 145 enum wlan_umac_comp_id id, 146 wlan_objmgr_psoc_destroy_handler handler, 147 void *arg) 148 { 149 /* If id is not within valid range, return */ 150 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 151 obj_mgr_err("Component %d is out of range", id); 152 return QDF_STATUS_MAXCOMP_FAIL; 153 } 154 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 155 /* If there is a valid entry, return failure */ 156 if (g_umac_glb_obj->psoc_destroy_handler[id]) { 157 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 158 obj_mgr_err("Callback for comp %d is already registered", id); 159 QDF_ASSERT(0); 160 return QDF_STATUS_E_FAILURE; 161 } 162 /* Store handler and args in Global object table */ 163 g_umac_glb_obj->psoc_destroy_handler[id] = handler; 164 g_umac_glb_obj->psoc_destroy_handler_arg[id] = arg; 165 166 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 167 return QDF_STATUS_SUCCESS; 168 } 169 qdf_export_symbol(wlan_objmgr_register_psoc_destroy_handler); 170 171 QDF_STATUS wlan_objmgr_unregister_psoc_destroy_handler( 172 enum wlan_umac_comp_id id, 173 wlan_objmgr_psoc_destroy_handler handler, 174 void *arg) 175 { 176 /* If id is not within valid range, return */ 177 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 178 obj_mgr_err("Component %d is out of range", id); 179 return QDF_STATUS_MAXCOMP_FAIL; 180 } 181 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 182 /* If there is an invalid entry, return failure */ 183 if (g_umac_glb_obj->psoc_destroy_handler[id] != handler) { 184 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 185 obj_mgr_err("Callback for comp %d is not registered", id); 186 QDF_ASSERT(0); 187 return QDF_STATUS_E_FAILURE; 188 } 189 /* Reset handlers, and args to NULL */ 190 g_umac_glb_obj->psoc_destroy_handler[id] = NULL; 191 g_umac_glb_obj->psoc_destroy_handler_arg[id] = NULL; 192 193 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 194 return QDF_STATUS_SUCCESS; 195 } 196 qdf_export_symbol(wlan_objmgr_unregister_psoc_destroy_handler); 197 198 QDF_STATUS wlan_objmgr_register_psoc_status_handler( 199 enum wlan_umac_comp_id id, 200 wlan_objmgr_psoc_status_handler handler, 201 void *arg) 202 { 203 /* If id is not within valid range, return */ 204 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 205 obj_mgr_err("Component %d is out of range", id); 206 return QDF_STATUS_MAXCOMP_FAIL; 207 } 208 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 209 /* If there is a valid entry, return failure */ 210 if (g_umac_glb_obj->psoc_status_handler[id]) { 211 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 212 obj_mgr_err("Callback for comp %d is already registered", id); 213 return QDF_STATUS_E_FAILURE; 214 } 215 /* Store handler and args in Global object table */ 216 g_umac_glb_obj->psoc_status_handler[id] = handler; 217 g_umac_glb_obj->psoc_status_handler_arg[id] = arg; 218 219 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 220 return QDF_STATUS_SUCCESS; 221 } 222 223 QDF_STATUS wlan_objmgr_unregister_psoc_status_handler( 224 enum wlan_umac_comp_id id, 225 wlan_objmgr_psoc_status_handler handler, 226 void *arg) 227 { 228 /* If id is not within valid range, return */ 229 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 230 obj_mgr_err("Component %d is out of range", id); 231 return QDF_STATUS_MAXCOMP_FAIL; 232 } 233 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 234 /* If there is an invalid entry, return failure */ 235 if (g_umac_glb_obj->psoc_status_handler[id] != handler) { 236 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 237 obj_mgr_err("Callback for comp %d is not registered", id); 238 return QDF_STATUS_E_FAILURE; 239 } 240 /* Reset handlers, and args to NULL */ 241 g_umac_glb_obj->psoc_status_handler[id] = NULL; 242 g_umac_glb_obj->psoc_status_handler_arg[id] = NULL; 243 244 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 245 return QDF_STATUS_SUCCESS; 246 } 247 248 249 QDF_STATUS wlan_objmgr_register_pdev_create_handler( 250 enum wlan_umac_comp_id id, 251 wlan_objmgr_pdev_create_handler handler, 252 void *arg) 253 { 254 /* If id is not within valid range, return */ 255 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 256 obj_mgr_err("Component %d is out of range", id); 257 return QDF_STATUS_MAXCOMP_FAIL; 258 } 259 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 260 /* If there is a valid entry, return failure */ 261 if (g_umac_glb_obj->pdev_create_handler[id]) { 262 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 263 obj_mgr_err("Callback for comp %d is already registered", id); 264 QDF_ASSERT(0); 265 return QDF_STATUS_E_FAILURE; 266 } 267 /* Store handler and args in Global object table */ 268 g_umac_glb_obj->pdev_create_handler[id] = handler; 269 g_umac_glb_obj->pdev_create_handler_arg[id] = arg; 270 271 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 272 return QDF_STATUS_SUCCESS; 273 } 274 qdf_export_symbol(wlan_objmgr_register_pdev_create_handler); 275 276 QDF_STATUS wlan_objmgr_unregister_pdev_create_handler( 277 enum wlan_umac_comp_id id, 278 wlan_objmgr_pdev_create_handler handler, 279 void *arg) 280 { 281 /* If id is not within valid range, return */ 282 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 283 obj_mgr_err("Component %d is out of range", id); 284 return QDF_STATUS_MAXCOMP_FAIL; 285 } 286 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 287 /* If there is an invalid entry, return failure */ 288 if (g_umac_glb_obj->pdev_create_handler[id] != handler) { 289 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 290 obj_mgr_err("Callback for comp %d is not registered", id); 291 QDF_ASSERT(0); 292 return QDF_STATUS_E_FAILURE; 293 } 294 /* Reset handlers, and args to NULL */ 295 g_umac_glb_obj->pdev_create_handler[id] = NULL; 296 g_umac_glb_obj->pdev_create_handler_arg[id] = NULL; 297 298 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 299 return QDF_STATUS_SUCCESS; 300 } 301 qdf_export_symbol(wlan_objmgr_unregister_pdev_create_handler); 302 303 QDF_STATUS wlan_objmgr_register_pdev_destroy_handler( 304 enum wlan_umac_comp_id id, 305 wlan_objmgr_pdev_destroy_handler handler, 306 void *arg) 307 { 308 /* If id is not within valid range, return */ 309 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 310 obj_mgr_err("Component %d is out of range", id); 311 return QDF_STATUS_MAXCOMP_FAIL; 312 } 313 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 314 /* If there is a valid entry, return failure */ 315 if (g_umac_glb_obj->pdev_destroy_handler[id]) { 316 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 317 obj_mgr_err("Callback for comp %d is already registered", id); 318 QDF_ASSERT(0); 319 return QDF_STATUS_E_FAILURE; 320 } 321 /* Store handler and args in Global object table */ 322 g_umac_glb_obj->pdev_destroy_handler[id] = handler; 323 g_umac_glb_obj->pdev_destroy_handler_arg[id] = arg; 324 325 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 326 return QDF_STATUS_SUCCESS; 327 } 328 qdf_export_symbol(wlan_objmgr_register_pdev_destroy_handler); 329 330 QDF_STATUS wlan_objmgr_unregister_pdev_destroy_handler( 331 enum wlan_umac_comp_id id, 332 wlan_objmgr_pdev_destroy_handler handler, 333 void *arg) 334 { 335 /* If id is not within valid range, return */ 336 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 337 obj_mgr_err("Component %d is out of range", id); 338 return QDF_STATUS_MAXCOMP_FAIL; 339 } 340 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 341 /* If there is an invalid entry, return failure */ 342 if (g_umac_glb_obj->pdev_destroy_handler[id] != handler) { 343 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 344 obj_mgr_err("Callback for Component %d is not registered", id); 345 QDF_ASSERT(0); 346 return QDF_STATUS_E_FAILURE; 347 } 348 /* Reset handlers, and args to NULL */ 349 g_umac_glb_obj->pdev_destroy_handler[id] = NULL; 350 g_umac_glb_obj->pdev_destroy_handler_arg[id] = NULL; 351 352 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 353 return QDF_STATUS_SUCCESS; 354 } 355 qdf_export_symbol(wlan_objmgr_unregister_pdev_destroy_handler); 356 357 QDF_STATUS wlan_objmgr_register_pdev_status_handler( 358 enum wlan_umac_comp_id id, 359 wlan_objmgr_pdev_status_handler handler, 360 void *arg) 361 { 362 /* If id is not within valid range, return */ 363 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 364 obj_mgr_err("Component %d is out of range", id); 365 return QDF_STATUS_MAXCOMP_FAIL; 366 } 367 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 368 /* If there is a valid entry, return failure */ 369 if (g_umac_glb_obj->pdev_status_handler[id]) { 370 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 371 obj_mgr_err("Callback for comp %d is already registered", id); 372 return QDF_STATUS_E_FAILURE; 373 } 374 /* Store handler and args in Global object table */ 375 g_umac_glb_obj->pdev_status_handler[id] = handler; 376 g_umac_glb_obj->pdev_status_handler_arg[id] = arg; 377 378 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 379 return QDF_STATUS_SUCCESS; 380 } 381 382 QDF_STATUS wlan_objmgr_unregister_pdev_status_handler( 383 enum wlan_umac_comp_id id, 384 wlan_objmgr_pdev_status_handler handler, 385 void *arg) 386 { 387 /* If id is not within valid range, return */ 388 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 389 obj_mgr_err("Component %d is out of range", id); 390 return QDF_STATUS_MAXCOMP_FAIL; 391 } 392 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 393 /* If there is an invalid entry, return failure */ 394 if (g_umac_glb_obj->pdev_status_handler[id] != handler) { 395 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 396 obj_mgr_err("Callback for Component %d is not registered", id); 397 return QDF_STATUS_E_FAILURE; 398 } 399 /* Reset handlers, and args to NULL */ 400 g_umac_glb_obj->pdev_status_handler[id] = NULL; 401 g_umac_glb_obj->pdev_status_handler_arg[id] = NULL; 402 403 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 404 return QDF_STATUS_SUCCESS; 405 } 406 407 408 QDF_STATUS wlan_objmgr_register_vdev_create_handler( 409 enum wlan_umac_comp_id id, 410 wlan_objmgr_vdev_create_handler handler, 411 void *arg) 412 { 413 /* If id is not within valid range, return */ 414 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 415 obj_mgr_err("Component %d is out of range", id); 416 return QDF_STATUS_MAXCOMP_FAIL; 417 } 418 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 419 /* If there is a valid entry, return failure */ 420 if (g_umac_glb_obj->vdev_create_handler[id]) { 421 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 422 obj_mgr_err("Callback for comp %d is already registered", id); 423 QDF_ASSERT(0); 424 return QDF_STATUS_E_FAILURE; 425 } 426 /* Store handler and args in Global object table */ 427 g_umac_glb_obj->vdev_create_handler[id] = handler; 428 g_umac_glb_obj->vdev_create_handler_arg[id] = arg; 429 430 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 431 return QDF_STATUS_SUCCESS; 432 } 433 qdf_export_symbol(wlan_objmgr_register_vdev_create_handler); 434 435 QDF_STATUS wlan_objmgr_unregister_vdev_create_handler( 436 enum wlan_umac_comp_id id, 437 wlan_objmgr_vdev_create_handler handler, 438 void *arg) 439 { 440 /* If id is not within valid range, return */ 441 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 442 obj_mgr_err("Component %d is out of range", id); 443 return QDF_STATUS_MAXCOMP_FAIL; 444 } 445 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 446 /* If there is an invalid entry, return failure */ 447 if (g_umac_glb_obj->vdev_create_handler[id] != handler) { 448 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 449 obj_mgr_err("Callback for comp %d is not registered", id); 450 QDF_ASSERT(0); 451 return QDF_STATUS_E_FAILURE; 452 } 453 /* Reset handlers, and args to NULL */ 454 g_umac_glb_obj->vdev_create_handler[id] = NULL; 455 g_umac_glb_obj->vdev_create_handler_arg[id] = NULL; 456 457 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 458 return QDF_STATUS_SUCCESS; 459 } 460 qdf_export_symbol(wlan_objmgr_unregister_vdev_create_handler); 461 462 QDF_STATUS wlan_objmgr_register_vdev_destroy_handler( 463 enum wlan_umac_comp_id id, 464 wlan_objmgr_vdev_destroy_handler handler, 465 void *arg) 466 { 467 /* If id is not within valid range, return */ 468 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 469 obj_mgr_err("Component %d is out of range", id); 470 return QDF_STATUS_MAXCOMP_FAIL; 471 } 472 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 473 /* If there is a valid entry, return failure */ 474 if (g_umac_glb_obj->vdev_destroy_handler[id]) { 475 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 476 obj_mgr_err("Callback for comp %d is already registered", id); 477 QDF_ASSERT(0); 478 return QDF_STATUS_E_FAILURE; 479 } 480 /* Store handler and args in Global object table */ 481 g_umac_glb_obj->vdev_destroy_handler[id] = handler; 482 g_umac_glb_obj->vdev_destroy_handler_arg[id] = arg; 483 484 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 485 return QDF_STATUS_SUCCESS; 486 } 487 qdf_export_symbol(wlan_objmgr_register_vdev_destroy_handler); 488 489 QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler( 490 enum wlan_umac_comp_id id, 491 wlan_objmgr_vdev_destroy_handler handler, 492 void *arg) 493 { 494 /* If id is not within valid range, return */ 495 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 496 obj_mgr_err("Component %d is out of range", id); 497 return QDF_STATUS_MAXCOMP_FAIL; 498 } 499 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 500 /* If there is an invalid entry, return failure */ 501 if (g_umac_glb_obj->vdev_destroy_handler[id] != handler) { 502 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 503 obj_mgr_err("Callback for comp %d is not registered", id); 504 QDF_ASSERT(0); 505 return QDF_STATUS_E_FAILURE; 506 } 507 /* Reset handlers, and args to NULL */ 508 g_umac_glb_obj->vdev_destroy_handler[id] = NULL; 509 g_umac_glb_obj->vdev_destroy_handler_arg[id] = NULL; 510 511 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 512 return QDF_STATUS_SUCCESS; 513 } 514 qdf_export_symbol(wlan_objmgr_unregister_vdev_destroy_handler); 515 516 QDF_STATUS wlan_objmgr_register_vdev_status_handler( 517 enum wlan_umac_comp_id id, 518 wlan_objmgr_vdev_status_handler handler, 519 void *arg) 520 { 521 /* If id is not within valid range, return */ 522 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 523 obj_mgr_err("Component %d is out of range", id); 524 return QDF_STATUS_MAXCOMP_FAIL; 525 } 526 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 527 /* If there is a valid entry, return failure */ 528 if (g_umac_glb_obj->vdev_status_handler[id]) { 529 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 530 obj_mgr_err("Callback for comp %d is already registered", id); 531 return QDF_STATUS_E_FAILURE; 532 } 533 /* Store handler and args in Global object table */ 534 g_umac_glb_obj->vdev_status_handler[id] = handler; 535 g_umac_glb_obj->vdev_status_handler_arg[id] = arg; 536 537 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 538 return QDF_STATUS_SUCCESS; 539 } 540 541 QDF_STATUS wlan_objmgr_unregister_vdev_status_handler( 542 enum wlan_umac_comp_id id, 543 wlan_objmgr_vdev_status_handler handler, 544 void *arg) 545 { 546 /* If id is not within valid range, return */ 547 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 548 obj_mgr_err("Component %d is out of range", id); 549 return QDF_STATUS_MAXCOMP_FAIL; 550 } 551 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 552 /* If there is an invalid entry, return failure */ 553 if (g_umac_glb_obj->vdev_status_handler[id] != handler) { 554 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 555 obj_mgr_err("Callback for Component %d is not registered", id); 556 return QDF_STATUS_E_FAILURE; 557 } 558 /* Reset handlers, and args to NULL */ 559 g_umac_glb_obj->vdev_status_handler[id] = NULL; 560 g_umac_glb_obj->vdev_status_handler_arg[id] = NULL; 561 562 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 563 return QDF_STATUS_SUCCESS; 564 } 565 566 QDF_STATUS wlan_objmgr_register_vdev_peer_free_notify_handler( 567 enum wlan_umac_comp_id id, 568 wlan_objmgr_vdev_peer_free_notify_handler handler) 569 { 570 /* If id is not within valid range, return */ 571 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 572 obj_mgr_err("Component %d is out of range", id); 573 WLAN_OBJMGR_BUG(0); 574 return QDF_STATUS_MAXCOMP_FAIL; 575 } 576 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 577 /* If there is a valid entry, return failure */ 578 if (g_umac_glb_obj->vdev_peer_free_notify_handler[id]) { 579 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 580 obj_mgr_err("Callback for comp %d is already registered", id); 581 return QDF_STATUS_E_FAILURE; 582 } 583 /* Store handler in Global object table */ 584 g_umac_glb_obj->vdev_peer_free_notify_handler[id] = handler; 585 586 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 587 588 return QDF_STATUS_SUCCESS; 589 } 590 591 QDF_STATUS wlan_objmgr_unregister_vdev_peer_free_notify_handler( 592 enum wlan_umac_comp_id id, 593 wlan_objmgr_vdev_peer_free_notify_handler handler) 594 { 595 /* If id is not within valid range, return */ 596 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 597 obj_mgr_err("Component %d is out of range", id); 598 WLAN_OBJMGR_BUG(0); 599 return QDF_STATUS_MAXCOMP_FAIL; 600 } 601 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 602 /* If there is an invalid entry, return failure */ 603 if (g_umac_glb_obj->vdev_peer_free_notify_handler[id] != handler) { 604 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 605 obj_mgr_err("Callback for Component %d is not registered", id); 606 return QDF_STATUS_E_FAILURE; 607 } 608 /* Reset handlers to NULL */ 609 g_umac_glb_obj->vdev_peer_free_notify_handler[id] = NULL; 610 611 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 612 613 return QDF_STATUS_SUCCESS; 614 } 615 616 QDF_STATUS wlan_objmgr_register_peer_create_handler( 617 enum wlan_umac_comp_id id, 618 wlan_objmgr_peer_create_handler handler, 619 void *arg) 620 { 621 /* If id is not within valid range, return */ 622 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 623 obj_mgr_err("Component %d is out of range", id); 624 return QDF_STATUS_MAXCOMP_FAIL; 625 } 626 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 627 /* If there is a valid entry, return failure */ 628 if (g_umac_glb_obj->peer_create_handler[id]) { 629 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 630 obj_mgr_err("Callback for comp %d is already registered", id); 631 QDF_ASSERT(0); 632 return QDF_STATUS_E_FAILURE; 633 } 634 /* Store handler and args in Global object table */ 635 g_umac_glb_obj->peer_create_handler[id] = handler; 636 g_umac_glb_obj->peer_create_handler_arg[id] = arg; 637 638 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 639 return QDF_STATUS_SUCCESS; 640 } 641 642 643 QDF_STATUS wlan_objmgr_unregister_peer_create_handler( 644 enum wlan_umac_comp_id id, 645 wlan_objmgr_peer_create_handler handler, 646 void *arg) 647 { 648 /* If id is not within valid range, return */ 649 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 650 obj_mgr_err("Component %d is out of range", id); 651 return QDF_STATUS_MAXCOMP_FAIL; 652 } 653 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 654 /* If there is an invalid entry, return failure */ 655 if (g_umac_glb_obj->peer_create_handler[id] != handler) { 656 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 657 obj_mgr_err("Callback for comp %d is not registered", id); 658 QDF_ASSERT(0); 659 return QDF_STATUS_E_FAILURE; 660 } 661 /* Reset handlers, and args to NULL */ 662 g_umac_glb_obj->peer_create_handler[id] = NULL; 663 g_umac_glb_obj->peer_create_handler_arg[id] = NULL; 664 665 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 666 return QDF_STATUS_SUCCESS; 667 } 668 669 QDF_STATUS wlan_objmgr_register_peer_destroy_handler( 670 enum wlan_umac_comp_id id, 671 wlan_objmgr_peer_destroy_handler handler, 672 void *arg) 673 { 674 /* If id is not within valid range, return */ 675 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 676 obj_mgr_err("Component %d is out of range", id); 677 return QDF_STATUS_MAXCOMP_FAIL; 678 } 679 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 680 /* If there is a valid entry, return failure */ 681 if (g_umac_glb_obj->peer_destroy_handler[id]) { 682 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 683 obj_mgr_err("Callback for comp %d is already registered", id); 684 QDF_ASSERT(0); 685 return QDF_STATUS_E_FAILURE; 686 } 687 /* Store handler and args in Global object table */ 688 g_umac_glb_obj->peer_destroy_handler[id] = handler; 689 g_umac_glb_obj->peer_destroy_handler_arg[id] = arg; 690 691 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 692 return QDF_STATUS_SUCCESS; 693 } 694 695 QDF_STATUS wlan_objmgr_unregister_peer_destroy_handler( 696 enum wlan_umac_comp_id id, 697 wlan_objmgr_peer_destroy_handler handler, 698 void *arg) 699 { 700 /* If id is not within valid range, return */ 701 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 702 obj_mgr_err("Component %d is out of range", id); 703 return QDF_STATUS_MAXCOMP_FAIL; 704 } 705 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 706 /* If there is an invalid entry, return failure */ 707 if (g_umac_glb_obj->peer_destroy_handler[id] != handler) { 708 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 709 obj_mgr_err("Callback for comp %d is not registered", id); 710 QDF_ASSERT(0); 711 return QDF_STATUS_E_FAILURE; 712 } 713 /* Reset handlers, and args to NULL */ 714 g_umac_glb_obj->peer_destroy_handler[id] = NULL; 715 g_umac_glb_obj->peer_destroy_handler_arg[id] = NULL; 716 717 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 718 return QDF_STATUS_SUCCESS; 719 } 720 721 QDF_STATUS wlan_objmgr_register_peer_status_handler( 722 enum wlan_umac_comp_id id, 723 wlan_objmgr_peer_status_handler handler, 724 void *arg) 725 { 726 /* If id is not within valid range, return */ 727 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 728 obj_mgr_err("Component %d is out of range", id); 729 return QDF_STATUS_MAXCOMP_FAIL; 730 } 731 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 732 /* If there is a valid entry, return failure */ 733 if (g_umac_glb_obj->peer_status_handler[id]) { 734 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 735 obj_mgr_err("Callback for comp %d is already registered", id); 736 return QDF_STATUS_E_FAILURE; 737 } 738 /* Store handler and args in Global object table */ 739 g_umac_glb_obj->peer_status_handler[id] = handler; 740 g_umac_glb_obj->peer_status_handler_arg[id] = arg; 741 742 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 743 return QDF_STATUS_SUCCESS; 744 } 745 746 QDF_STATUS wlan_objmgr_unregister_peer_status_handler( 747 enum wlan_umac_comp_id id, 748 wlan_objmgr_peer_status_handler handler, 749 void *arg) 750 { 751 /* If id is not within valid range, return */ 752 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 753 obj_mgr_err("Component %d is out of range", id); 754 return QDF_STATUS_MAXCOMP_FAIL; 755 } 756 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 757 /* If there is an invalid entry, return failure */ 758 if (g_umac_glb_obj->peer_status_handler[id] != handler) { 759 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 760 obj_mgr_err("Callback for comp %d is not registered", id); 761 return QDF_STATUS_E_FAILURE; 762 } 763 /* Reset handlers, and args to NULL */ 764 g_umac_glb_obj->peer_status_handler[id] = NULL; 765 g_umac_glb_obj->peer_status_handler_arg[id] = NULL; 766 767 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 768 return QDF_STATUS_SUCCESS; 769 } 770 771 QDF_STATUS wlan_objmgr_psoc_object_attach(struct wlan_objmgr_psoc *psoc) 772 { 773 uint8_t index = 0; 774 QDF_STATUS status = QDF_STATUS_E_FAILURE; 775 776 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 777 /* Find free slot in PSOC table, store the PSOC */ 778 while (index < WLAN_OBJMGR_MAX_DEVICES) { 779 if (!g_umac_glb_obj->psoc[index]) { 780 /* Found free slot, store psoc */ 781 g_umac_glb_obj->psoc[index] = psoc; 782 psoc->soc_objmgr.psoc_id = index; 783 status = QDF_STATUS_SUCCESS; 784 break; 785 } 786 index++; 787 } 788 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 789 return status; 790 } 791 792 QDF_STATUS wlan_objmgr_psoc_object_detach(struct wlan_objmgr_psoc *psoc) 793 { 794 uint8_t psoc_id; 795 796 psoc_id = psoc->soc_objmgr.psoc_id; 797 QDF_BUG(psoc_id < WLAN_OBJMGR_MAX_DEVICES); 798 if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES) 799 return QDF_STATUS_E_INVAL; 800 801 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 802 g_umac_glb_obj->psoc[psoc_id] = NULL; 803 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 804 805 return QDF_STATUS_SUCCESS; 806 } 807 808 QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void) 809 { 810 uint8_t index = 0; 811 QDF_STATUS status = QDF_STATUS_SUCCESS; 812 813 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 814 /* Check whether all PSOCs are freed */ 815 while (index < WLAN_OBJMGR_MAX_DEVICES) { 816 if (g_umac_glb_obj->psoc[index]) { 817 status = QDF_STATUS_E_FAILURE; 818 break; 819 } 820 index++; 821 } 822 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 823 824 return status; 825 } 826 qdf_export_symbol(wlan_objmgr_global_obj_can_destroyed); 827 828 void wlan_objmgr_print_ref_ids(qdf_atomic_t *id, 829 QDF_TRACE_LEVEL log_level) 830 { 831 uint32_t i; 832 uint32_t pending_ref; 833 834 obj_mgr_log_level(log_level, "Pending references of object"); 835 for (i = 0; i < WLAN_REF_ID_MAX; i++) { 836 pending_ref = qdf_atomic_read(&id[i]); 837 if (pending_ref) 838 obj_mgr_log_level(log_level, "%s -- %d", 839 string_from_dbgid(i), pending_ref); 840 } 841 842 return; 843 } 844 845 QDF_STATUS wlan_objmgr_iterate_psoc_list( 846 wlan_objmgr_psoc_handler handler, 847 void *arg, wlan_objmgr_ref_dbgid dbg_id) 848 { 849 uint8_t index = 0; 850 851 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 852 853 while (index < WLAN_OBJMGR_MAX_DEVICES) { 854 if (g_umac_glb_obj->psoc[index]) { 855 handler((void *)g_umac_glb_obj->psoc[index], 856 arg, index); 857 } 858 index++; 859 } 860 861 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 862 863 return QDF_STATUS_SUCCESS; 864 } 865 866 qdf_export_symbol(wlan_objmgr_iterate_psoc_list); 867 868 #ifdef WLAN_FEATURE_11BE_MLO 869 struct mlo_mgr_context *wlan_objmgr_get_mlo_ctx(void) 870 { 871 return g_umac_glb_obj->mlo_ctx; 872 } 873 874 void wlan_objmgr_set_mlo_ctx(struct mlo_mgr_context *ctx) 875 { 876 g_umac_glb_obj->mlo_ctx = ctx; 877 } 878 #endif 879