1 /* 2 * Copyright (c) 2017-2018 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_internal.c 20 * This file defines the functions which are called 21 * from serialization public API's and are internal 22 * to serialization. 23 */ 24 25 #include <wlan_objmgr_vdev_obj.h> 26 #include <wlan_objmgr_pdev_obj.h> 27 #include <wlan_objmgr_psoc_obj.h> 28 #include <qdf_list.h> 29 #include <qdf_status.h> 30 #include <wlan_utility.h> 31 #include "wlan_serialization_api.h" 32 #include "wlan_serialization_main_i.h" 33 #include "wlan_serialization_utils_i.h" 34 #include "wlan_serialization_non_scan_i.h" 35 #include "wlan_serialization_scan_i.h" 36 #include "wlan_serialization_internal_i.h" 37 38 bool wlan_serialization_is_cmd_present_queue( 39 struct wlan_serialization_command *cmd, 40 uint8_t is_active_queue) 41 { 42 qdf_list_t *queue; 43 bool status = false; 44 enum wlan_serialization_node node_type; 45 struct wlan_ser_pdev_obj *ser_pdev_obj; 46 struct wlan_ser_vdev_obj *ser_vdev_obj; 47 enum wlan_serialization_cmd_type cmd_type; 48 49 if (!cmd) { 50 ser_err("invalid cmd"); 51 goto error; 52 } 53 54 cmd_type = cmd->cmd_type; 55 56 ser_pdev_obj = wlan_serialization_get_pdev_obj( 57 wlan_serialization_get_pdev_from_cmd(cmd)); 58 59 if (!ser_pdev_obj) { 60 ser_err("invalid ser vdev obj"); 61 goto error; 62 } 63 64 ser_vdev_obj = wlan_serialization_get_vdev_obj( 65 wlan_serialization_get_vdev_from_cmd(cmd)); 66 if (!ser_vdev_obj) { 67 ser_err("invalid ser pdev obj"); 68 goto error; 69 } 70 71 if (cmd_type < WLAN_SER_CMD_NONSCAN) { 72 queue = wlan_serialization_get_list_from_pdev_queue( 73 ser_pdev_obj, cmd_type, is_active_queue); 74 node_type = WLAN_SER_PDEV_NODE; 75 } else { 76 queue = wlan_serialization_get_list_from_vdev_queue( 77 ser_vdev_obj, cmd_type, is_active_queue); 78 node_type = WLAN_SER_VDEV_NODE; 79 } 80 81 status = wlan_serialization_is_cmd_present_in_given_queue(queue, cmd, 82 node_type); 83 84 error: 85 return status; 86 } 87 88 enum wlan_serialization_status 89 wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd) 90 { 91 enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 92 struct wlan_serialization_command_list *cmd_list; 93 qdf_list_node_t *nnode; 94 struct wlan_objmgr_pdev *pdev; 95 struct wlan_ser_pdev_obj *ser_pdev_obj; 96 struct wlan_serialization_pdev_queue *pdev_queue; 97 bool active_queue; 98 99 /* Enqueue process 100 * 1) peek through command structure and see what is the command type 101 * 2) two main types of commands to process 102 * a) SCAN 103 * b) NON-SCAN 104 * 3) for each command there are separate command queues per pdev 105 * 4) pull pdev from vdev structure and get the command queue associated 106 * with that pdev and try to enqueue on those queue 107 * 5) Thumb rule: 108 * a) There could be only 1 active non-scan command at a 109 * time including all total non-scan commands of all pdevs. 110 * 111 * example: pdev1 has 1 non-scan active command and 112 * pdev2 got 1 non-scan command then that command should go to 113 * pdev2's pending queue 114 * 115 * b) There could be only N number of scan commands at a time 116 * including all total scan commands of all pdevs 117 * 118 * example: Let's say N=8, 119 * pdev1's vdev1 has 5 scan command, pdev2's vdev1 has 3 120 * scan commands, if we get scan request on vdev2 then it will go 121 * to pending queue of vdev2 as we reached max allowed scan active 122 * command. 123 */ 124 125 ser_enter(); 126 127 if (!cmd) { 128 ser_err("NULL command"); 129 goto error; 130 } 131 132 if (!cmd->cmd_cb) { 133 ser_err("no cmd_cb for cmd type:%d, id: %d", 134 cmd->cmd_type, 135 cmd->cmd_id); 136 goto error; 137 } 138 139 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 140 if (!pdev) { 141 ser_err("pdev is invalid"); 142 goto error; 143 } 144 145 ser_pdev_obj = 146 wlan_objmgr_pdev_get_comp_private_obj( 147 pdev, 148 WLAN_UMAC_COMP_SERIALIZATION); 149 if (!ser_pdev_obj) { 150 ser_err("Invalid ser_pdev_obj"); 151 goto error; 152 } 153 154 pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, 155 cmd->cmd_type); 156 if (!pdev_queue) { 157 ser_err("pdev_queue is invalid"); 158 goto error; 159 } 160 161 ser_debug("enqueue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 162 cmd->cmd_type, 163 cmd->cmd_id, 164 cmd->is_high_priority, 165 cmd->is_blocking); 166 167 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 168 169 active_queue = wlan_serialization_is_active_cmd_allowed(cmd); 170 171 if (wlan_serialization_is_cmd_present_queue(cmd, active_queue)) { 172 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 173 ser_err("duplicate command, can't enqueue"); 174 goto error; 175 } 176 177 if (wlan_serialization_remove_front( 178 &pdev_queue->cmd_pool_list, 179 &nnode) != QDF_STATUS_SUCCESS) { 180 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 181 ser_err("Failed to get cmd buffer from global pool"); 182 status = WLAN_SER_CMD_DENIED_LIST_FULL; 183 goto error; 184 } 185 186 ser_debug("Global pool node: %pK", nnode); 187 188 cmd_list = 189 qdf_container_of(nnode, 190 struct wlan_serialization_command_list, 191 pdev_node); 192 193 qdf_mem_copy(&cmd_list->cmd, cmd, 194 sizeof(struct wlan_serialization_command)); 195 196 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) { 197 status = wlan_ser_add_scan_cmd(ser_pdev_obj, 198 cmd_list, 199 active_queue); 200 } else { 201 status = wlan_ser_add_non_scan_cmd(ser_pdev_obj, 202 cmd_list, 203 active_queue); 204 } 205 206 if (status != WLAN_SER_CMD_PENDING && status != WLAN_SER_CMD_ACTIVE) { 207 ser_err("Failed to add cmd to active/pending queue"); 208 qdf_mem_zero(&cmd_list->cmd, 209 sizeof(struct wlan_serialization_command)); 210 wlan_serialization_insert_back( 211 &pdev_queue->cmd_pool_list, 212 &cmd_list->pdev_node); 213 } 214 215 if (WLAN_SER_CMD_ACTIVE == status) { 216 qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION, 217 &cmd_list->cmd_in_use); 218 } 219 220 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 221 222 if (WLAN_SER_CMD_ACTIVE == status) 223 wlan_serialization_activate_cmd(cmd_list, 224 ser_pdev_obj); 225 226 error: 227 ser_exit(); 228 229 return status; 230 } 231 232 QDF_STATUS wlan_serialization_activate_cmd( 233 struct wlan_serialization_command_list *cmd_list, 234 struct wlan_ser_pdev_obj *ser_pdev_obj) 235 { 236 QDF_STATUS status = QDF_STATUS_E_FAILURE; 237 struct wlan_objmgr_psoc *psoc = NULL; 238 struct wlan_serialization_pdev_queue *pdev_queue; 239 240 pdev_queue = wlan_serialization_get_pdev_queue_obj( 241 ser_pdev_obj, cmd_list->cmd.cmd_type); 242 243 psoc = wlan_vdev_get_psoc(cmd_list->cmd.vdev); 244 if (!psoc) { 245 ser_err("invalid psoc"); 246 goto error; 247 } 248 249 /* 250 * command is already pushed to active queue above 251 * now start the timer and notify requestor 252 */ 253 wlan_serialization_find_and_start_timer(psoc, &cmd_list->cmd); 254 /* 255 * Remember that serialization module may send 256 * this callback in same context through which it 257 * received the serialization request. Due to which 258 * it is caller's responsibility to ensure acquiring 259 * and releasing its own lock appropriately. 260 */ 261 262 ser_debug("cmd cb: type[%d] id[%d] : reason: %s", 263 cmd_list->cmd.cmd_type, 264 cmd_list->cmd.cmd_id, 265 "WLAN_SER_CB_ACTIVATE_CMD"); 266 267 status = cmd_list->cmd.cmd_cb(&cmd_list->cmd, 268 WLAN_SER_CB_ACTIVATE_CMD); 269 270 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 271 272 qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION, 273 &cmd_list->cmd_in_use); 274 qdf_atomic_set_bit(CMD_IS_ACTIVE, 275 &cmd_list->cmd_in_use); 276 277 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 278 279 if (QDF_IS_STATUS_ERROR(status)) 280 wlan_serialization_dequeue_cmd(&cmd_list->cmd, true); 281 282 error: 283 return status; 284 } 285 286 bool 287 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd) 288 { 289 struct wlan_objmgr_pdev *pdev; 290 bool active_cmd_allowed = 0; 291 292 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 293 if (!pdev) { 294 ser_err("NULL pdev"); 295 goto error; 296 } 297 298 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 299 active_cmd_allowed = 300 wlan_serialization_is_active_scan_cmd_allowed(cmd); 301 else 302 active_cmd_allowed = 303 wlan_serialization_is_active_non_scan_cmd_allowed(cmd); 304 305 ser_debug("active cmd_type[%d] cmd_id[%d] allowed: %d", 306 cmd->cmd_type, 307 cmd->cmd_id, 308 active_cmd_allowed); 309 310 error: 311 return active_cmd_allowed; 312 } 313 314 enum wlan_serialization_status 315 wlan_serialization_move_pending_to_active( 316 enum wlan_serialization_cmd_type cmd_type, 317 struct wlan_ser_pdev_obj *ser_pdev_obj, 318 struct wlan_objmgr_vdev *vdev, 319 bool blocking_cmd_removed) 320 { 321 enum wlan_serialization_status status; 322 323 if (cmd_type < WLAN_SER_CMD_NONSCAN) { 324 status = 325 wlan_ser_move_scan_pending_to_active( 326 ser_pdev_obj); 327 } else { 328 status = 329 wlan_ser_move_non_scan_pending_to_active( 330 ser_pdev_obj, 331 vdev, 332 blocking_cmd_removed); 333 } 334 335 return status; 336 } 337 338 enum wlan_serialization_cmd_status 339 wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd, 340 uint8_t active_cmd) 341 { 342 enum wlan_serialization_cmd_status status = 343 WLAN_SER_CMD_NOT_FOUND; 344 enum wlan_serialization_status ser_status = 345 WLAN_SER_CMD_DENIED_UNSPECIFIED; 346 347 QDF_STATUS qdf_status; 348 struct wlan_objmgr_pdev *pdev; 349 struct wlan_objmgr_psoc *psoc; 350 struct wlan_ser_pdev_obj *ser_pdev_obj; 351 struct wlan_serialization_command cmd_bkup; 352 struct wlan_serialization_command_list *cmd_list; 353 struct wlan_serialization_pdev_queue *pdev_queue; 354 bool blocking_cmd_removed = 0; 355 356 ser_enter(); 357 358 if (!cmd) { 359 ser_err("NULL command"); 360 goto error; 361 } 362 363 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 364 if (!pdev) { 365 ser_err("invalid pdev"); 366 goto error; 367 } 368 369 psoc = wlan_pdev_get_psoc(pdev); 370 if (!psoc) { 371 ser_err("invalid psoc"); 372 goto error; 373 } 374 375 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 376 if (!ser_pdev_obj) { 377 ser_err("ser_pdev_obj is empty"); 378 goto error; 379 } 380 381 pdev_queue = wlan_serialization_get_pdev_queue_obj( 382 ser_pdev_obj, cmd->cmd_type); 383 384 ser_debug("dequeue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 385 cmd->cmd_type, 386 cmd->cmd_id, 387 cmd->is_high_priority, 388 cmd->is_blocking); 389 390 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 391 392 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 393 qdf_status = wlan_ser_remove_scan_cmd( 394 ser_pdev_obj, &cmd_list, cmd, active_cmd); 395 else { 396 qdf_status = wlan_ser_remove_non_scan_cmd( 397 ser_pdev_obj, &cmd_list, cmd, active_cmd); 398 } 399 400 if (qdf_status != QDF_STATUS_SUCCESS) { 401 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 402 status = WLAN_SER_CMD_NOT_FOUND; 403 goto error; 404 } 405 406 if (active_cmd) { 407 if (cmd_list->cmd.cmd_type >= WLAN_SER_CMD_NONSCAN) 408 blocking_cmd_removed = cmd_list->cmd.is_blocking; 409 } 410 411 if (active_cmd) 412 wlan_serialization_find_and_stop_timer(psoc, &cmd_list->cmd); 413 414 qdf_mem_copy(&cmd_bkup, &cmd_list->cmd, 415 sizeof(struct wlan_serialization_command)); 416 qdf_mem_zero(&cmd_list->cmd, 417 sizeof(struct wlan_serialization_command)); 418 qdf_status = wlan_serialization_insert_back( 419 &pdev_queue->cmd_pool_list, 420 &cmd_list->pdev_node); 421 422 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 423 424 /* Call cmd cb for remove request*/ 425 if (cmd_bkup.cmd_cb) { 426 /* caller should release the memory */ 427 ser_debug("cmd cb: type[%d] id[%d]: reason: %s", 428 cmd_bkup.cmd_type, 429 cmd_bkup.cmd_id, 430 "WLAN_SER_CB_RELEASE_MEM_CMD"); 431 cmd_bkup.cmd_cb(&cmd_bkup, 432 WLAN_SER_CB_RELEASE_MEM_CMD); 433 } 434 435 if (active_cmd) { 436 ser_status = wlan_serialization_move_pending_to_active( 437 cmd_bkup.cmd_type, ser_pdev_obj, 438 cmd_bkup.vdev, 439 blocking_cmd_removed); 440 } 441 442 if (active_cmd) 443 status = WLAN_SER_CMD_IN_ACTIVE_LIST; 444 else 445 status = WLAN_SER_CMD_IN_PENDING_LIST; 446 447 error: 448 ser_exit(); 449 return status; 450 } 451 452 void wlan_serialization_generic_timer_cb(void *arg) 453 { 454 struct wlan_serialization_timer *timer = arg; 455 struct wlan_serialization_command *cmd = timer->cmd; 456 457 if (!cmd) { 458 ser_err("command not found"); 459 QDF_ASSERT(0); 460 return; 461 } 462 463 ser_err("active cmd timeout for cmd_type[%d] vdev[%pK]", 464 cmd->cmd_type, cmd->vdev); 465 466 if (cmd->cmd_cb) 467 cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT); 468 469 /* 470 * dequeue cmd API will cleanup and destroy the timer. If it fails to 471 * dequeue command then we have to destroy the timer. 472 */ 473 wlan_serialization_dequeue_cmd(cmd, true); 474 } 475 476 static QDF_STATUS wlan_serialization_mc_flush_noop(struct scheduler_msg *msg) 477 { 478 return QDF_STATUS_SUCCESS; 479 } 480 481 static void 482 wlan_serialization_timer_cb_mc_ctx(void *arg) 483 { 484 struct scheduler_msg msg = {0}; 485 486 msg.type = SYS_MSG_ID_MC_TIMER; 487 msg.reserved = SYS_MSG_COOKIE; 488 msg.callback = wlan_serialization_generic_timer_cb; 489 msg.bodyptr = arg; 490 msg.bodyval = 0; 491 msg.flush_callback = wlan_serialization_mc_flush_noop; 492 493 if (scheduler_post_msg(QDF_MODULE_ID_SYS, &msg) == QDF_STATUS_SUCCESS) 494 return; 495 496 ser_err("Could not enqueue timer to timer queue"); 497 } 498 499 #ifdef CONFIG_MCL 500 static void wlan_serialization_timer_handler(void *arg) 501 { 502 ser_enter(); 503 504 wlan_serialization_timer_cb_mc_ctx(arg); 505 506 ser_exit(); 507 } 508 #else 509 static void wlan_serialization_timer_handler(void *arg) 510 { 511 struct wlan_serialization_timer *timer = arg; 512 struct wlan_serialization_command *cmd = timer->cmd; 513 514 if (!cmd) { 515 ser_err("command not found"); 516 QDF_ASSERT(0); 517 return; 518 } 519 520 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 521 wlan_serialization_timer_cb_mc_ctx(arg); 522 else 523 wlan_serialization_generic_timer_cb(arg); 524 } 525 #endif 526 527 QDF_STATUS 528 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc, 529 struct wlan_serialization_command *cmd) 530 { 531 struct wlan_ser_psoc_obj *psoc_ser_obj; 532 struct wlan_serialization_timer *ser_timer; 533 QDF_STATUS status = QDF_STATUS_E_FAILURE; 534 int i = 0; 535 uint32_t phy_version; 536 537 if (!psoc || !cmd) { 538 ser_err("invalid param"); 539 goto exit; 540 } 541 542 if (cmd->cmd_timeout_duration == 0) { 543 phy_version = wlan_psoc_get_nif_phy_version(psoc); 544 if (wlan_is_emulation_platform(phy_version)) { 545 ser_err("[SCAN-EMULATION]: Not performing timer funcs"); 546 status = QDF_STATUS_SUCCESS; 547 goto exit; 548 } 549 } 550 551 psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); 552 /* 553 * Here cmd_id and cmd_type are used to locate the timer being 554 * associated with command. 555 */ 556 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); 557 558 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 559 ser_timer = &psoc_ser_obj->timers[i]; 560 if (!(ser_timer->cmd) || 561 (ser_timer->cmd->cmd_id != cmd->cmd_id) || 562 (ser_timer->cmd->cmd_type != cmd->cmd_type) || 563 (ser_timer->cmd->vdev != cmd->vdev)) 564 continue; 565 566 status = QDF_STATUS_SUCCESS; 567 break; 568 } 569 570 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); 571 572 if (QDF_IS_STATUS_SUCCESS(status)) { 573 status = wlan_serialization_stop_timer(ser_timer); 574 ser_debug("\n Stopping timer for cmd type:%d, id: %d", 575 cmd->cmd_type, cmd->cmd_id); 576 } else { 577 ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type); 578 } 579 580 exit: 581 return status; 582 } 583 584 QDF_STATUS 585 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc, 586 struct wlan_serialization_command *cmd) 587 { 588 QDF_STATUS status = QDF_STATUS_E_FAILURE; 589 struct wlan_ser_psoc_obj *psoc_ser_obj; 590 struct wlan_serialization_timer *ser_timer; 591 int i = 0; 592 uint32_t nif_phy_ver; 593 594 if (!psoc || !cmd) { 595 ser_err("invalid param"); 596 goto error; 597 } 598 599 nif_phy_ver = wlan_psoc_get_nif_phy_version(psoc); 600 if ((cmd->cmd_timeout_duration == 0) && 601 (wlan_is_emulation_platform(nif_phy_ver))) { 602 ser_err("[SCAN-EMULATION]: Not performing timer functions\n"); 603 status = QDF_STATUS_SUCCESS; 604 goto exit; 605 } 606 607 psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); 608 609 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); 610 611 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 612 /* Keep trying timer */ 613 ser_timer = &psoc_ser_obj->timers[i]; 614 if (ser_timer->cmd) 615 continue; 616 617 /* Remember timer is pointing to command */ 618 ser_timer->cmd = cmd; 619 status = QDF_STATUS_SUCCESS; 620 break; 621 } 622 623 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); 624 625 if (QDF_IS_STATUS_SUCCESS(status)) { 626 qdf_timer_init(NULL, 627 &ser_timer->timer, 628 wlan_serialization_timer_handler, 629 ser_timer, 630 QDF_TIMER_TYPE_SW); 631 qdf_timer_mod(&ser_timer->timer, 632 cmd->cmd_timeout_duration); 633 634 ser_debug("starting timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 635 cmd->cmd_type, 636 cmd->cmd_id, 637 cmd->is_high_priority, 638 cmd->is_blocking); 639 } 640 641 error: 642 exit: 643 644 return status; 645 } 646 647 enum wlan_serialization_cmd_status 648 wlan_serialization_cmd_cancel_handler( 649 struct wlan_ser_pdev_obj *ser_obj, 650 struct wlan_serialization_command *cmd, 651 struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, 652 enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type) 653 { 654 enum wlan_serialization_cmd_status active_status = 655 WLAN_SER_CMD_NOT_FOUND; 656 enum wlan_serialization_cmd_status pending_status = 657 WLAN_SER_CMD_NOT_FOUND; 658 enum wlan_serialization_cmd_status status = 659 WLAN_SER_CMD_NOT_FOUND; 660 661 ser_enter(); 662 663 if (!ser_obj) { 664 ser_err("invalid serial object"); 665 goto error; 666 } 667 668 if (queue_type & WLAN_SERIALIZATION_ACTIVE_QUEUE) { 669 if (cmd_type < WLAN_SER_CMD_NONSCAN) 670 active_status = wlan_ser_cancel_scan_cmd( 671 ser_obj, pdev, vdev, cmd, 672 cmd_type, true); 673 else 674 active_status = wlan_ser_cancel_non_scan_cmd( 675 ser_obj, pdev, vdev, cmd, 676 cmd_type, true); 677 } 678 679 if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) { 680 if (cmd_type < WLAN_SER_CMD_NONSCAN) 681 pending_status = wlan_ser_cancel_scan_cmd( 682 ser_obj, pdev, vdev, cmd, 683 cmd_type, false); 684 else 685 pending_status = wlan_ser_cancel_non_scan_cmd( 686 ser_obj, pdev, vdev, cmd, 687 cmd_type, false); 688 } 689 690 if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST && 691 pending_status == WLAN_SER_CMD_IN_PENDING_LIST) 692 status = WLAN_SER_CMDS_IN_ALL_LISTS; 693 else if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST) 694 status = active_status; 695 else if (pending_status == WLAN_SER_CMD_IN_PENDING_LIST) 696 status = pending_status; 697 698 error: 699 ser_exit(); 700 return status; 701 } 702 703 enum wlan_serialization_cmd_status 704 wlan_serialization_find_and_cancel_cmd( 705 struct wlan_serialization_command *cmd, 706 enum wlan_serialization_cancel_type req_type, 707 uint8_t queue_type) 708 { 709 enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND; 710 struct wlan_ser_pdev_obj *ser_obj = NULL; 711 struct wlan_objmgr_pdev *pdev; 712 713 ser_enter(); 714 715 if (!cmd) { 716 ser_err("Invalid cmd"); 717 goto error; 718 } 719 720 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 721 if (!pdev) { 722 ser_err("Invalid pdev"); 723 goto error; 724 } 725 ser_obj = wlan_serialization_get_pdev_obj(pdev); 726 if (!ser_obj) { 727 ser_err("Invalid ser_obj"); 728 goto error; 729 } 730 731 switch (req_type) { 732 case WLAN_SER_CANCEL_SINGLE_SCAN: 733 /* remove scan cmd which matches the given cmd struct */ 734 status = wlan_serialization_cmd_cancel_handler(ser_obj, 735 cmd, 736 NULL, 737 NULL, 738 cmd->cmd_type, 739 queue_type); 740 break; 741 case WLAN_SER_CANCEL_PDEV_SCANS: 742 /* remove all scan cmds which matches the pdev object */ 743 status = wlan_serialization_cmd_cancel_handler( 744 ser_obj, 745 NULL, 746 wlan_vdev_get_pdev(cmd->vdev), 747 NULL, 748 cmd->cmd_type, 749 queue_type); 750 break; 751 case WLAN_SER_CANCEL_VDEV_SCANS: 752 /* remove all scan cmds which matches the vdev object */ 753 status = wlan_serialization_cmd_cancel_handler(ser_obj, 754 NULL, NULL, 755 cmd->vdev, 756 cmd->cmd_type, 757 queue_type); 758 break; 759 case WLAN_SER_CANCEL_NON_SCAN_CMD: 760 /* remove nonscan cmd which matches the given cmd */ 761 status = wlan_serialization_cmd_cancel_handler(ser_obj, 762 cmd, 763 NULL, 764 NULL, 765 cmd->cmd_type, 766 queue_type); 767 break; 768 case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD: 769 /* remove all non scan cmds which matches the pdev object */ 770 status = wlan_serialization_cmd_cancel_handler( 771 ser_obj, 772 NULL, 773 wlan_vdev_get_pdev(cmd->vdev), 774 NULL, 775 cmd->cmd_type, 776 queue_type); 777 break; 778 case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD: 779 /* remove all non scan cmds which matches the vdev object */ 780 status = wlan_serialization_cmd_cancel_handler(ser_obj, 781 NULL, NULL, 782 cmd->vdev, 783 cmd->cmd_type, 784 queue_type); 785 break; 786 default: 787 ser_err("Invalid request"); 788 } 789 790 error: 791 ser_exit(); 792 return status; 793 } 794