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); 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); 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); 181 ser_err("Failed to get cmd buffer from global pool"); 182 goto error; 183 } 184 185 ser_debug("Global pool node: %pK", nnode); 186 187 cmd_list = 188 qdf_container_of(nnode, 189 struct wlan_serialization_command_list, 190 pdev_node); 191 192 qdf_mem_copy(&cmd_list->cmd, cmd, 193 sizeof(struct wlan_serialization_command)); 194 195 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) { 196 status = wlan_ser_add_scan_cmd(ser_pdev_obj, 197 cmd_list, 198 active_queue); 199 } else { 200 status = wlan_ser_add_non_scan_cmd(ser_pdev_obj, 201 cmd_list, 202 active_queue); 203 } 204 205 if (status != WLAN_SER_CMD_PENDING && status != WLAN_SER_CMD_ACTIVE) { 206 ser_err("Failed to add cmd to active/pending queue"); 207 qdf_mem_zero(&cmd_list->cmd, 208 sizeof(struct wlan_serialization_command)); 209 wlan_serialization_insert_back( 210 &pdev_queue->cmd_pool_list, 211 &cmd_list->pdev_node); 212 } 213 214 if (WLAN_SER_CMD_ACTIVE == status) { 215 qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION, 216 &cmd_list->cmd_in_use); 217 } 218 219 wlan_serialization_release_lock(pdev_queue); 220 221 if (WLAN_SER_CMD_ACTIVE == status) 222 wlan_serialization_activate_cmd(cmd_list, 223 ser_pdev_obj); 224 225 error: 226 ser_exit(); 227 228 return status; 229 } 230 231 QDF_STATUS 232 wlan_serialization_activate_multiple_cmd( 233 struct wlan_ser_pdev_obj *ser_pdev_obj) 234 { 235 struct wlan_serialization_pdev_queue *pdev_queue; 236 qdf_list_t *active_queue; 237 QDF_STATUS peek_status = QDF_STATUS_E_FAILURE; 238 struct wlan_serialization_command_list *active_cmd_list; 239 uint32_t qsize; 240 uint32_t vdev_id; 241 qdf_list_node_t *nnode = NULL; 242 QDF_STATUS status = QDF_STATUS_SUCCESS; 243 struct wlan_objmgr_psoc *psoc = NULL; 244 245 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 246 active_queue = &pdev_queue->active_list; 247 248 qsize = wlan_serialization_list_size(active_queue); 249 while (qsize--) { 250 peek_status = wlan_serialization_get_cmd_from_queue( 251 active_queue, &nnode); 252 253 if (peek_status != QDF_STATUS_SUCCESS) { 254 ser_err("can't peek cmd"); 255 break; 256 } 257 258 active_cmd_list = qdf_container_of( 259 nnode, struct wlan_serialization_command_list, 260 pdev_node); 261 262 if (!qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION, 263 &active_cmd_list->cmd_in_use)) { 264 continue; 265 } 266 267 /* 268 * Command is already pushed to active queue. 269 * Now start the timer. 270 */ 271 psoc = wlan_vdev_get_psoc(active_cmd_list->cmd.vdev); 272 wlan_serialization_find_and_start_timer(psoc, 273 &active_cmd_list->cmd); 274 275 ser_debug("cmd cb: type[%d] id[%d] : reason: %s", 276 active_cmd_list->cmd.cmd_type, 277 active_cmd_list->cmd.cmd_id, 278 "WLAN_SER_CB_ACTIVATE_CMD"); 279 280 status = active_cmd_list->cmd.cmd_cb(&active_cmd_list->cmd, 281 WLAN_SER_CB_ACTIVATE_CMD); 282 283 qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION, 284 &active_cmd_list->cmd_in_use); 285 286 qdf_atomic_set_bit(CMD_IS_ACTIVE, 287 &active_cmd_list->cmd_in_use); 288 289 vdev_id = wlan_vdev_get_id(active_cmd_list->cmd.vdev); 290 pdev_queue->vdev_active_cmd_bitmap |= (1 << vdev_id); 291 292 if (active_cmd_list->cmd.is_blocking) 293 pdev_queue->blocking_cmd_active = 1; 294 295 if (QDF_IS_STATUS_ERROR(status)) 296 wlan_serialization_dequeue_cmd(&active_cmd_list->cmd, 297 true); 298 } 299 return status; 300 } 301 302 QDF_STATUS wlan_serialization_activate_cmd( 303 struct wlan_serialization_command_list *cmd_list, 304 struct wlan_ser_pdev_obj *ser_pdev_obj) 305 { 306 QDF_STATUS status = QDF_STATUS_E_FAILURE; 307 struct wlan_objmgr_psoc *psoc = NULL; 308 309 psoc = wlan_vdev_get_psoc(cmd_list->cmd.vdev); 310 if (!psoc) { 311 ser_err("invalid psoc"); 312 goto error; 313 } 314 315 /* 316 * command is already pushed to active queue above 317 * now start the timer and notify requestor 318 */ 319 wlan_serialization_find_and_start_timer(psoc, &cmd_list->cmd); 320 /* 321 * Remember that serialization module may send 322 * this callback in same context through which it 323 * received the serialization request. Due to which 324 * it is caller's responsibility to ensure acquiring 325 * and releasing its own lock appropriately. 326 */ 327 328 ser_debug("cmd cb: type[%d] id[%d] : reason: %s", 329 cmd_list->cmd.cmd_type, 330 cmd_list->cmd.cmd_id, 331 "WLAN_SER_CB_ACTIVATE_CMD"); 332 333 status = cmd_list->cmd.cmd_cb(&cmd_list->cmd, 334 WLAN_SER_CB_ACTIVATE_CMD); 335 336 qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION, 337 &cmd_list->cmd_in_use); 338 qdf_atomic_set_bit(CMD_IS_ACTIVE, 339 &cmd_list->cmd_in_use); 340 341 if (QDF_IS_STATUS_ERROR(status)) 342 wlan_serialization_dequeue_cmd(&cmd_list->cmd, true); 343 344 error: 345 return status; 346 } 347 348 bool 349 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd) 350 { 351 struct wlan_objmgr_pdev *pdev; 352 bool active_cmd_allowed = 0; 353 354 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 355 if (!pdev) { 356 ser_err("NULL pdev"); 357 goto error; 358 } 359 360 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 361 active_cmd_allowed = 362 wlan_serialization_is_active_scan_cmd_allowed(cmd); 363 else 364 active_cmd_allowed = 365 wlan_serialization_is_active_non_scan_cmd_allowed(cmd); 366 367 ser_debug("active cmd_type[%d] cmd_id[%d] allowed: %d", 368 cmd->cmd_type, 369 cmd->cmd_id, 370 active_cmd_allowed); 371 372 error: 373 return active_cmd_allowed; 374 } 375 376 enum wlan_serialization_status 377 wlan_serialization_move_pending_to_active( 378 enum wlan_serialization_cmd_type cmd_type, 379 struct wlan_serialization_command_list **pcmd_list, 380 struct wlan_ser_pdev_obj *ser_pdev_obj, 381 struct wlan_objmgr_vdev *vdev, 382 bool blocking_cmd_removed, 383 bool blocking_cmd_waiting) 384 { 385 enum wlan_serialization_status status; 386 struct wlan_serialization_pdev_queue *pdev_queue; 387 388 if (cmd_type < WLAN_SER_CMD_NONSCAN) { 389 status = 390 wlan_ser_move_scan_pending_to_active( 391 pcmd_list, 392 ser_pdev_obj); 393 } else { 394 pdev_queue = 395 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 396 397 if (!blocking_cmd_removed && !blocking_cmd_waiting) 398 status = 399 wlan_ser_move_non_scan_pending_to_active( 400 pcmd_list, 401 ser_pdev_obj, 402 vdev); 403 else 404 status = 405 wlan_ser_move_multiple_non_scan_pending_to_active( 406 ser_pdev_obj); 407 } 408 409 return status; 410 } 411 412 enum wlan_serialization_cmd_status 413 wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd, 414 uint8_t active_cmd) 415 { 416 enum wlan_serialization_cmd_status status = 417 WLAN_SER_CMD_NOT_FOUND; 418 enum wlan_serialization_status ser_status = 419 WLAN_SER_CMD_DENIED_UNSPECIFIED; 420 421 QDF_STATUS qdf_status; 422 struct wlan_objmgr_pdev *pdev; 423 struct wlan_objmgr_psoc *psoc; 424 struct wlan_ser_pdev_obj *ser_pdev_obj; 425 struct wlan_serialization_command cmd_bkup; 426 struct wlan_serialization_command_list *cmd_list; 427 struct wlan_serialization_command_list *pcmd_list; 428 struct wlan_serialization_pdev_queue *pdev_queue; 429 bool blocking_cmd_removed = 0; 430 bool blocking_cmd_waiting = 0; 431 432 ser_enter(); 433 434 if (!cmd) { 435 ser_err("NULL command"); 436 goto error; 437 } 438 439 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 440 if (!pdev) { 441 ser_err("invalid pdev"); 442 goto error; 443 } 444 445 psoc = wlan_pdev_get_psoc(pdev); 446 if (!psoc) { 447 ser_err("invalid psoc"); 448 goto error; 449 } 450 451 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 452 if (!ser_pdev_obj) { 453 ser_err("ser_pdev_obj is empty"); 454 goto error; 455 } 456 457 pdev_queue = wlan_serialization_get_pdev_queue_obj( 458 ser_pdev_obj, cmd->cmd_type); 459 460 ser_debug("dequeue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 461 cmd->cmd_type, 462 cmd->cmd_id, 463 cmd->is_high_priority, 464 cmd->is_blocking); 465 466 wlan_serialization_acquire_lock(pdev_queue); 467 468 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 469 qdf_status = wlan_ser_remove_scan_cmd( 470 ser_pdev_obj, &cmd_list, cmd, active_cmd); 471 else { 472 qdf_status = wlan_ser_remove_non_scan_cmd( 473 ser_pdev_obj, &cmd_list, cmd, active_cmd); 474 } 475 476 if (qdf_status != QDF_STATUS_SUCCESS) { 477 wlan_serialization_release_lock(pdev_queue); 478 status = WLAN_SER_CMD_NOT_FOUND; 479 goto error; 480 } 481 482 if (active_cmd) { 483 wlan_serialization_find_and_stop_timer(psoc, &cmd_list->cmd); 484 485 if (cmd_list->cmd.cmd_type >= WLAN_SER_CMD_NONSCAN) 486 blocking_cmd_removed = cmd_list->cmd.is_blocking; 487 } 488 489 qdf_mem_copy(&cmd_bkup, &cmd_list->cmd, 490 sizeof(struct wlan_serialization_command)); 491 qdf_mem_zero(&cmd_list->cmd, 492 sizeof(struct wlan_serialization_command)); 493 qdf_status = wlan_serialization_insert_back( 494 &pdev_queue->cmd_pool_list, 495 &cmd_list->pdev_node); 496 497 /* 498 * For NON SCAN commands, the following is possible: 499 * 500 * If the remove is for non blocking command, 501 * and there is no blocking command waiting, 502 * look at vdev pending queue and 503 * only one command moves from pending 504 * to active 505 * 506 * If the remove is for blocking comamnd, 507 * look at the pdev queue and 508 * either single blocking command 509 * or multiple non blocking commands moves 510 * from pending to active 511 */ 512 513 blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting; 514 515 if (active_cmd) { 516 ser_status = wlan_serialization_move_pending_to_active( 517 cmd_bkup.cmd_type, &pcmd_list, ser_pdev_obj, 518 cmd_bkup.vdev, 519 blocking_cmd_removed, 520 blocking_cmd_waiting); 521 } 522 523 wlan_serialization_release_lock(pdev_queue); 524 525 /* Call cmd cb for remove request*/ 526 if (cmd_bkup.cmd_cb) { 527 /* caller should release the memory */ 528 ser_debug("cmd cb: type[%d] id[%d]: reason: %s", 529 cmd_bkup.cmd_type, 530 cmd_bkup.cmd_id, 531 "WLAN_SER_CB_RELEASE_MEM_CMD"); 532 cmd_bkup.cmd_cb(&cmd_bkup, 533 WLAN_SER_CB_RELEASE_MEM_CMD); 534 } 535 536 /* 537 * If the remove is for non blocking command, 538 * and there is no blocking command waiting, 539 * look at vdev pending queue and 540 * only one command moves from pending 541 * to active and gets activated 542 */ 543 if (WLAN_SER_CMD_ACTIVE == ser_status && !blocking_cmd_removed && 544 !blocking_cmd_waiting) { 545 ser_debug("cmd type[%d] id[%d] moved from pending to active", 546 pcmd_list->cmd.cmd_type, 547 pcmd_list->cmd.cmd_id); 548 wlan_serialization_activate_cmd(pcmd_list, 549 ser_pdev_obj); 550 } else if (ser_status == WLAN_SER_CMD_ACTIVE) { 551 /* If the remove is for blocking command 552 * either one or multiple commands can move 553 * from pending to active and gets activated 554 */ 555 wlan_serialization_activate_multiple_cmd(ser_pdev_obj); 556 } else { 557 goto exit; 558 } 559 560 exit: 561 if (active_cmd) 562 status = WLAN_SER_CMD_IN_ACTIVE_LIST; 563 else 564 status = WLAN_SER_CMD_IN_PENDING_LIST; 565 566 error: 567 ser_exit(); 568 return status; 569 } 570 571 void wlan_serialization_generic_timer_cb(void *arg) 572 { 573 struct wlan_serialization_timer *timer = arg; 574 struct wlan_serialization_command *cmd = timer->cmd; 575 576 if (!cmd) { 577 ser_err("command not found"); 578 QDF_ASSERT(0); 579 return; 580 } 581 582 ser_err("active cmd timeout for cmd_type[%d] vdev[%pK]", 583 cmd->cmd_type, cmd->vdev); 584 585 if (cmd->cmd_cb) 586 cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT); 587 588 /* 589 * dequeue cmd API will cleanup and destroy the timer. If it fails to 590 * dequeue command then we have to destroy the timer. 591 */ 592 wlan_serialization_dequeue_cmd(cmd, true); 593 } 594 595 static QDF_STATUS wlan_serialization_mc_flush_noop(struct scheduler_msg *msg) 596 { 597 return QDF_STATUS_SUCCESS; 598 } 599 600 static void 601 wlan_serialization_timer_cb_mc_ctx(void *arg) 602 { 603 struct scheduler_msg msg = {0}; 604 605 msg.type = SYS_MSG_ID_MC_TIMER; 606 msg.reserved = SYS_MSG_COOKIE; 607 msg.callback = wlan_serialization_generic_timer_cb; 608 msg.bodyptr = arg; 609 msg.bodyval = 0; 610 msg.flush_callback = wlan_serialization_mc_flush_noop; 611 612 if (scheduler_post_msg(QDF_MODULE_ID_SYS, &msg) == QDF_STATUS_SUCCESS) 613 return; 614 615 ser_err("Could not enqueue timer to timer queue"); 616 } 617 618 #ifdef CONFIG_MCL 619 static void wlan_serialization_timer_handler(void *arg) 620 { 621 ser_enter(); 622 623 wlan_serialization_timer_cb_mc_ctx(arg); 624 625 ser_exit(); 626 } 627 #else 628 static void wlan_serialization_timer_handler(void *arg) 629 { 630 struct wlan_serialization_timer *timer = arg; 631 struct wlan_serialization_command *cmd = timer->cmd; 632 633 if (!cmd) { 634 ser_err("command not found"); 635 QDF_ASSERT(0); 636 return; 637 } 638 639 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 640 wlan_serialization_timer_cb_mc_ctx(arg); 641 else 642 wlan_serialization_generic_timer_cb(arg); 643 } 644 #endif 645 646 QDF_STATUS 647 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc, 648 struct wlan_serialization_command *cmd) 649 { 650 struct wlan_ser_psoc_obj *psoc_ser_obj; 651 struct wlan_serialization_timer *ser_timer; 652 QDF_STATUS status = QDF_STATUS_E_FAILURE; 653 int i = 0; 654 uint32_t phy_version; 655 656 if (!psoc || !cmd) { 657 ser_err("invalid param"); 658 goto error; 659 } 660 661 if (cmd->cmd_timeout_duration == 0) { 662 phy_version = wlan_psoc_get_nif_phy_version(psoc); 663 if (wlan_is_emulation_platform(phy_version)) { 664 ser_err("[SCAN-EMULATION]: Not performing timer funcs"); 665 status = QDF_STATUS_SUCCESS; 666 goto exit; 667 } 668 } 669 670 psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); 671 /* 672 * Here cmd_id and cmd_type are used to locate the timer being 673 * associated with command. For scan command, cmd_id is expected to 674 * be unique and For non-scan command, there should be only one active 675 * command per pdev 676 */ 677 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 678 ser_timer = &psoc_ser_obj->timers[i]; 679 if (!(ser_timer->cmd) || 680 (ser_timer->cmd->cmd_id != cmd->cmd_id) || 681 (ser_timer->cmd->cmd_type != cmd->cmd_type) || 682 (ser_timer->cmd->vdev != cmd->vdev)) 683 continue; 684 status = wlan_serialization_stop_timer(ser_timer); 685 ser_debug("\n Stopping timer for cmd type:%d, id: %d", 686 cmd->cmd_type, cmd->cmd_id); 687 break; 688 } 689 690 if (QDF_STATUS_SUCCESS != status) 691 ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type); 692 693 error: 694 exit: 695 696 return status; 697 } 698 699 QDF_STATUS 700 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc, 701 struct wlan_serialization_command *cmd) 702 { 703 QDF_STATUS status = QDF_STATUS_E_FAILURE; 704 struct wlan_ser_psoc_obj *psoc_ser_obj; 705 struct wlan_serialization_timer *ser_timer; 706 int i = 0; 707 uint32_t nif_phy_ver; 708 709 if (!psoc || !cmd) { 710 ser_err("invalid param"); 711 goto error; 712 } 713 714 nif_phy_ver = wlan_psoc_get_nif_phy_version(psoc); 715 if ((cmd->cmd_timeout_duration == 0) && 716 (wlan_is_emulation_platform(nif_phy_ver))) { 717 ser_err("[SCAN-EMULATION]: Not performing timer functions\n"); 718 status = QDF_STATUS_SUCCESS; 719 goto exit; 720 } 721 722 psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); 723 724 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 725 /* Keep trying timer */ 726 ser_timer = &psoc_ser_obj->timers[i]; 727 if (ser_timer->cmd) 728 continue; 729 730 /* Remember timer is pointing to command */ 731 ser_timer->cmd = cmd; 732 qdf_timer_init(NULL, 733 &ser_timer->timer, 734 wlan_serialization_timer_handler, 735 ser_timer, 736 QDF_TIMER_TYPE_SW); 737 qdf_timer_mod(&ser_timer->timer, 738 cmd->cmd_timeout_duration); 739 740 ser_debug("starting timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 741 cmd->cmd_type, 742 cmd->cmd_id, 743 cmd->is_high_priority, 744 cmd->is_blocking); 745 746 status = QDF_STATUS_SUCCESS; 747 break; 748 } 749 750 error: 751 exit: 752 753 return status; 754 } 755 756 enum wlan_serialization_cmd_status 757 wlan_serialization_cmd_cancel_handler( 758 struct wlan_ser_pdev_obj *ser_obj, 759 struct wlan_serialization_command *cmd, 760 struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, 761 enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type) 762 { 763 enum wlan_serialization_cmd_status active_status = 764 WLAN_SER_CMD_NOT_FOUND; 765 enum wlan_serialization_cmd_status pending_status = 766 WLAN_SER_CMD_NOT_FOUND; 767 enum wlan_serialization_cmd_status status = 768 WLAN_SER_CMD_NOT_FOUND; 769 770 ser_enter(); 771 772 if (!ser_obj) { 773 ser_err("invalid serial object"); 774 goto error; 775 } 776 777 if (queue_type & WLAN_SERIALIZATION_ACTIVE_QUEUE) { 778 if (cmd_type < WLAN_SER_CMD_NONSCAN) 779 active_status = wlan_ser_cancel_scan_cmd( 780 ser_obj, pdev, vdev, cmd, 781 cmd_type, true); 782 else 783 active_status = wlan_ser_cancel_non_scan_cmd( 784 ser_obj, pdev, vdev, cmd, 785 cmd_type, true); 786 } 787 788 if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) { 789 if (cmd_type < WLAN_SER_CMD_NONSCAN) 790 pending_status = wlan_ser_cancel_scan_cmd( 791 ser_obj, pdev, vdev, cmd, 792 cmd_type, false); 793 else 794 pending_status = wlan_ser_cancel_non_scan_cmd( 795 ser_obj, pdev, vdev, cmd, 796 cmd_type, false); 797 } 798 799 if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST && 800 pending_status == WLAN_SER_CMD_IN_PENDING_LIST) 801 status = WLAN_SER_CMDS_IN_ALL_LISTS; 802 else if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST) 803 status = active_status; 804 else if (pending_status == WLAN_SER_CMD_IN_PENDING_LIST) 805 status = pending_status; 806 807 error: 808 ser_exit(); 809 return status; 810 } 811 812 enum wlan_serialization_cmd_status 813 wlan_serialization_find_and_cancel_cmd( 814 struct wlan_serialization_command *cmd, 815 enum wlan_serialization_cancel_type req_type, 816 uint8_t queue_type) 817 { 818 enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND; 819 struct wlan_ser_pdev_obj *ser_obj = NULL; 820 struct wlan_objmgr_pdev *pdev; 821 822 ser_enter(); 823 824 if (!cmd) { 825 ser_err("Invalid cmd"); 826 goto error; 827 } 828 829 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 830 if (!pdev) { 831 ser_err("Invalid pdev"); 832 goto error; 833 } 834 ser_obj = wlan_serialization_get_pdev_obj(pdev); 835 if (!ser_obj) { 836 ser_err("Invalid ser_obj"); 837 goto error; 838 } 839 840 switch (req_type) { 841 case WLAN_SER_CANCEL_SINGLE_SCAN: 842 /* remove scan cmd which matches the given cmd struct */ 843 status = wlan_serialization_cmd_cancel_handler(ser_obj, 844 cmd, 845 NULL, 846 NULL, 847 cmd->cmd_type, 848 queue_type); 849 break; 850 case WLAN_SER_CANCEL_PDEV_SCANS: 851 /* remove all scan cmds which matches the pdev object */ 852 status = wlan_serialization_cmd_cancel_handler( 853 ser_obj, 854 NULL, 855 wlan_vdev_get_pdev(cmd->vdev), 856 NULL, 857 cmd->cmd_type, 858 queue_type); 859 break; 860 case WLAN_SER_CANCEL_VDEV_SCANS: 861 /* remove all scan cmds which matches the vdev object */ 862 status = wlan_serialization_cmd_cancel_handler(ser_obj, 863 NULL, NULL, 864 cmd->vdev, 865 cmd->cmd_type, 866 queue_type); 867 break; 868 case WLAN_SER_CANCEL_NON_SCAN_CMD: 869 /* remove nonscan cmd which matches the given cmd */ 870 status = wlan_serialization_cmd_cancel_handler(ser_obj, 871 cmd, 872 NULL, 873 NULL, 874 cmd->cmd_type, 875 queue_type); 876 break; 877 case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD: 878 /* remove all non scan cmds which matches the pdev object */ 879 status = wlan_serialization_cmd_cancel_handler( 880 ser_obj, 881 NULL, 882 wlan_vdev_get_pdev(cmd->vdev), 883 NULL, 884 cmd->cmd_type, 885 queue_type); 886 break; 887 case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD: 888 /* remove all non scan cmds which matches the vdev object */ 889 status = wlan_serialization_cmd_cancel_handler(ser_obj, 890 NULL, NULL, 891 cmd->vdev, 892 cmd->cmd_type, 893 queue_type); 894 break; 895 default: 896 ser_err("Invalid request"); 897 } 898 899 error: 900 ser_exit(); 901 return status; 902 } 903