1 /* 2 * Copyright (c) 2017-2019 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 pdev_queue->vdev_active_cmd_bitmap = 0; 275 pdev_queue->blocking_cmd_active = 0; 276 pdev_queue->blocking_cmd_waiting = 0; 277 } 278 279 status = wlan_objmgr_pdev_component_obj_attach( 280 pdev, WLAN_UMAC_COMP_SERIALIZATION, 281 ser_pdev_obj, QDF_STATUS_SUCCESS); 282 283 if (status != QDF_STATUS_SUCCESS) { 284 ser_err("Pdev obj attach failed, status %d", status); 285 goto error_free; 286 } 287 288 return QDF_STATUS_SUCCESS; 289 290 error_free: 291 for (free_index = 0; free_index <= index; free_index++) { 292 pdev_queue = &ser_pdev_obj->pdev_q[free_index]; 293 294 wlan_serialization_destroy_cmd_pool(pdev_queue); 295 qdf_list_destroy(&pdev_queue->pending_list); 296 qdf_list_destroy(&pdev_queue->active_list); 297 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 298 } 299 error: 300 return status; 301 } 302 303 /** 304 * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback 305 * @psoc: PSOC object 306 * @arg_list: Variable argument list 307 * 308 * This callback is registered with object manager during initialization and 309 * when obj manager gets its turn to delete the object, it would notify each 310 * component with the corresponding callback registered to inform the 311 * completion of the deletion of the respective object. 312 * 313 * Return: QDF Status 314 */ 315 static QDF_STATUS 316 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc, 317 void *arg_list) 318 { 319 QDF_STATUS status = QDF_STATUS_E_FAULT; 320 struct wlan_ser_psoc_obj *ser_soc_obj = 321 wlan_serialization_get_psoc_obj(psoc); 322 323 if (!ser_soc_obj) { 324 ser_err("invalid ser_soc_obj"); 325 goto error; 326 } 327 status = wlan_objmgr_psoc_component_obj_detach( 328 psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj); 329 if (status != QDF_STATUS_SUCCESS) 330 ser_err("ser psoc private obj detach failed"); 331 332 ser_debug("ser psoc obj deleted with status %d", status); 333 qdf_mem_free(ser_soc_obj); 334 335 error: 336 return status; 337 } 338 339 /** 340 * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback 341 * @pdev: PDEV object 342 * @arg_list: Variable argument list 343 * 344 * This callback is registered with object manager during initialization and 345 * when obj manager gets its turn to delete the object, it would notify each 346 * component with the corresponding callback registered to inform the 347 * completion of the deletion of the respective object. 348 * 349 * Return: QDF Status 350 */ 351 static QDF_STATUS wlan_serialization_pdev_destroy_handler( 352 struct wlan_objmgr_pdev *pdev, void *arg_list) 353 { 354 QDF_STATUS status; 355 struct wlan_serialization_pdev_queue *pdev_queue; 356 struct wlan_ser_pdev_obj *ser_pdev_obj = 357 wlan_serialization_get_pdev_obj(pdev); 358 uint8_t index; 359 360 if (!ser_pdev_obj) { 361 ser_err("ser_pdev_obj NULL"); 362 return QDF_STATUS_E_INVAL; 363 } 364 status = wlan_objmgr_pdev_component_obj_detach( 365 pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj); 366 367 for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) { 368 pdev_queue = &ser_pdev_obj->pdev_q[index]; 369 370 wlan_serialization_destroy_pdev_list(pdev_queue); 371 wlan_serialization_destroy_cmd_pool(pdev_queue); 372 373 wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock); 374 } 375 qdf_mem_free(ser_pdev_obj); 376 377 return status; 378 } 379 380 /** 381 * wlan_serialization_vdev_create_handler() - VDEV obj create callback 382 * @vdev: VDEV object 383 * @arg_list: Variable argument list 384 * 385 * This callback is registered with object manager during initialization and 386 * when obj manager gets its turn to create the object, it would notify each 387 * component with the corresponding callback registered to inform the 388 * completion of the creation of the respective object. 389 * 390 * Return: QDF Status 391 */ 392 static QDF_STATUS 393 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev, 394 void *arg_list) 395 { 396 struct wlan_ser_vdev_obj *ser_vdev_obj; 397 struct wlan_serialization_vdev_queue *vdev_q; 398 QDF_STATUS status = QDF_STATUS_E_NOMEM; 399 uint8_t index; 400 uint8_t max_active_cmds; 401 uint8_t max_pending_cmds; 402 403 ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj)); 404 if (!ser_vdev_obj) 405 goto error; 406 407 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 408 vdev_q = &ser_vdev_obj->vdev_q[index]; 409 410 switch (index) { 411 case SER_VDEV_QUEUE_COMP_NON_SCAN: 412 max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS / 413 WLAN_SER_MAX_VDEVS; 414 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE || 415 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE) 416 max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS_AP; 417 else 418 max_pending_cmds = 419 WLAN_SER_MAX_PENDING_CMDS_STA; 420 421 ser_debug("Vdev type %d max_pending_cmds %d", 422 wlan_vdev_mlme_get_opmode(vdev), 423 max_pending_cmds); 424 break; 425 } 426 427 qdf_list_create(&vdev_q->active_list, 428 max_active_cmds); 429 qdf_list_create(&vdev_q->pending_list, 430 max_pending_cmds); 431 } 432 433 status = wlan_objmgr_vdev_component_obj_attach( 434 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj, 435 QDF_STATUS_SUCCESS); 436 437 if (status != QDF_STATUS_SUCCESS) { 438 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 439 vdev_q = &ser_vdev_obj->vdev_q[index]; 440 qdf_list_destroy(&vdev_q->pending_list); 441 qdf_list_destroy(&vdev_q->active_list); 442 } 443 qdf_mem_free(ser_vdev_obj); 444 ser_err("serialization vdev obj attach failed"); 445 } 446 error: 447 return status; 448 } 449 450 /** 451 * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback 452 * @vdev: VDEV object 453 * @arg_list: Variable argument list 454 * 455 * This callback is registered with object manager during initialization and 456 * when obj manager gets its turn to delete the object, it would notify each 457 * component with the corresponding callback registered to inform the 458 * completion of the deletion of the respective object. 459 * 460 * Return: QDF Status 461 */ 462 static QDF_STATUS wlan_serialization_vdev_destroy_handler( 463 struct wlan_objmgr_vdev *vdev, void *arg_list) 464 { 465 QDF_STATUS status = QDF_STATUS_SUCCESS; 466 struct wlan_serialization_vdev_queue *vdev_q; 467 struct wlan_ser_vdev_obj *ser_vdev_obj = 468 wlan_serialization_get_vdev_obj(vdev); 469 uint8_t index; 470 471 if (!ser_vdev_obj) { 472 ser_err("ser_vdev_obj NULL"); 473 return QDF_STATUS_E_INVAL; 474 } 475 476 status = wlan_objmgr_vdev_component_obj_detach( 477 vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj); 478 479 /*Clean up serialization timers if any for this vdev*/ 480 wlan_serialization_cleanup_vdev_timers(vdev); 481 482 for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) { 483 vdev_q = &ser_vdev_obj->vdev_q[index]; 484 wlan_serialization_destroy_vdev_list(&vdev_q->pending_list); 485 wlan_serialization_destroy_vdev_list(&vdev_q->active_list); 486 } 487 488 qdf_mem_free(ser_vdev_obj); 489 490 return status; 491 } 492 493 QDF_STATUS wlan_serialization_init(void) 494 { 495 QDF_STATUS status = QDF_STATUS_SUCCESS; 496 497 status = wlan_objmgr_register_psoc_create_handler( 498 WLAN_UMAC_COMP_SERIALIZATION, 499 wlan_serialization_psoc_create_handler, NULL); 500 if (status != QDF_STATUS_SUCCESS) { 501 ser_err("Failed to reg soc ser obj create handler"); 502 goto err_psoc_create; 503 } 504 505 status = wlan_objmgr_register_psoc_destroy_handler( 506 WLAN_UMAC_COMP_SERIALIZATION, 507 wlan_serialization_psoc_destroy_handler, NULL); 508 if (status != QDF_STATUS_SUCCESS) { 509 ser_err("Failed to reg soc ser obj delete handler"); 510 goto err_psoc_delete; 511 } 512 513 status = wlan_objmgr_register_pdev_create_handler( 514 WLAN_UMAC_COMP_SERIALIZATION, 515 wlan_serialization_pdev_create_handler, NULL); 516 if (status != QDF_STATUS_SUCCESS) { 517 ser_err("Failed to reg pdev ser obj create handler"); 518 goto err_pdev_create; 519 } 520 521 status = wlan_objmgr_register_pdev_destroy_handler( 522 WLAN_UMAC_COMP_SERIALIZATION, 523 wlan_serialization_pdev_destroy_handler, NULL); 524 if (status != QDF_STATUS_SUCCESS) { 525 ser_err("Failed to reg pdev ser obj delete handler"); 526 goto err_pdev_delete; 527 } 528 529 status = wlan_objmgr_register_vdev_create_handler( 530 WLAN_UMAC_COMP_SERIALIZATION, 531 wlan_serialization_vdev_create_handler, NULL); 532 if (status != QDF_STATUS_SUCCESS) { 533 ser_err("Failed to reg vdev ser obj create handler"); 534 goto err_vdev_create; 535 } 536 537 status = wlan_objmgr_register_vdev_destroy_handler( 538 WLAN_UMAC_COMP_SERIALIZATION, 539 wlan_serialization_vdev_destroy_handler, NULL); 540 if (status != QDF_STATUS_SUCCESS) { 541 ser_err("Failed to reg vdev ser obj delete handler"); 542 goto err_vdev_delete; 543 } 544 545 status = QDF_STATUS_SUCCESS; 546 goto exit; 547 548 err_vdev_delete: 549 wlan_objmgr_unregister_vdev_create_handler( 550 WLAN_UMAC_COMP_SERIALIZATION, 551 wlan_serialization_vdev_create_handler, 552 NULL); 553 err_vdev_create: 554 wlan_objmgr_unregister_pdev_destroy_handler( 555 WLAN_UMAC_COMP_SERIALIZATION, 556 wlan_serialization_pdev_destroy_handler, 557 NULL); 558 err_pdev_delete: 559 wlan_objmgr_unregister_pdev_create_handler( 560 WLAN_UMAC_COMP_SERIALIZATION, 561 wlan_serialization_pdev_create_handler, 562 NULL); 563 err_pdev_create: 564 wlan_objmgr_unregister_psoc_destroy_handler( 565 WLAN_UMAC_COMP_SERIALIZATION, 566 wlan_serialization_psoc_destroy_handler, 567 NULL); 568 err_psoc_delete: 569 wlan_objmgr_unregister_psoc_create_handler( 570 WLAN_UMAC_COMP_SERIALIZATION, 571 wlan_serialization_psoc_create_handler, 572 NULL); 573 err_psoc_create: 574 exit: 575 return status; 576 } 577 578 QDF_STATUS wlan_serialization_deinit(void) 579 { 580 QDF_STATUS status; 581 QDF_STATUS ret_status = QDF_STATUS_SUCCESS; 582 583 status = wlan_objmgr_unregister_psoc_create_handler( 584 WLAN_UMAC_COMP_SERIALIZATION, 585 wlan_serialization_psoc_create_handler, 586 NULL); 587 588 if (status != QDF_STATUS_SUCCESS) { 589 ser_err("unreg fail for psoc ser obj create notf:%d", status); 590 ret_status = QDF_STATUS_E_FAILURE; 591 } 592 status = wlan_objmgr_unregister_psoc_destroy_handler( 593 WLAN_UMAC_COMP_SERIALIZATION, 594 wlan_serialization_psoc_destroy_handler, 595 NULL); 596 597 if (status != QDF_STATUS_SUCCESS) { 598 ser_err("unreg fail for psoc ser obj destroy notf:%d", status); 599 ret_status = QDF_STATUS_E_FAILURE; 600 } 601 602 status = wlan_objmgr_unregister_pdev_create_handler( 603 WLAN_UMAC_COMP_SERIALIZATION, 604 wlan_serialization_pdev_create_handler, 605 NULL); 606 if (status != QDF_STATUS_SUCCESS) { 607 ser_err("unreg fail for pdev ser obj create notf:%d", status); 608 ret_status = QDF_STATUS_E_FAILURE; 609 } 610 611 status = wlan_objmgr_unregister_pdev_destroy_handler( 612 WLAN_UMAC_COMP_SERIALIZATION, 613 wlan_serialization_pdev_destroy_handler, 614 NULL); 615 616 if (status != QDF_STATUS_SUCCESS) { 617 ser_err("unreg fail for pdev ser destroy notf:%d", status); 618 ret_status = QDF_STATUS_E_FAILURE; 619 } 620 621 ser_alert("deregistered callbacks with obj mgr successfully"); 622 623 return ret_status; 624 } 625