1 /* 2 * Copyright (c) 2017-2020 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 /** 20 * DOC: wlan_serialization_main.c 21 * This file defines the important functions pertinent to 22 * serialization to initialize and de-initialize the 23 * component. 24 */ 25 #include <qdf_status.h> 26 #include <qdf_list.h> 27 #include <wlan_objmgr_cmn.h> 28 #include <wlan_objmgr_global_obj.h> 29 #include <wlan_objmgr_psoc_obj.h> 30 #include "wlan_serialization_main_i.h" 31 #include "wlan_serialization_rules_i.h" 32 #include "wlan_serialization_utils_i.h" 33 34 QDF_STATUS wlan_serialization_psoc_disable(struct wlan_objmgr_psoc *psoc) 35 { 36 QDF_STATUS status = QDF_STATUS_E_FAILURE; 37 struct wlan_ser_psoc_obj *ser_soc_obj = 38 wlan_serialization_get_psoc_obj(psoc); 39 40 if (!ser_soc_obj) { 41 ser_err("invalid ser_soc_obj"); 42 goto error; 43 } 44 45 /* 46 * purge all serialization command if there are any pending to make 47 * sure memory and vdev ref are freed. 48 */ 49 wlan_serialization_purge_all_cmd(psoc); 50 /* clean up all timers before exiting */ 51 status = wlan_serialization_cleanup_all_timers(ser_soc_obj); 52 if (status != QDF_STATUS_SUCCESS) 53 ser_err("ser cleanning up all timer failed"); 54 55 qdf_mem_free(ser_soc_obj->timers); 56 ser_soc_obj->timers = NULL; 57 ser_soc_obj->max_active_cmds = 0; 58 59 wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); 60 error: 61 return status; 62 } 63 64 QDF_STATUS wlan_serialization_psoc_enable(struct wlan_objmgr_psoc *psoc) 65 { 66 uint8_t pdev_count; 67 struct wlan_ser_psoc_obj *ser_soc_obj = 68 wlan_serialization_get_psoc_obj(psoc); 69 QDF_STATUS status = QDF_STATUS_E_FAILURE; 70 71 if (!ser_soc_obj) { 72 ser_err("invalid ser_soc_obj"); 73 goto error; 74 } 75 76 pdev_count = wlan_psoc_get_pdev_count(psoc); 77 ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS + 78 (pdev_count * WLAN_SER_MAX_VDEVS); 79 80 ser_debug("max_active_cmds %d", ser_soc_obj->max_active_cmds); 81 82 ser_soc_obj->timers = 83 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 84 ser_soc_obj->max_active_cmds); 85 if (!ser_soc_obj->timers) { 86 status = QDF_STATUS_E_NOMEM; 87 goto error; 88 } 89 90 wlan_serialization_create_lock(&ser_soc_obj->timer_lock); 91 status = QDF_STATUS_SUCCESS; 92 93 error: 94 return status; 95 } 96 97 /** 98 * wlan_serialization_psoc_create_handler() - PSOC obj create callback 99 * @psoc: PSOC object 100 * @arg_list: Variable argument list 101 * 102 * This callback is registered with object manager during initialization and 103 * when obj manager gets its turn to create the object, it would notify each 104 * component with the corresponding callback registered to inform the 105 * completion of the creation of the respective object. 106 * 107 * Return: QDF Status 108 */ 109 static QDF_STATUS wlan_serialization_psoc_create_handler( 110 struct wlan_objmgr_psoc *psoc, void *arg_list) 111 { 112 struct wlan_ser_psoc_obj *soc_ser_obj; 113 QDF_STATUS status = QDF_STATUS_E_NOMEM; 114 115 soc_ser_obj = 116 qdf_mem_malloc(sizeof(*soc_ser_obj)); 117 if (!soc_ser_obj) 118 goto error; 119 120 status = wlan_objmgr_psoc_component_obj_attach( 121 psoc, 122 WLAN_UMAC_COMP_SERIALIZATION, 123 soc_ser_obj, 124 QDF_STATUS_SUCCESS); 125 if (QDF_IS_STATUS_ERROR(status)) { 126 qdf_mem_free(soc_ser_obj); 127 ser_err("Obj attach failed"); 128 goto error; 129 } 130 ser_debug("ser psoc obj created"); 131 status = QDF_STATUS_SUCCESS; 132 133 error: 134 return status; 135 } 136 137 /** 138 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 139 * @ser_pdev_obj: Serialization private pdev object 140 * 141 * Return: None 142 */ 143 static void wlan_serialization_destroy_cmd_pool( 144 struct wlan_serialization_pdev_queue *pdev_queue) 145 { 146 qdf_list_node_t *node = NULL; 147 struct wlan_serialization_command_list *cmd_list; 148 149 ser_debug("Destroy cmd pool list %pK, size %d", 150 &pdev_queue->cmd_pool_list, 151 qdf_list_size(&pdev_queue->cmd_pool_list)); 152 while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) { 153 qdf_list_remove_front(&pdev_queue->cmd_pool_list, 154 &node); 155 cmd_list = (struct wlan_serialization_command_list *)node; 156 qdf_mem_free(cmd_list); 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 ser_debug("ser psoc obj deleted with status %d", status); 335 qdf_mem_free(ser_soc_obj); 336 337 error: 338 return status; 339 } 340 341 /** 342 * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback 343 * @pdev: PDEV object 344 * @arg_list: Variable argument list 345 * 346 * This callback is registered with object manager during initialization and 347 * when obj manager gets its turn to delete the object, it would notify each 348 * component with the corresponding callback registered to inform the 349 * completion of the deletion of the respective object. 350 * 351 * Return: QDF Status 352 */ 353 static QDF_STATUS wlan_serialization_pdev_destroy_handler( 354 struct wlan_objmgr_pdev *pdev, void *arg_list) 355 { 356 QDF_STATUS status; 357 struct wlan_serialization_pdev_queue *pdev_queue; 358 struct wlan_ser_pdev_obj *ser_pdev_obj = 359 wlan_serialization_get_pdev_obj(pdev); 360 uint8_t index; 361 362 if (!ser_pdev_obj) { 363 ser_err("ser_pdev_obj NULL"); 364 return QDF_STATUS_E_INVAL; 365 } 366 status = wlan_objmgr_pdev_component_obj_detach( 367 pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 368 369 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 370 pdev_queue = &ser_pdev_obj->pdev_q[index]; 371 372 wlan_serialization_destroy_pdev_list(pdev_queue); 373 wlan_serialization_destroy_cmd_pool(pdev_queue); 374 375 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 376 } 377 qdf_mem_free(ser_pdev_obj); 378 379 return status; 380 } 381 382 /** 383 * wlan_serialization_vdev_create_handler() - VDEV obj create callback 384 * @vdev: VDEV object 385 * @arg_list: Variable argument list 386 * 387 * This callback is registered with object manager during initialization and 388 * when obj manager gets its turn to create the object, it would notify each 389 * component with the corresponding callback registered to inform the 390 * completion of the creation of the respective object. 391 * 392 * Return: QDF Status 393 */ 394 static QDF_STATUS 395 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev, 396 void *arg_list) 397 { 398 struct wlan_ser_vdev_obj *ser_vdev_obj; 399 struct wlan_serialization_vdev_queue *vdev_q; 400 QDF_STATUS status = QDF_STATUS_E_NOMEM; 401 uint8_t index; 402 uint8_t max_active_cmds; 403 uint8_t max_pending_cmds; 404 405 ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj)); 406 if (!ser_vdev_obj) 407 goto error; 408 409 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 410 vdev_q = &ser_vdev_obj->vdev_q[index]; 411 412 switch (index) { 413 case SER_VDEV_QUEUE_COMP_NON_SCAN: 414 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS / 415 WLAN_SER_MAX_VDEVS; 416 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE || 417 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE) 418 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS_AP; 419 else 420 max_pending_cmds = 421 WLAN_SER_MAX_PENDING_CMDS_STA; 422 423 ser_debug("Vdev type %d max_pending_cmds %d", 424 wlan_vdev_mlme_get_opmode(vdev), 425 max_pending_cmds); 426 break; 427 } 428 429 qdf_list_create(&vdev_q->active_list, 430 max_active_cmds); 431 qdf_list_create(&vdev_q->pending_list, 432 max_pending_cmds); 433 } 434 435 status = wlan_objmgr_vdev_component_obj_attach( 436 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj, 437 QDF_STATUS_SUCCESS); 438 439 if (status != QDF_STATUS_SUCCESS) { 440 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 441 vdev_q = &ser_vdev_obj->vdev_q[index]; 442 qdf_list_destroy(&vdev_q->pending_list); 443 qdf_list_destroy(&vdev_q->active_list); 444 } 445 qdf_mem_free(ser_vdev_obj); 446 ser_err("serialization vdev obj attach failed"); 447 } 448 error: 449 return status; 450 } 451 452 /** 453 * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback 454 * @vdev: VDEV object 455 * @arg_list: Variable argument list 456 * 457 * This callback is registered with object manager during initialization and 458 * when obj manager gets its turn to delete the object, it would notify each 459 * component with the corresponding callback registered to inform the 460 * completion of the deletion of the respective object. 461 * 462 * Return: QDF Status 463 */ 464 static QDF_STATUS wlan_serialization_vdev_destroy_handler( 465 struct wlan_objmgr_vdev *vdev, void *arg_list) 466 { 467 QDF_STATUS status = QDF_STATUS_SUCCESS; 468 struct wlan_serialization_vdev_queue *vdev_q; 469 struct wlan_ser_vdev_obj *ser_vdev_obj = 470 wlan_serialization_get_vdev_obj(vdev); 471 uint8_t index; 472 473 if (!ser_vdev_obj) { 474 ser_err("ser_vdev_obj NULL"); 475 return QDF_STATUS_E_INVAL; 476 } 477 478 status = wlan_objmgr_vdev_component_obj_detach( 479 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj); 480 481 /*Clean up serialization timers if any for this vdev*/ 482 wlan_serialization_cleanup_vdev_timers(vdev); 483 484 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 485 vdev_q = &ser_vdev_obj->vdev_q[index]; 486 wlan_serialization_destroy_vdev_list(&vdev_q->pending_list); 487 wlan_serialization_destroy_vdev_list(&vdev_q->active_list); 488 } 489 490 qdf_mem_free(ser_vdev_obj); 491 492 return status; 493 } 494 495 QDF_STATUS wlan_serialization_init(void) 496 { 497 QDF_STATUS status = QDF_STATUS_SUCCESS; 498 499 status = wlan_objmgr_register_psoc_create_handler( 500 WLAN_UMAC_COMP_SERIALIZATION, 501 wlan_serialization_psoc_create_handler, NULL); 502 if (status != QDF_STATUS_SUCCESS) { 503 ser_err("Failed to reg soc ser obj create handler"); 504 goto err_psoc_create; 505 } 506 507 status = wlan_objmgr_register_psoc_destroy_handler( 508 WLAN_UMAC_COMP_SERIALIZATION, 509 wlan_serialization_psoc_destroy_handler, NULL); 510 if (status != QDF_STATUS_SUCCESS) { 511 ser_err("Failed to reg soc ser obj delete handler"); 512 goto err_psoc_delete; 513 } 514 515 status = wlan_objmgr_register_pdev_create_handler( 516 WLAN_UMAC_COMP_SERIALIZATION, 517 wlan_serialization_pdev_create_handler, NULL); 518 if (status != QDF_STATUS_SUCCESS) { 519 ser_err("Failed to reg pdev ser obj create handler"); 520 goto err_pdev_create; 521 } 522 523 status = wlan_objmgr_register_pdev_destroy_handler( 524 WLAN_UMAC_COMP_SERIALIZATION, 525 wlan_serialization_pdev_destroy_handler, NULL); 526 if (status != QDF_STATUS_SUCCESS) { 527 ser_err("Failed to reg pdev ser obj delete handler"); 528 goto err_pdev_delete; 529 } 530 531 status = wlan_objmgr_register_vdev_create_handler( 532 WLAN_UMAC_COMP_SERIALIZATION, 533 wlan_serialization_vdev_create_handler, NULL); 534 if (status != QDF_STATUS_SUCCESS) { 535 ser_err("Failed to reg vdev ser obj create handler"); 536 goto err_vdev_create; 537 } 538 539 status = wlan_objmgr_register_vdev_destroy_handler( 540 WLAN_UMAC_COMP_SERIALIZATION, 541 wlan_serialization_vdev_destroy_handler, NULL); 542 if (status != QDF_STATUS_SUCCESS) { 543 ser_err("Failed to reg vdev ser obj delete handler"); 544 goto err_vdev_delete; 545 } 546 547 status = QDF_STATUS_SUCCESS; 548 goto exit; 549 550 err_vdev_delete: 551 wlan_objmgr_unregister_vdev_create_handler( 552 WLAN_UMAC_COMP_SERIALIZATION, 553 wlan_serialization_vdev_create_handler, 554 NULL); 555 err_vdev_create: 556 wlan_objmgr_unregister_pdev_destroy_handler( 557 WLAN_UMAC_COMP_SERIALIZATION, 558 wlan_serialization_pdev_destroy_handler, 559 NULL); 560 err_pdev_delete: 561 wlan_objmgr_unregister_pdev_create_handler( 562 WLAN_UMAC_COMP_SERIALIZATION, 563 wlan_serialization_pdev_create_handler, 564 NULL); 565 err_pdev_create: 566 wlan_objmgr_unregister_psoc_destroy_handler( 567 WLAN_UMAC_COMP_SERIALIZATION, 568 wlan_serialization_psoc_destroy_handler, 569 NULL); 570 err_psoc_delete: 571 wlan_objmgr_unregister_psoc_create_handler( 572 WLAN_UMAC_COMP_SERIALIZATION, 573 wlan_serialization_psoc_create_handler, 574 NULL); 575 err_psoc_create: 576 exit: 577 return status; 578 } 579 580 QDF_STATUS wlan_serialization_deinit(void) 581 { 582 QDF_STATUS status; 583 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 584 585 status = wlan_objmgr_unregister_psoc_create_handler( 586 WLAN_UMAC_COMP_SERIALIZATION, 587 wlan_serialization_psoc_create_handler, 588 NULL); 589 590 if (status != QDF_STATUS_SUCCESS) { 591 ser_err("unreg fail for psoc ser obj create notf:%d", status); 592 ret_status = QDF_STATUS_E_FAILURE; 593 } 594 status = wlan_objmgr_unregister_psoc_destroy_handler( 595 WLAN_UMAC_COMP_SERIALIZATION, 596 wlan_serialization_psoc_destroy_handler, 597 NULL); 598 599 if (status != QDF_STATUS_SUCCESS) { 600 ser_err("unreg fail for psoc ser obj destroy notf:%d", status); 601 ret_status = QDF_STATUS_E_FAILURE; 602 } 603 604 status = wlan_objmgr_unregister_pdev_create_handler( 605 WLAN_UMAC_COMP_SERIALIZATION, 606 wlan_serialization_pdev_create_handler, 607 NULL); 608 if (status != QDF_STATUS_SUCCESS) { 609 ser_err("unreg fail for pdev ser obj create notf:%d", status); 610 ret_status = QDF_STATUS_E_FAILURE; 611 } 612 613 status = wlan_objmgr_unregister_pdev_destroy_handler( 614 WLAN_UMAC_COMP_SERIALIZATION, 615 wlan_serialization_pdev_destroy_handler, 616 NULL); 617 618 if (status != QDF_STATUS_SUCCESS) { 619 ser_err("unreg fail for pdev ser destroy notf:%d", status); 620 ret_status = QDF_STATUS_E_FAILURE; 621 } 622 623 ser_debug("deregistered callbacks with obj mgr successfully"); 624 625 return ret_status; 626 } 627