1 /* 2 * Copyright (c) 2016-2017 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 "qdf_mem.h" 25 26 /* Global object, it is declared globally */ 27 struct wlan_objmgr_global *g_umac_glb_obj; 28 /* Component Name table */ 29 const char *wlan_umac_Component_name[] = { 30 "MLME", 31 "SCAN_MGR", 32 "SCAN_CACHE", 33 "MGMT_TXRX", 34 "", 35 }; 36 /* 37 ** APIs to Create/Delete Global object APIs 38 */ 39 QDF_STATUS wlan_objmgr_global_obj_init(void) 40 { 41 struct wlan_objmgr_global *umac_global_obj; 42 43 /* If it is already created, ignore */ 44 if (g_umac_glb_obj != NULL) { 45 obj_mgr_err("Global object is already created"); 46 return QDF_STATUS_E_FAILURE; 47 } 48 49 /* Allocation of memory for Global object */ 50 umac_global_obj = (struct wlan_objmgr_global *)qdf_mem_malloc( 51 sizeof(*umac_global_obj)); 52 if (umac_global_obj == NULL) { 53 obj_mgr_err("Global object alloc failed due to malloc"); 54 return QDF_STATUS_E_NOMEM; 55 } 56 /* Store Global object pointer in Global variable */ 57 g_umac_glb_obj = umac_global_obj; 58 /* Initialize spinlock */ 59 qdf_spinlock_create(&g_umac_glb_obj->global_lock); 60 61 return QDF_STATUS_SUCCESS; 62 } 63 EXPORT_SYMBOL(wlan_objmgr_global_obj_init); 64 65 QDF_STATUS wlan_objmgr_global_obj_deinit(void) 66 { 67 /* If it is already destroyed */ 68 if (g_umac_glb_obj == NULL) { 69 obj_mgr_err("Global object is not allocated"); 70 return QDF_STATUS_E_FAILURE; 71 } 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 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] != NULL) { 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 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 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] != NULL) { 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 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 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] != NULL) { 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] != NULL) { 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 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 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] != NULL) { 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 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 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] != NULL) { 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] != NULL) { 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 434 QDF_STATUS wlan_objmgr_unregister_vdev_create_handler( 435 enum wlan_umac_comp_id id, 436 wlan_objmgr_vdev_create_handler handler, 437 void *arg) 438 { 439 /* If id is not within valid range, return */ 440 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 441 obj_mgr_err("Component %d is out of range", id); 442 return QDF_STATUS_MAXCOMP_FAIL; 443 } 444 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 445 /* If there is an invalid entry, return failure */ 446 if (g_umac_glb_obj->vdev_create_handler[id] != handler) { 447 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 448 obj_mgr_err("Callback for comp %d is not registered", id); 449 QDF_ASSERT(0); 450 return QDF_STATUS_E_FAILURE; 451 } 452 /* Reset handlers, and args to NULL */ 453 g_umac_glb_obj->vdev_create_handler[id] = NULL; 454 g_umac_glb_obj->vdev_create_handler_arg[id] = NULL; 455 456 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 457 return QDF_STATUS_SUCCESS; 458 } 459 460 QDF_STATUS wlan_objmgr_register_vdev_destroy_handler( 461 enum wlan_umac_comp_id id, 462 wlan_objmgr_vdev_destroy_handler handler, 463 void *arg) 464 { 465 /* If id is not within valid range, return */ 466 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 467 obj_mgr_err("Component %d is out of range", id); 468 return QDF_STATUS_MAXCOMP_FAIL; 469 } 470 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 471 /* If there is a valid entry, return failure */ 472 if (g_umac_glb_obj->vdev_destroy_handler[id] != NULL) { 473 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 474 obj_mgr_err("Callback for comp %d is already registered", id); 475 QDF_ASSERT(0); 476 return QDF_STATUS_E_FAILURE; 477 } 478 /* Store handler and args in Global object table */ 479 g_umac_glb_obj->vdev_destroy_handler[id] = handler; 480 g_umac_glb_obj->vdev_destroy_handler_arg[id] = arg; 481 482 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 483 return QDF_STATUS_SUCCESS; 484 } 485 486 QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler( 487 enum wlan_umac_comp_id id, 488 wlan_objmgr_vdev_destroy_handler handler, 489 void *arg) 490 { 491 /* If id is not within valid range, return */ 492 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 493 obj_mgr_err("Component %d is out of range", id); 494 return QDF_STATUS_MAXCOMP_FAIL; 495 } 496 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 497 /* If there is an invalid entry, return failure */ 498 if (g_umac_glb_obj->vdev_destroy_handler[id] != handler) { 499 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 500 obj_mgr_err("Callback for comp %d is not registered", id); 501 QDF_ASSERT(0); 502 return QDF_STATUS_E_FAILURE; 503 } 504 /* Reset handlers, and args to NULL */ 505 g_umac_glb_obj->vdev_destroy_handler[id] = NULL; 506 g_umac_glb_obj->vdev_destroy_handler_arg[id] = NULL; 507 508 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 509 return QDF_STATUS_SUCCESS; 510 } 511 512 QDF_STATUS wlan_objmgr_register_vdev_status_handler( 513 enum wlan_umac_comp_id id, 514 wlan_objmgr_vdev_status_handler handler, 515 void *arg) 516 { 517 /* If id is not within valid range, return */ 518 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 519 obj_mgr_err("Component %d is out of range", id); 520 return QDF_STATUS_MAXCOMP_FAIL; 521 } 522 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 523 /* If there is a valid entry, return failure */ 524 if (g_umac_glb_obj->vdev_status_handler[id] != NULL) { 525 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 526 obj_mgr_err("Callback for comp %d is already registered", id); 527 return QDF_STATUS_E_FAILURE; 528 } 529 /* Store handler and args in Global object table */ 530 g_umac_glb_obj->vdev_status_handler[id] = handler; 531 g_umac_glb_obj->vdev_status_handler_arg[id] = arg; 532 533 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 534 return QDF_STATUS_SUCCESS; 535 } 536 537 QDF_STATUS wlan_objmgr_unregister_vdev_status_handler( 538 enum wlan_umac_comp_id id, 539 wlan_objmgr_vdev_status_handler handler, 540 void *arg) 541 { 542 /* If id is not within valid range, return */ 543 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 544 obj_mgr_err("Component %d is out of range", id); 545 return QDF_STATUS_MAXCOMP_FAIL; 546 } 547 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 548 /* If there is an invalid entry, return failure */ 549 if (g_umac_glb_obj->vdev_status_handler[id] != handler) { 550 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 551 obj_mgr_err("Callback for Component %d is not registered", id); 552 return QDF_STATUS_E_FAILURE; 553 } 554 /* Reset handlers, and args to NULL */ 555 g_umac_glb_obj->vdev_status_handler[id] = NULL; 556 g_umac_glb_obj->vdev_status_handler_arg[id] = NULL; 557 558 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 559 return QDF_STATUS_SUCCESS; 560 } 561 562 563 QDF_STATUS wlan_objmgr_register_peer_create_handler( 564 enum wlan_umac_comp_id id, 565 wlan_objmgr_peer_create_handler handler, 566 void *arg) 567 { 568 /* If id is not within valid range, return */ 569 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 570 obj_mgr_err("Component %d is out of range", id); 571 return QDF_STATUS_MAXCOMP_FAIL; 572 } 573 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 574 /* If there is a valid entry, return failure */ 575 if (g_umac_glb_obj->peer_create_handler[id] != NULL) { 576 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 577 obj_mgr_err("Callback for comp %d is already registered", id); 578 QDF_ASSERT(0); 579 return QDF_STATUS_E_FAILURE; 580 } 581 /* Store handler and args in Global object table */ 582 g_umac_glb_obj->peer_create_handler[id] = handler; 583 g_umac_glb_obj->peer_create_handler_arg[id] = arg; 584 585 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 586 return QDF_STATUS_SUCCESS; 587 } 588 589 590 QDF_STATUS wlan_objmgr_unregister_peer_create_handler( 591 enum wlan_umac_comp_id id, 592 wlan_objmgr_peer_create_handler handler, 593 void *arg) 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 return QDF_STATUS_MAXCOMP_FAIL; 599 } 600 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 601 /* If there is an invalid entry, return failure */ 602 if (g_umac_glb_obj->peer_create_handler[id] != handler) { 603 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 604 obj_mgr_err("Callback for comp %d is not registered", id); 605 QDF_ASSERT(0); 606 return QDF_STATUS_E_FAILURE; 607 } 608 /* Reset handlers, and args to NULL */ 609 g_umac_glb_obj->peer_create_handler[id] = NULL; 610 g_umac_glb_obj->peer_create_handler_arg[id] = NULL; 611 612 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 613 return QDF_STATUS_SUCCESS; 614 } 615 616 QDF_STATUS wlan_objmgr_register_peer_destroy_handler( 617 enum wlan_umac_comp_id id, 618 wlan_objmgr_peer_destroy_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_destroy_handler[id] != NULL) { 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_destroy_handler[id] = handler; 636 g_umac_glb_obj->peer_destroy_handler_arg[id] = arg; 637 638 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 639 return QDF_STATUS_SUCCESS; 640 } 641 642 QDF_STATUS wlan_objmgr_unregister_peer_destroy_handler( 643 enum wlan_umac_comp_id id, 644 wlan_objmgr_peer_destroy_handler handler, 645 void *arg) 646 { 647 /* If id is not within valid range, return */ 648 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 649 obj_mgr_err("Component %d is out of range", id); 650 return QDF_STATUS_MAXCOMP_FAIL; 651 } 652 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 653 /* If there is an invalid entry, return failure */ 654 if (g_umac_glb_obj->peer_destroy_handler[id] != handler) { 655 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 656 obj_mgr_err("Callback for comp %d is not registered", id); 657 QDF_ASSERT(0); 658 return QDF_STATUS_E_FAILURE; 659 } 660 /* Reset handlers, and args to NULL */ 661 g_umac_glb_obj->peer_destroy_handler[id] = NULL; 662 g_umac_glb_obj->peer_destroy_handler_arg[id] = NULL; 663 664 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 665 return QDF_STATUS_SUCCESS; 666 } 667 668 QDF_STATUS wlan_objmgr_register_peer_status_handler( 669 enum wlan_umac_comp_id id, 670 wlan_objmgr_peer_status_handler handler, 671 void *arg) 672 { 673 /* If id is not within valid range, return */ 674 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 675 obj_mgr_err("Component %d is out of range", id); 676 return QDF_STATUS_MAXCOMP_FAIL; 677 } 678 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 679 /* If there is a valid entry, return failure */ 680 if (g_umac_glb_obj->peer_status_handler[id] != NULL) { 681 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 682 obj_mgr_err("Callback for comp %d is already registered", id); 683 return QDF_STATUS_E_FAILURE; 684 } 685 /* Store handler and args in Global object table */ 686 g_umac_glb_obj->peer_status_handler[id] = handler; 687 g_umac_glb_obj->peer_status_handler_arg[id] = arg; 688 689 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 690 return QDF_STATUS_SUCCESS; 691 } 692 693 QDF_STATUS wlan_objmgr_unregister_peer_status_handler( 694 enum wlan_umac_comp_id id, 695 wlan_objmgr_peer_status_handler handler, 696 void *arg) 697 { 698 /* If id is not within valid range, return */ 699 if (id >= WLAN_UMAC_MAX_COMPONENTS) { 700 obj_mgr_err("Component %d is out of range", id); 701 return QDF_STATUS_MAXCOMP_FAIL; 702 } 703 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 704 /* If there is an invalid entry, return failure */ 705 if (g_umac_glb_obj->peer_status_handler[id] != handler) { 706 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 707 obj_mgr_err("Callback for comp %d is not registered", id); 708 return QDF_STATUS_E_FAILURE; 709 } 710 /* Reset handlers, and args to NULL */ 711 g_umac_glb_obj->peer_status_handler[id] = NULL; 712 g_umac_glb_obj->peer_status_handler_arg[id] = NULL; 713 714 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 715 return QDF_STATUS_SUCCESS; 716 } 717 718 719 QDF_STATUS wlan_objmgr_psoc_object_attach(struct wlan_objmgr_psoc *psoc) 720 { 721 uint8_t index = 0; 722 QDF_STATUS status = QDF_STATUS_E_FAILURE; 723 724 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 725 /* Find free slot in PSOC table, store the PSOC */ 726 while (index < WLAN_OBJMGR_MAX_DEVICES) { 727 if (g_umac_glb_obj->psoc[index] == NULL) { 728 /* Found free slot, store psoc */ 729 g_umac_glb_obj->psoc[index] = psoc; 730 status = QDF_STATUS_SUCCESS; 731 break; 732 } 733 index++; 734 } 735 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 736 return status; 737 } 738 739 QDF_STATUS wlan_objmgr_psoc_object_detach(struct wlan_objmgr_psoc *psoc) 740 { 741 uint8_t index = 0; 742 QDF_STATUS status = QDF_STATUS_E_FAILURE; 743 744 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 745 while (index < WLAN_OBJMGR_MAX_DEVICES) { 746 if (g_umac_glb_obj->psoc[index] == psoc) { 747 /* found psoc, store NULL */ 748 g_umac_glb_obj->psoc[index] = NULL; 749 status = QDF_STATUS_SUCCESS; 750 break; 751 } 752 index++; 753 } 754 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 755 return status; 756 } 757 758 QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void) 759 { 760 uint8_t index = 0; 761 QDF_STATUS status = QDF_STATUS_SUCCESS; 762 763 qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); 764 /* Check whether all PSOCs are freed */ 765 while (index < WLAN_OBJMGR_MAX_DEVICES) { 766 if (g_umac_glb_obj->psoc[index] != NULL) { 767 status = QDF_STATUS_E_FAILURE; 768 break; 769 } 770 index++; 771 } 772 qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); 773 774 return status; 775 } 776 EXPORT_SYMBOL(wlan_objmgr_global_obj_can_destroyed); 777 778 void wlan_objmgr_print_ref_ids(qdf_atomic_t *id) 779 { 780 uint32_t i; 781 uint32_t pending_ref; 782 783 obj_mgr_info("Pending references of object"); 784 for (i = 0; i < WLAN_REF_ID_MAX; i++) { 785 pending_ref = qdf_atomic_read(&id[i]); 786 if (pending_ref) 787 obj_mgr_info("%s -- %d", 788 string_from_dbgid(i), pending_ref); 789 } 790 791 return; 792 } 793