1 /* 2 * Copyright (c) 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: wlan_serialization_utils.c 20 * This file defines the utility helper functions for serialization component. 21 */ 22 23 #include "wlan_serialization_utils_i.h" 24 #include "wlan_serialization_main_i.h" 25 #include "wlan_serialization_api.h" 26 #include "wlan_objmgr_vdev_obj.h" 27 #include "wlan_objmgr_pdev_obj.h" 28 #include "qdf_mc_timer.h" 29 #include "wlan_utility.h" 30 31 QDF_STATUS 32 wlan_serialization_put_back_to_global_list(qdf_list_t *queue, 33 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 34 struct wlan_serialization_command_list *cmd_list) 35 { 36 QDF_STATUS status; 37 38 if (!queue || !ser_pdev_obj || !cmd_list) { 39 serialization_err("input parameters are invalid"); 40 return QDF_STATUS_E_FAILURE; 41 } 42 status = qdf_list_remove_node(queue, &cmd_list->node); 43 if (QDF_STATUS_SUCCESS != status) { 44 serialization_err("can't remove cmd from queue"); 45 /* assert to catch any leaks */ 46 QDF_ASSERT(0); 47 return status; 48 } 49 serialization_info("cmd_id-%d, cmd_type-%d", cmd_list->cmd.cmd_id, 50 cmd_list->cmd.cmd_type); 51 qdf_mem_zero(&cmd_list->cmd, sizeof(struct wlan_serialization_command)); 52 status = qdf_list_insert_back(&ser_pdev_obj->global_cmd_pool_list, 53 &cmd_list->node); 54 if (QDF_STATUS_SUCCESS != status) { 55 serialization_err("can't put command back to global pool"); 56 QDF_ASSERT(0); 57 return status; 58 } 59 60 return status; 61 } 62 63 struct wlan_objmgr_pdev* 64 wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd) 65 { 66 struct wlan_objmgr_pdev *pdev = NULL; 67 68 if (!cmd) { 69 serialization_err("invalid cmd"); 70 return pdev; 71 } 72 pdev = wlan_vdev_get_pdev(cmd->vdev); 73 74 return pdev; 75 } 76 77 /** 78 * wlan_serialization_get_cmd_from_queue() - to extract command from given queue 79 * @queue: pointer to queue 80 * @nnode: next node to extract 81 * 82 * This API will try to extract node from queue which is next to prev node. If 83 * no previous node is given then take out the front node of the queue. 84 * 85 * Return: QDF_STATUS 86 */ 87 QDF_STATUS wlan_serialization_get_cmd_from_queue(qdf_list_t *queue, 88 qdf_list_node_t **nnode) 89 { 90 QDF_STATUS status; 91 qdf_list_node_t *pnode; 92 93 pnode = *nnode; 94 if (!pnode) 95 status = qdf_list_peek_front(queue, nnode); 96 else 97 status = qdf_list_peek_next(queue, pnode, nnode); 98 99 if (status != QDF_STATUS_SUCCESS) { 100 serialization_err("can't get next node from queue"); 101 return status; 102 } 103 return QDF_STATUS_SUCCESS; 104 } 105 106 /** 107 * wlan_serialization_timer_destroy() - destroys the timer 108 * @ser_timer: pointer to particular timer 109 * 110 * This API destroys the memory allocated by timer and assigns cmd member of 111 * that timer structure to NULL 112 * 113 * Return: QDF_STATUS 114 */ 115 static QDF_STATUS wlan_serialization_timer_destroy( 116 struct wlan_serialization_timer *ser_timer) 117 { 118 QDF_STATUS status = QDF_STATUS_E_FAILURE; 119 120 if (!ser_timer || !ser_timer->cmd) { 121 serialization_debug("Invalid ser_timer"); 122 return status; 123 } 124 status = qdf_mc_timer_destroy(&ser_timer->timer); 125 if (!QDF_IS_STATUS_SUCCESS(status)) { 126 serialization_err("Failed to destroy timer for cmd_id[%d]", 127 ser_timer->cmd->cmd_id); 128 QDF_ASSERT(0); 129 return status; 130 } 131 ser_timer->cmd = NULL; 132 133 return status; 134 } 135 136 /** 137 * wlan_serialization_generic_timer_callback() - timer callback when timer fire 138 * @arg: argument that timer passes to this callback 139 * 140 * All the timers in serialization module calls this callback when they fire, 141 * and this API in turn calls command specific timeout callback and remove 142 * timed-out command from active queue and move any pending command to active 143 * queue of same cmd_type. 144 * 145 * Return: none 146 */ 147 static void wlan_serialization_generic_timer_callback(void *arg) 148 { 149 struct wlan_serialization_timer *timer = arg; 150 struct wlan_serialization_command *cmd = timer->cmd; 151 152 if (!cmd) { 153 serialization_err("command not found"); 154 QDF_ASSERT(0); 155 return; 156 } 157 158 serialization_err("active cmd timeout for cmd_type[%d] vdev[%pK]", 159 cmd->cmd_type, cmd->vdev); 160 if (cmd->cmd_cb) 161 cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT); 162 163 if (cmd->cmd_type >= WLAN_SER_CMD_NONSCAN) 164 QDF_BUG(0); 165 /* 166 * dequeue cmd API will cleanup and destroy the timer. If it fails to 167 * dequeue command then we have to destroy the timer. It will also call 168 * cmd callback with WLAN_SER_CB_RELEASE_MEM_CMD to free the memory. 169 */ 170 if (WLAN_SER_CMD_NOT_FOUND == wlan_serialization_dequeue_cmd(cmd, true)) 171 wlan_serialization_timer_destroy(timer); 172 if (cmd->cmd_cb) 173 cmd->cmd_cb(cmd, WLAN_SER_CB_RELEASE_MEM_CMD); 174 } 175 176 /** 177 * wlan_serialization_stop_timer() - to stop particular timer 178 * @ser_timer: pointer to serialization timer 179 * 180 * This API stops the particular timer 181 * 182 * Return: QDF_STATUS 183 */ 184 static QDF_STATUS 185 wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer) 186 { 187 QDF_TIMER_STATE state; 188 QDF_STATUS status; 189 190 state = qdf_mc_timer_get_current_state(&ser_timer->timer); 191 if (QDF_TIMER_STATE_RUNNING != state || 192 QDF_TIMER_STATE_STARTING != state) { 193 serialization_debug("nothing to stop"); 194 wlan_serialization_timer_destroy(ser_timer); 195 return QDF_STATUS_SUCCESS; 196 } 197 status = qdf_mc_timer_stop(&ser_timer->timer); 198 if (!QDF_IS_STATUS_SUCCESS(status)) { 199 serialization_err("Failed to stop timer"); 200 /* to catch the bug */ 201 QDF_ASSERT(0); 202 return status; 203 } 204 wlan_serialization_timer_destroy(ser_timer); 205 status = QDF_STATUS_SUCCESS; 206 } 207 208 QDF_STATUS wlan_serialization_cleanup_all_timers( 209 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj) 210 { 211 struct wlan_serialization_timer *ser_timer; 212 QDF_STATUS status = QDF_STATUS_SUCCESS; 213 uint32_t i = 0; 214 215 if (!psoc_ser_obj) { 216 serialization_err("Invalid psoc_ser_obj"); 217 return QDF_STATUS_E_FAILURE; 218 } 219 220 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 221 ser_timer = &psoc_ser_obj->timers[i]; 222 if (!ser_timer->cmd) 223 continue; 224 status = wlan_serialization_stop_timer(ser_timer); 225 if (QDF_STATUS_SUCCESS != status) { 226 /* lets not break the loop but report error */ 227 serialization_err("some error in stopping timer"); 228 } 229 } 230 231 return status; 232 } 233 234 QDF_STATUS 235 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc, 236 struct wlan_serialization_command *cmd) 237 { 238 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj; 239 struct wlan_serialization_timer *ser_timer; 240 QDF_STATUS status = QDF_STATUS_E_FAILURE; 241 int i = 0; 242 243 if (!psoc || !cmd) { 244 serialization_err("invalid param"); 245 return status; 246 } 247 248 if ((cmd->cmd_timeout_duration == 0) && 249 (wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc) 250 ))) { 251 serialization_err("[SCAN-EMULATION]: Not performing timer functions\n"); 252 return QDF_STATUS_SUCCESS; 253 } 254 255 psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc); 256 /* 257 * Here cmd_id and cmd_type are used to locate the timer being 258 * associated with command. For scan command, cmd_id is expected to 259 * be unique and For non-scan command, there should be only one active 260 * command per pdev 261 */ 262 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 263 ser_timer = &psoc_ser_obj->timers[i]; 264 if (!(ser_timer->cmd) || 265 (ser_timer->cmd->cmd_id != cmd->cmd_id) || 266 (ser_timer->cmd->cmd_type != cmd->cmd_type) || 267 (ser_timer->cmd->vdev != cmd->vdev)) 268 continue; 269 status = wlan_serialization_stop_timer(ser_timer); 270 if (QDF_STATUS_SUCCESS != status) { 271 serialization_err("Failed to stop timer for cmd_id[%d]", 272 cmd->cmd_id); 273 } 274 break; 275 } 276 277 if (QDF_STATUS_SUCCESS != status) { 278 serialization_err("can't find timer for cmd_type[%d]", 279 cmd->cmd_type); 280 } 281 return status; 282 } 283 284 QDF_STATUS 285 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc, 286 struct wlan_serialization_command *cmd) 287 { 288 QDF_STATUS status = QDF_STATUS_E_FAILURE; 289 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj; 290 struct wlan_serialization_timer *ser_timer; 291 int i = 0; 292 293 if (!psoc || !cmd) { 294 serialization_err("invalid param"); 295 return status; 296 } 297 298 if ((cmd->cmd_timeout_duration == 0) && 299 (wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc) 300 ))) { 301 serialization_err("[SCAN-EMULATION]: Not performing timer functions\n"); 302 return QDF_STATUS_SUCCESS; 303 } 304 305 306 psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc); 307 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 308 /* Keep trying timer */ 309 ser_timer = &psoc_ser_obj->timers[i]; 310 if (ser_timer->cmd) 311 continue; 312 /* Remember timer is pointing to command */ 313 ser_timer->cmd = cmd; 314 if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_init(&ser_timer->timer, 315 QDF_TIMER_TYPE_SW, 316 wlan_serialization_generic_timer_callback, 317 ser_timer))) { 318 serialization_err("Failed to init timer cmdid [%d]", 319 cmd->cmd_id); 320 QDF_ASSERT(0); 321 continue; 322 } 323 if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_start(&ser_timer->timer, 324 cmd->cmd_timeout_duration))) { 325 serialization_err("Failed to start timer cmdid [%d]", 326 cmd->cmd_id); 327 wlan_serialization_timer_destroy(ser_timer); 328 QDF_ASSERT(0); 329 continue; 330 } 331 status = QDF_STATUS_SUCCESS; 332 break; 333 } 334 335 return status; 336 } 337 338 /** 339 * wlan_serialization_active_scan_cmd_count_handler() - count active scan cmds 340 * @psoc: pointer to soc strucutre 341 * @obj : pointer to pdev object 342 * @arg: pointer to argument 343 * 344 * This API will be called while iterating each pdev object and it will count 345 * number of scan commands present in that pdev object's active queue. count 346 * will be updated in *arg 347 * 348 * Return: none 349 */ 350 static void 351 wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc, 352 void *obj, void *arg) 353 { 354 struct wlan_objmgr_pdev *pdev = obj; 355 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 356 uint32_t *count = arg; 357 358 if (!pdev) { 359 serialization_err("invalid pdev"); 360 return; 361 } 362 363 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( 364 pdev, WLAN_UMAC_COMP_SERIALIZATION); 365 *count += qdf_list_size(&ser_pdev_obj->active_scan_list); 366 } 367 368 /** 369 * wlan_serialization_is_active_scan_cmd_allowed() - find if scan cmd allowed 370 * @pdev: pointer to pdev object 371 * 372 * This API will be called to find out if active scan cmd is allowed. It has 373 * to iterate through all pdev to find out total number of active scan cmds. 374 * If total number of active scan cmds reach to allowed threshold then don't 375 * allow more scan cmd. 376 * 377 * Return: true or false 378 */ 379 static bool 380 wlan_serialization_is_active_scan_cmd_allowed(struct wlan_objmgr_pdev *pdev) 381 { 382 uint32_t count = 0; 383 struct wlan_objmgr_psoc *psoc; 384 385 if (!pdev) { 386 serialization_err("invalid pdev"); 387 return false; 388 } 389 390 psoc = wlan_pdev_get_psoc(pdev); 391 392 if (!psoc) { 393 serialization_err("invalid psoc"); 394 return false; 395 } 396 397 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 398 wlan_serialization_active_scan_cmd_count_handler, 399 &count, 1, WLAN_SERIALIZATION_ID); 400 if (count < ucfg_scan_get_max_active_scans(psoc)) { 401 serialization_notice("count is [%d]", count); 402 return true; 403 } 404 405 return false; 406 } 407 408 /** 409 * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed 410 * @pdev: pointer to pdev object 411 * 412 * This API will be called to find out if non scan cmd is allowed. 413 * 414 * Return: true or false 415 */ 416 static bool 417 wlan_serialization_is_active_nonscan_cmd_allowed(struct wlan_objmgr_pdev *pdev) 418 { 419 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 420 421 if (!pdev) { 422 serialization_err("invalid pdev"); 423 return false; 424 } 425 426 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( 427 pdev, WLAN_UMAC_COMP_SERIALIZATION); 428 429 if (!ser_pdev_obj) { 430 serialization_err("invalid ser_pdev_obj"); 431 return false; 432 } 433 434 if (qdf_list_empty(&ser_pdev_obj->active_list)) 435 return true; 436 437 return false; 438 } 439 440 bool 441 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd) 442 { 443 struct wlan_objmgr_pdev *pdev; 444 445 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 446 if (!pdev) { 447 serialization_err("NULL pdev"); 448 return false; 449 } 450 451 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 452 return wlan_serialization_is_active_scan_cmd_allowed(pdev); 453 else 454 return wlan_serialization_is_active_nonscan_cmd_allowed(pdev); 455 } 456 457 QDF_STATUS wlan_serialization_validate_cmdtype( 458 enum wlan_serialization_cmd_type cmd_type) 459 { 460 serialization_info("validate cmd_type:%d", cmd_type); 461 462 if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) { 463 serialization_err("Invalid cmd or comp passed"); 464 return QDF_STATUS_E_INVAL; 465 } 466 467 return QDF_STATUS_SUCCESS; 468 } 469 470 QDF_STATUS wlan_serialization_validate_cmd( 471 enum wlan_umac_comp_id comp_id, 472 enum wlan_serialization_cmd_type cmd_type) 473 { 474 serialization_info("validate cmd_type:%d, comp_id:%d", 475 cmd_type, comp_id); 476 if (cmd_type < 0 || comp_id < 0 || 477 cmd_type >= WLAN_SER_CMD_MAX || 478 comp_id >= WLAN_UMAC_COMP_ID_MAX) { 479 serialization_err("Invalid cmd or comp passed"); 480 return QDF_STATUS_E_INVAL; 481 } 482 483 return QDF_STATUS_SUCCESS; 484 } 485 486 void wlan_serialization_release_list_cmds( 487 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 488 qdf_list_t *list) 489 { 490 qdf_list_node_t *node = NULL; 491 492 while (!qdf_list_empty(list)) { 493 qdf_list_remove_front(list, &node); 494 qdf_list_insert_back(&ser_pdev_obj->global_cmd_pool_list, node); 495 } 496 497 return; 498 } 499 500 void wlan_serialization_destroy_list( 501 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 502 qdf_list_t *list) 503 { 504 wlan_serialization_release_list_cmds(ser_pdev_obj, list); 505 qdf_list_destroy(list); 506 } 507 508 struct wlan_serialization_psoc_priv_obj *wlan_serialization_get_psoc_priv_obj( 509 struct wlan_objmgr_psoc *psoc) 510 { 511 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 512 ser_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 513 WLAN_UMAC_COMP_SERIALIZATION); 514 515 return ser_soc_obj; 516 } 517 518 struct wlan_serialization_pdev_priv_obj *wlan_serialization_get_pdev_priv_obj( 519 struct wlan_objmgr_pdev *pdev) 520 { 521 struct wlan_serialization_pdev_priv_obj *obj; 522 obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 523 WLAN_UMAC_COMP_SERIALIZATION); 524 525 return obj; 526 } 527 528 struct wlan_serialization_psoc_priv_obj * 529 wlan_serialization_get_obj(struct wlan_serialization_command *cmd) 530 { 531 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 532 struct wlan_objmgr_psoc *psoc; 533 534 psoc = wlan_vdev_get_psoc(cmd->vdev); 535 ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc); 536 537 return ser_soc_obj; 538 } 539 540 bool wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev *vdev, 541 qdf_list_t *queue) 542 { 543 uint32_t queuelen; 544 qdf_list_node_t *nnode = NULL; 545 struct wlan_serialization_command_list *cmd_list = NULL; 546 QDF_STATUS status; 547 548 queuelen = qdf_list_size(queue); 549 if (!queuelen) { 550 serialization_debug("queue empty"); 551 return false; 552 } 553 554 while (queuelen--) { 555 status = wlan_serialization_get_cmd_from_queue(queue, &nnode); 556 if (status != QDF_STATUS_SUCCESS) 557 break; 558 cmd_list = qdf_container_of(nnode, 559 struct wlan_serialization_command_list, node); 560 if (cmd_list->cmd.vdev == vdev) 561 return true; 562 }; 563 564 return false; 565 } 566 567 bool wlan_serialization_is_cmd_in_pdev_list(struct wlan_objmgr_pdev *pdev, 568 qdf_list_t *queue) 569 { 570 uint32_t queuelen; 571 qdf_list_node_t *nnode = NULL; 572 struct wlan_objmgr_pdev *node_pdev = NULL; 573 struct wlan_serialization_command_list *cmd_list = NULL; 574 QDF_STATUS status; 575 576 queuelen = qdf_list_size(queue); 577 if (!queuelen) { 578 serialization_debug("queue empty"); 579 return false; 580 } 581 582 while (queuelen--) { 583 status = wlan_serialization_get_cmd_from_queue(queue, &nnode); 584 if (status != QDF_STATUS_SUCCESS) 585 break; 586 cmd_list = qdf_container_of(nnode, 587 struct wlan_serialization_command_list, node); 588 node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev); 589 if (node_pdev == pdev) 590 return true; 591 } 592 593 return false; 594 } 595 596 enum wlan_serialization_cmd_status 597 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active, 598 bool cmd_in_pending) 599 { 600 if (cmd_in_active && cmd_in_pending) 601 return WLAN_SER_CMDS_IN_ALL_LISTS; 602 else if (cmd_in_active) 603 return WLAN_SER_CMD_IN_ACTIVE_LIST; 604 else if (cmd_in_pending) 605 return WLAN_SER_CMD_IN_PENDING_LIST; 606 else 607 return WLAN_SER_CMD_NOT_FOUND; 608 } 609 610 static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue, 611 struct wlan_serialization_command *cmd) 612 { 613 uint32_t qsize; 614 QDF_STATUS status; 615 struct wlan_serialization_command_list *cmd_list = NULL; 616 qdf_list_node_t *nnode = NULL, *pnode = NULL; 617 bool found = false; 618 619 qsize = qdf_list_size(queue); 620 while (qsize--) { 621 if (!cmd_list) 622 status = qdf_list_peek_front(queue, &nnode); 623 else 624 status = qdf_list_peek_next(queue, pnode, 625 &nnode); 626 627 if (status != QDF_STATUS_SUCCESS) 628 break; 629 630 pnode = nnode; 631 cmd_list = qdf_container_of(nnode, 632 struct wlan_serialization_command_list, node); 633 if ((cmd_list->cmd.cmd_id == cmd->cmd_id) && 634 (cmd_list->cmd.cmd_type == cmd->cmd_type) && 635 (cmd_list->cmd.vdev == cmd->vdev)) { 636 found = true; 637 break; 638 } 639 nnode = NULL; 640 } 641 return found; 642 } 643 644 bool wlan_serialization_is_cmd_present_queue( 645 struct wlan_serialization_command *cmd, 646 uint8_t is_active_queue) 647 { 648 qdf_list_t *queue; 649 struct wlan_objmgr_pdev *pdev; 650 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 651 652 if (!cmd) { 653 serialization_err("invalid params"); 654 return false; 655 } 656 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 657 if (!pdev) { 658 serialization_err("invalid pdev"); 659 return false; 660 } 661 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 662 WLAN_UMAC_COMP_SERIALIZATION); 663 if (!ser_pdev_obj) { 664 serialization_err("invalid ser_pdev_obj"); 665 return false; 666 } 667 if (!is_active_queue) { 668 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 669 queue = &ser_pdev_obj->pending_scan_list; 670 else 671 queue = &ser_pdev_obj->pending_list; 672 } else { 673 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 674 queue = &ser_pdev_obj->active_scan_list; 675 else 676 queue = &ser_pdev_obj->active_list; 677 } 678 679 return wlan_serialization_is_cmd_present_in_given_queue(queue, cmd); 680 } 681