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 /* Use lock to free to avoid any race where timer is still in use */ 56 wlan_serialization_acquire_lock(&ser_soc_obj->timer_lock); 57 qdf_mem_free(ser_soc_obj->timers); 58 ser_soc_obj->timers = NULL; 59 ser_soc_obj->max_active_cmds = 0; 60 wlan_serialization_release_lock(&ser_soc_obj->timer_lock); 61 error: 62 return status; 63 } 64 65 QDF_STATUS wlan_serialization_psoc_enable(struct wlan_objmgr_psoc *psoc) 66 { 67 uint8_t pdev_count; 68 struct wlan_ser_psoc_obj *ser_soc_obj = 69 wlan_serialization_get_psoc_obj(psoc); 70 QDF_STATUS status = QDF_STATUS_E_FAILURE; 71 72 if (!ser_soc_obj) { 73 ser_err("invalid ser_soc_obj"); 74 goto error; 75 } 76 77 pdev_count = wlan_psoc_get_pdev_count(psoc); 78 ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS + 79 (pdev_count * WLAN_SER_MAX_VDEVS); 80 81 ser_debug("max_active_cmds %d", ser_soc_obj->max_active_cmds); 82 83 ser_soc_obj->timers = 84 qdf_mem_malloc(sizeof(struct wlan_serialization_timer) * 85 ser_soc_obj->max_active_cmds); 86 if (!ser_soc_obj->timers) { 87 status = QDF_STATUS_E_NOMEM; 88 goto error; 89 } 90 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 wlan_serialization_create_lock(&soc_ser_obj->timer_lock); 131 ser_debug("ser psoc obj created"); 132 status = QDF_STATUS_SUCCESS; 133 134 error: 135 return status; 136 } 137 138 /** 139 * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool 140 * @ser_pdev_obj: Serialization private pdev object 141 * 142 * Return: None 143 */ 144 static void wlan_serialization_destroy_cmd_pool( 145 struct wlan_serialization_pdev_queue *pdev_queue) 146 { 147 qdf_list_node_t *node = NULL; 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 qdf_mem_free(node); 156 } 157 158 qdf_list_destroy(&pdev_queue->cmd_pool_list); 159 160 } 161 162 /** 163 * wlan_serialization_create_cmd_pool() - Create the global cmd pool 164 * @pdev: PDEV Object 165 * @ser_pdev_obj: Serialization private pdev object 166 * 167 * Global command pool of memory is created here. 168 * It is safe to allocate memory individually for each command rather than 169 * requesting for a huge chunk of memory at once. 170 * 171 * The individual command nodes allocated above will keep moving between 172 * the active, pending and global pool lists dynamically, but all the 173 * memory will be freed during driver unload only. 174 * 175 * Return: QDF Status 176 */ 177 static QDF_STATUS 178 wlan_serialization_create_cmd_pool( 179 struct wlan_serialization_pdev_queue *pdev_queue, 180 uint16_t cmd_pool_size) 181 { 182 struct wlan_serialization_command_list *cmd_list_ptr; 183 uint8_t i; 184 QDF_STATUS status = QDF_STATUS_E_NOMEM; 185 186 qdf_list_create(&pdev_queue->cmd_pool_list, cmd_pool_size); 187 188 for (i = 0; i < cmd_pool_size; i++) { 189 cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr)); 190 if (!cmd_list_ptr) { 191 wlan_serialization_destroy_cmd_pool(pdev_queue); 192 goto error; 193 } 194 195 qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr)); 196 qdf_list_insert_back( 197 &pdev_queue->cmd_pool_list, 198 &cmd_list_ptr->pdev_node); 199 cmd_list_ptr->cmd_in_use = 0; 200 } 201 202 ser_debug("Create cmd pool list %pK, size %d", 203 &pdev_queue->cmd_pool_list, 204 qdf_list_size(&pdev_queue->cmd_pool_list)); 205 206 status = QDF_STATUS_SUCCESS; 207 208 error: 209 return status; 210 } 211 212 /** 213 * wlan_serialization_pdev_create_handler() - PDEV obj create callback 214 * @pdev: PDEV object 215 * @arg_list: Variable argument list 216 * 217 * This callback is registered with object manager during initialization and 218 * when obj manager gets its turn to create the object, it would notify each 219 * component with the corresponding callback registered to inform the 220 * completion of the creation of the respective object. 221 * 222 * Return: QDF Status 223 */ 224 static QDF_STATUS wlan_serialization_pdev_create_handler( 225 struct wlan_objmgr_pdev *pdev, void *arg_list) 226 { 227 struct wlan_ser_pdev_obj *ser_pdev_obj; 228 struct wlan_serialization_pdev_queue *pdev_queue; 229 QDF_STATUS status = QDF_STATUS_E_NOMEM; 230 uint8_t index; 231 uint8_t free_index; 232 uint8_t max_active_cmds; 233 uint8_t max_pending_cmds; 234 uint16_t cmd_pool_size; 235 236 ser_pdev_obj = 237 qdf_mem_malloc(sizeof(*ser_pdev_obj)); 238 if (!ser_pdev_obj) 239 goto error; 240 241 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 242 pdev_queue = &ser_pdev_obj->pdev_q[index]; 243 244 wlan_serialization_create_lock(&pdev_queue->pdev_queue_lock); 245 246 switch (index) { 247 case SER_PDEV_QUEUE_COMP_SCAN: 248 max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS; 249 max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS; 250 cmd_pool_size = max_active_cmds + max_pending_cmds; 251 break; 252 253 case SER_PDEV_QUEUE_COMP_NON_SCAN: 254 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS; 255 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS; 256 cmd_pool_size = max_active_cmds + max_pending_cmds; 257 ser_debug("max_active_cmds %d max_pending_cmds %d", 258 max_active_cmds, max_pending_cmds); 259 break; 260 } 261 qdf_list_create(&pdev_queue->active_list, 262 max_active_cmds); 263 qdf_list_create(&pdev_queue->pending_list, 264 max_pending_cmds); 265 266 status = wlan_serialization_create_cmd_pool(pdev_queue, 267 cmd_pool_size); 268 if (status != QDF_STATUS_SUCCESS) { 269 ser_err("Create cmd pool failed, status %d", status); 270 goto error_free; 271 } 272 273 qdf_mem_zero(pdev_queue->vdev_active_cmd_bitmap, 274 sizeof(pdev_queue->vdev_active_cmd_bitmap)); 275 276 pdev_queue->blocking_cmd_active = 0; 277 pdev_queue->blocking_cmd_waiting = 0; 278 } 279 280 status = wlan_objmgr_pdev_component_obj_attach( 281 pdev, WLAN_UMAC_COMP_SERIALIZATION, 282 ser_pdev_obj, QDF_STATUS_SUCCESS); 283 284 if (status != QDF_STATUS_SUCCESS) { 285 ser_err("Pdev obj attach failed, status %d", status); 286 goto error_free; 287 } 288 289 return QDF_STATUS_SUCCESS; 290 291 error_free: 292 for (free_index = 0; free_index <= index; free_index++) { 293 pdev_queue = &ser_pdev_obj->pdev_q[free_index]; 294 295 wlan_serialization_destroy_cmd_pool(pdev_queue); 296 qdf_list_destroy(&pdev_queue->pending_list); 297 qdf_list_destroy(&pdev_queue->active_list); 298 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 299 } 300 error: 301 return status; 302 } 303 304 /** 305 * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback 306 * @psoc: PSOC object 307 * @arg_list: Variable argument list 308 * 309 * This callback is registered with object manager during initialization and 310 * when obj manager gets its turn to delete the object, it would notify each 311 * component with the corresponding callback registered to inform the 312 * completion of the deletion of the respective object. 313 * 314 * Return: QDF Status 315 */ 316 static QDF_STATUS 317 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc, 318 void *arg_list) 319 { 320 QDF_STATUS status = QDF_STATUS_E_FAULT; 321 struct wlan_ser_psoc_obj *ser_soc_obj = 322 wlan_serialization_get_psoc_obj(psoc); 323 324 if (!ser_soc_obj) { 325 ser_err("invalid ser_soc_obj"); 326 goto error; 327 } 328 status = wlan_objmgr_psoc_component_obj_detach( 329 psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj); 330 if (status != QDF_STATUS_SUCCESS) 331 ser_err("ser psoc private obj detach failed"); 332 333 wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); 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