1 /* 2 * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: wlan_serialization_main.c 22 * This file defines the important functions pertinent to 23 * serialization to initialize and de-initialize the 24 * component. 25 */ 26 #include <qdf_status.h> 27 #include <qdf_list.h> 28 #include <wlan_objmgr_cmn.h> 29 #include <wlan_objmgr_global_obj.h> 30 #include <wlan_objmgr_psoc_obj.h> 31 #include "wlan_serialization_main_i.h" 32 #include "wlan_serialization_rules_i.h" 33 #include "wlan_serialization_utils_i.h" 34 35 QDF_STATUS wlan_serialization_psoc_disable(struct wlan_objmgr_psoc *psoc) 36 { 37 QDF_STATUS status = QDF_STATUS_E_FAILURE; 38 struct wlan_ser_psoc_obj *ser_soc_obj = 39 wlan_serialization_get_psoc_obj(psoc); 40 41 if (!ser_soc_obj) { 42 ser_err("invalid ser_soc_obj"); 43 goto error; 44 } 45 46 /* 47 * purge all serialization command if there are any pending to make 48 * sure memory and vdev ref are freed. 49 */ 50 wlan_serialization_purge_all_cmd(psoc); 51 /* clean up all timers before exiting */ 52 status = wlan_serialization_cleanup_all_timers(ser_soc_obj); 53 if (status != QDF_STATUS_SUCCESS) 54 ser_err("ser cleaning up all timer failed"); 55 56 /* Use lock to free to avoid any race where timer is still in use */ 57 wlan_serialization_acquire_lock(&ser_soc_obj->timer_lock); 58 qdf_mem_free(ser_soc_obj->timers); 59 ser_soc_obj->timers = NULL; 60 ser_soc_obj->max_active_cmds = 0; 61 wlan_serialization_release_lock(&ser_soc_obj->timer_lock); 62 error: 63 return status; 64 } 65 66 QDF_STATUS wlan_serialization_psoc_enable(struct wlan_objmgr_psoc *psoc) 67 { 68 uint8_t pdev_count; 69 struct wlan_ser_psoc_obj *ser_soc_obj = 70 wlan_serialization_get_psoc_obj(psoc); 71 QDF_STATUS status = QDF_STATUS_E_FAILURE; 72 73 if (!ser_soc_obj) { 74 ser_err("invalid ser_soc_obj"); 75 goto error; 76 } 77 78 pdev_count = wlan_psoc_get_pdev_count(psoc); 79 ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS + 80 (pdev_count * WLAN_SER_MAX_VDEVS); 81 82 ser_debug("max_active_cmds %d", ser_soc_obj->max_active_cmds); 83 84 ser_soc_obj->timers = 85 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 86 ser_soc_obj->max_active_cmds); 87 if (!ser_soc_obj->timers) { 88 status = QDF_STATUS_E_NOMEM; 89 goto error; 90 } 91 92 status = QDF_STATUS_SUCCESS; 93 94 error: 95 return status; 96 } 97 98 /** 99 * wlan_serialization_psoc_create_handler() - PSOC obj create callback 100 * @psoc: PSOC object 101 * @arg_list: Variable argument list 102 * 103 * This callback is registered with object manager during initialization and 104 * when obj manager gets its turn to create the object, it would notify each 105 * component with the corresponding callback registered to inform the 106 * completion of the creation of the respective object. 107 * 108 * Return: QDF Status 109 */ 110 static QDF_STATUS wlan_serialization_psoc_create_handler( 111 struct wlan_objmgr_psoc *psoc, void *arg_list) 112 { 113 struct wlan_ser_psoc_obj *soc_ser_obj; 114 QDF_STATUS status = QDF_STATUS_E_NOMEM; 115 116 soc_ser_obj = 117 qdf_mem_malloc(sizeof(*soc_ser_obj)); 118 if (!soc_ser_obj) 119 goto error; 120 121 status = wlan_objmgr_psoc_component_obj_attach( 122 psoc, 123 WLAN_UMAC_COMP_SERIALIZATION, 124 soc_ser_obj, 125 QDF_STATUS_SUCCESS); 126 if (QDF_IS_STATUS_ERROR(status)) { 127 qdf_mem_free(soc_ser_obj); 128 ser_err("Obj attach failed"); 129 goto error; 130 } 131 wlan_serialization_create_lock(&soc_ser_obj->timer_lock); 132 ser_debug("ser psoc obj created"); 133 status = QDF_STATUS_SUCCESS; 134 135 error: 136 return status; 137 } 138 139 /** 140 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 141 * @ser_pdev_obj: Serialization private pdev object 142 * 143 * Return: None 144 */ 145 static void wlan_serialization_destroy_cmd_pool( 146 struct wlan_serialization_pdev_queue *pdev_queue) 147 { 148 qdf_list_node_t *node = NULL; 149 150 ser_debug("Destroy cmd pool list %pK, size %d", 151 &pdev_queue->cmd_pool_list, 152 qdf_list_size(&pdev_queue->cmd_pool_list)); 153 while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) { 154 qdf_list_remove_front(&pdev_queue->cmd_pool_list, 155 &node); 156 qdf_mem_free(node); 157 } 158 159 qdf_list_destroy(&pdev_queue->cmd_pool_list); 160 161 } 162 163 /** 164 * wlan_serialization_create_cmd_pool() - Create the global cmd pool 165 * @pdev: PDEV Object 166 * @ser_pdev_obj: Serialization private pdev object 167 * 168 * Global command pool of memory is created here. 169 * It is safe to allocate memory individually for each command rather than 170 * requesting for a huge chunk of memory at once. 171 * 172 * The individual command nodes allocated above will keep moving between 173 * the active, pending and global pool lists dynamically, but all the 174 * memory will be freed during driver unload only. 175 * 176 * Return: QDF Status 177 */ 178 static QDF_STATUS 179 wlan_serialization_create_cmd_pool( 180 struct wlan_serialization_pdev_queue *pdev_queue, 181 uint16_t cmd_pool_size) 182 { 183 struct wlan_serialization_command_list *cmd_list_ptr; 184 uint8_t i; 185 QDF_STATUS status = QDF_STATUS_E_NOMEM; 186 187 qdf_list_create(&pdev_queue->cmd_pool_list, cmd_pool_size); 188 189 for (i = 0; i < cmd_pool_size; i++) { 190 cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr)); 191 if (!cmd_list_ptr) { 192 wlan_serialization_destroy_cmd_pool(pdev_queue); 193 goto error; 194 } 195 196 qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr)); 197 qdf_list_insert_back( 198 &pdev_queue->cmd_pool_list, 199 &cmd_list_ptr->pdev_node); 200 cmd_list_ptr->cmd_in_use = 0; 201 } 202 203 ser_debug("Create cmd pool list %pK, size %d", 204 &pdev_queue->cmd_pool_list, 205 qdf_list_size(&pdev_queue->cmd_pool_list)); 206 207 status = QDF_STATUS_SUCCESS; 208 209 error: 210 return status; 211 } 212 213 /** 214 * wlan_serialization_pdev_create_handler() - PDEV obj create callback 215 * @pdev: PDEV object 216 * @arg_list: Variable argument list 217 * 218 * This callback is registered with object manager during initialization and 219 * when obj manager gets its turn to create the object, it would notify each 220 * component with the corresponding callback registered to inform the 221 * completion of the creation of the respective object. 222 * 223 * Return: QDF Status 224 */ 225 static QDF_STATUS wlan_serialization_pdev_create_handler( 226 struct wlan_objmgr_pdev *pdev, void *arg_list) 227 { 228 struct wlan_ser_pdev_obj *ser_pdev_obj; 229 struct wlan_serialization_pdev_queue *pdev_queue; 230 QDF_STATUS status = QDF_STATUS_E_NOMEM; 231 uint8_t index; 232 uint8_t free_index; 233 uint8_t max_active_cmds; 234 uint8_t max_pending_cmds; 235 uint16_t cmd_pool_size; 236 237 ser_pdev_obj = 238 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 239 if (!ser_pdev_obj) 240 goto error; 241 242 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 243 pdev_queue = &ser_pdev_obj->pdev_q[index]; 244 245 wlan_serialization_create_lock(&pdev_queue->pdev_queue_lock); 246 247 switch (index) { 248 case SER_PDEV_QUEUE_COMP_SCAN: 249 max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS; 250 max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS; 251 cmd_pool_size = max_active_cmds + max_pending_cmds; 252 break; 253 254 case SER_PDEV_QUEUE_COMP_NON_SCAN: 255 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS; 256 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS; 257 cmd_pool_size = max_active_cmds + max_pending_cmds; 258 ser_debug("max_active_cmds %d max_pending_cmds %d", 259 max_active_cmds, max_pending_cmds); 260 break; 261 } 262 qdf_list_create(&pdev_queue->active_list, 263 max_active_cmds); 264 qdf_list_create(&pdev_queue->pending_list, 265 max_pending_cmds); 266 267 status = wlan_serialization_create_cmd_pool(pdev_queue, 268 cmd_pool_size); 269 if (status != QDF_STATUS_SUCCESS) { 270 ser_err("Create cmd pool failed, status %d", status); 271 goto error_free; 272 } 273 274 qdf_mem_zero(pdev_queue->vdev_active_cmd_bitmap, 275 sizeof(pdev_queue->vdev_active_cmd_bitmap)); 276 277 pdev_queue->blocking_cmd_active = 0; 278 pdev_queue->blocking_cmd_waiting = 0; 279 } 280 281 status = wlan_objmgr_pdev_component_obj_attach( 282 pdev, WLAN_UMAC_COMP_SERIALIZATION, 283 ser_pdev_obj, QDF_STATUS_SUCCESS); 284 285 if (status != QDF_STATUS_SUCCESS) { 286 ser_err("Pdev obj attach failed, status %d", status); 287 goto error_free; 288 } 289 290 return QDF_STATUS_SUCCESS; 291 292 error_free: 293 for (free_index = 0; free_index <= index; free_index++) { 294 pdev_queue = &ser_pdev_obj->pdev_q[free_index]; 295 296 wlan_serialization_destroy_cmd_pool(pdev_queue); 297 qdf_list_destroy(&pdev_queue->pending_list); 298 qdf_list_destroy(&pdev_queue->active_list); 299 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 300 } 301 error: 302 return status; 303 } 304 305 /** 306 * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback 307 * @psoc: PSOC object 308 * @arg_list: Variable argument list 309 * 310 * This callback is registered with object manager during initialization and 311 * when obj manager gets its turn to delete the object, it would notify each 312 * component with the corresponding callback registered to inform the 313 * completion of the deletion of the respective object. 314 * 315 * Return: QDF Status 316 */ 317 static QDF_STATUS 318 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc, 319 void *arg_list) 320 { 321 QDF_STATUS status = QDF_STATUS_E_FAULT; 322 struct wlan_ser_psoc_obj *ser_soc_obj = 323 wlan_serialization_get_psoc_obj(psoc); 324 325 if (!ser_soc_obj) { 326 ser_err("invalid ser_soc_obj"); 327 goto error; 328 } 329 status = wlan_objmgr_psoc_component_obj_detach( 330 psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj); 331 if (status != QDF_STATUS_SUCCESS) 332 ser_err("ser psoc private obj detach failed"); 333 334 wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); 335 ser_debug("ser psoc obj deleted with status %d", status); 336 qdf_mem_free(ser_soc_obj); 337 338 error: 339 return status; 340 } 341 342 /** 343 * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback 344 * @pdev: PDEV object 345 * @arg_list: Variable argument list 346 * 347 * This callback is registered with object manager during initialization and 348 * when obj manager gets its turn to delete the object, it would notify each 349 * component with the corresponding callback registered to inform the 350 * completion of the deletion of the respective object. 351 * 352 * Return: QDF Status 353 */ 354 static QDF_STATUS wlan_serialization_pdev_destroy_handler( 355 struct wlan_objmgr_pdev *pdev, void *arg_list) 356 { 357 QDF_STATUS status; 358 struct wlan_serialization_pdev_queue *pdev_queue; 359 struct wlan_ser_pdev_obj *ser_pdev_obj = 360 wlan_serialization_get_pdev_obj(pdev); 361 uint8_t index; 362 363 if (!ser_pdev_obj) { 364 ser_err("ser_pdev_obj NULL"); 365 return QDF_STATUS_E_INVAL; 366 } 367 status = wlan_objmgr_pdev_component_obj_detach( 368 pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 369 370 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 371 pdev_queue = &ser_pdev_obj->pdev_q[index]; 372 373 wlan_serialization_destroy_pdev_list(pdev_queue); 374 wlan_serialization_destroy_cmd_pool(pdev_queue); 375 376 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 377 } 378 qdf_mem_free(ser_pdev_obj); 379 380 return status; 381 } 382 383 /** 384 * wlan_serialization_vdev_create_handler() - VDEV obj create callback 385 * @vdev: VDEV object 386 * @arg_list: Variable argument list 387 * 388 * This callback is registered with object manager during initialization and 389 * when obj manager gets its turn to create the object, it would notify each 390 * component with the corresponding callback registered to inform the 391 * completion of the creation of the respective object. 392 * 393 * Return: QDF Status 394 */ 395 static QDF_STATUS 396 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev, 397 void *arg_list) 398 { 399 struct wlan_ser_vdev_obj *ser_vdev_obj; 400 struct wlan_serialization_vdev_queue *vdev_q; 401 QDF_STATUS status = QDF_STATUS_E_NOMEM; 402 uint8_t index; 403 uint8_t max_active_cmds; 404 uint8_t max_pending_cmds; 405 406 ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj)); 407 if (!ser_vdev_obj) 408 goto error; 409 410 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 411 vdev_q = &ser_vdev_obj->vdev_q[index]; 412 413 switch (index) { 414 case SER_VDEV_QUEUE_COMP_NON_SCAN: 415 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS / 416 WLAN_SER_MAX_VDEVS; 417 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE || 418 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE) 419 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS_AP; 420 else 421 max_pending_cmds = 422 WLAN_SER_MAX_PENDING_CMDS_STA; 423 424 ser_debug("Vdev type %d max_pending_cmds %d", 425 wlan_vdev_mlme_get_opmode(vdev), 426 max_pending_cmds); 427 break; 428 } 429 430 qdf_list_create(&vdev_q->active_list, 431 max_active_cmds); 432 qdf_list_create(&vdev_q->pending_list, 433 max_pending_cmds); 434 } 435 436 status = wlan_objmgr_vdev_component_obj_attach( 437 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj, 438 QDF_STATUS_SUCCESS); 439 440 if (status != QDF_STATUS_SUCCESS) { 441 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 442 vdev_q = &ser_vdev_obj->vdev_q[index]; 443 qdf_list_destroy(&vdev_q->pending_list); 444 qdf_list_destroy(&vdev_q->active_list); 445 } 446 qdf_mem_free(ser_vdev_obj); 447 ser_err("serialization vdev obj attach failed"); 448 } 449 error: 450 return status; 451 } 452 453 /** 454 * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback 455 * @vdev: VDEV object 456 * @arg_list: Variable argument list 457 * 458 * This callback is registered with object manager during initialization and 459 * when obj manager gets its turn to delete the object, it would notify each 460 * component with the corresponding callback registered to inform the 461 * completion of the deletion of the respective object. 462 * 463 * Return: QDF Status 464 */ 465 static QDF_STATUS wlan_serialization_vdev_destroy_handler( 466 struct wlan_objmgr_vdev *vdev, void *arg_list) 467 { 468 QDF_STATUS status = QDF_STATUS_SUCCESS; 469 struct wlan_serialization_vdev_queue *vdev_q; 470 struct wlan_ser_vdev_obj *ser_vdev_obj = 471 wlan_serialization_get_vdev_obj(vdev); 472 uint8_t index; 473 474 if (!ser_vdev_obj) { 475 ser_err("ser_vdev_obj NULL"); 476 return QDF_STATUS_E_INVAL; 477 } 478 479 status = wlan_objmgr_vdev_component_obj_detach( 480 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj); 481 482 /*Clean up serialization timers if any for this vdev*/ 483 wlan_serialization_cleanup_vdev_timers(vdev); 484 485 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 486 vdev_q = &ser_vdev_obj->vdev_q[index]; 487 wlan_serialization_destroy_vdev_list(&vdev_q->pending_list); 488 wlan_serialization_destroy_vdev_list(&vdev_q->active_list); 489 } 490 491 qdf_mem_free(ser_vdev_obj); 492 493 return status; 494 } 495 496 QDF_STATUS wlan_serialization_init(void) 497 { 498 QDF_STATUS status = QDF_STATUS_SUCCESS; 499 500 status = wlan_objmgr_register_psoc_create_handler( 501 WLAN_UMAC_COMP_SERIALIZATION, 502 wlan_serialization_psoc_create_handler, NULL); 503 if (status != QDF_STATUS_SUCCESS) { 504 ser_err("Failed to reg soc ser obj create handler"); 505 goto err_psoc_create; 506 } 507 508 status = wlan_objmgr_register_psoc_destroy_handler( 509 WLAN_UMAC_COMP_SERIALIZATION, 510 wlan_serialization_psoc_destroy_handler, NULL); 511 if (status != QDF_STATUS_SUCCESS) { 512 ser_err("Failed to reg soc ser obj delete handler"); 513 goto err_psoc_delete; 514 } 515 516 status = wlan_objmgr_register_pdev_create_handler( 517 WLAN_UMAC_COMP_SERIALIZATION, 518 wlan_serialization_pdev_create_handler, NULL); 519 if (status != QDF_STATUS_SUCCESS) { 520 ser_err("Failed to reg pdev ser obj create handler"); 521 goto err_pdev_create; 522 } 523 524 status = wlan_objmgr_register_pdev_destroy_handler( 525 WLAN_UMAC_COMP_SERIALIZATION, 526 wlan_serialization_pdev_destroy_handler, NULL); 527 if (status != QDF_STATUS_SUCCESS) { 528 ser_err("Failed to reg pdev ser obj delete handler"); 529 goto err_pdev_delete; 530 } 531 532 status = wlan_objmgr_register_vdev_create_handler( 533 WLAN_UMAC_COMP_SERIALIZATION, 534 wlan_serialization_vdev_create_handler, NULL); 535 if (status != QDF_STATUS_SUCCESS) { 536 ser_err("Failed to reg vdev ser obj create handler"); 537 goto err_vdev_create; 538 } 539 540 status = wlan_objmgr_register_vdev_destroy_handler( 541 WLAN_UMAC_COMP_SERIALIZATION, 542 wlan_serialization_vdev_destroy_handler, NULL); 543 if (status != QDF_STATUS_SUCCESS) { 544 ser_err("Failed to reg vdev ser obj delete handler"); 545 goto err_vdev_delete; 546 } 547 548 status = QDF_STATUS_SUCCESS; 549 goto exit; 550 551 err_vdev_delete: 552 wlan_objmgr_unregister_vdev_create_handler( 553 WLAN_UMAC_COMP_SERIALIZATION, 554 wlan_serialization_vdev_create_handler, 555 NULL); 556 err_vdev_create: 557 wlan_objmgr_unregister_pdev_destroy_handler( 558 WLAN_UMAC_COMP_SERIALIZATION, 559 wlan_serialization_pdev_destroy_handler, 560 NULL); 561 err_pdev_delete: 562 wlan_objmgr_unregister_pdev_create_handler( 563 WLAN_UMAC_COMP_SERIALIZATION, 564 wlan_serialization_pdev_create_handler, 565 NULL); 566 err_pdev_create: 567 wlan_objmgr_unregister_psoc_destroy_handler( 568 WLAN_UMAC_COMP_SERIALIZATION, 569 wlan_serialization_psoc_destroy_handler, 570 NULL); 571 err_psoc_delete: 572 wlan_objmgr_unregister_psoc_create_handler( 573 WLAN_UMAC_COMP_SERIALIZATION, 574 wlan_serialization_psoc_create_handler, 575 NULL); 576 err_psoc_create: 577 exit: 578 return status; 579 } 580 581 QDF_STATUS wlan_serialization_deinit(void) 582 { 583 QDF_STATUS status; 584 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 585 586 status = wlan_objmgr_unregister_psoc_create_handler( 587 WLAN_UMAC_COMP_SERIALIZATION, 588 wlan_serialization_psoc_create_handler, 589 NULL); 590 591 if (status != QDF_STATUS_SUCCESS) { 592 ser_err("unreg fail for psoc ser obj create notf:%d", status); 593 ret_status = QDF_STATUS_E_FAILURE; 594 } 595 status = wlan_objmgr_unregister_psoc_destroy_handler( 596 WLAN_UMAC_COMP_SERIALIZATION, 597 wlan_serialization_psoc_destroy_handler, 598 NULL); 599 600 if (status != QDF_STATUS_SUCCESS) { 601 ser_err("unreg fail for psoc ser obj destroy notf:%d", status); 602 ret_status = QDF_STATUS_E_FAILURE; 603 } 604 605 status = wlan_objmgr_unregister_pdev_create_handler( 606 WLAN_UMAC_COMP_SERIALIZATION, 607 wlan_serialization_pdev_create_handler, 608 NULL); 609 if (status != QDF_STATUS_SUCCESS) { 610 ser_err("unreg fail for pdev ser obj create notf:%d", status); 611 ret_status = QDF_STATUS_E_FAILURE; 612 } 613 614 status = wlan_objmgr_unregister_pdev_destroy_handler( 615 WLAN_UMAC_COMP_SERIALIZATION, 616 wlan_serialization_pdev_destroy_handler, 617 NULL); 618 619 if (status != QDF_STATUS_SUCCESS) { 620 ser_err("unreg fail for pdev ser destroy notf:%d", status); 621 ret_status = QDF_STATUS_E_FAILURE; 622 } 623 624 ser_debug("deregistered callbacks with obj mgr successfully"); 625 626 return ret_status; 627 } 628