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 * 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 enum ser_queue_reason ser_reason) 91 { 92 enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 93 struct wlan_serialization_command_list *cmd_list; 94 qdf_list_node_t *nnode; 95 struct wlan_objmgr_pdev *pdev; 96 struct wlan_ser_pdev_obj *ser_pdev_obj; 97 struct wlan_serialization_pdev_queue *pdev_queue; 98 struct wlan_ser_vdev_obj *ser_vdev_obj; 99 struct wlan_serialization_vdev_queue *vdev_queue; 100 bool active_queue; 101 102 /* Enqueue process 103 * 1) peek through command structure and see what is the command type 104 * 2) two main types of commands to process 105 * a) SCAN 106 * b) NON-SCAN 107 * 3) for each command there are separate command queues per pdev 108 * 4) pull pdev from vdev structure and get the command queue associated 109 * with that pdev and try to enqueue on those queue 110 * 5) Thumb rule: 111 * a) There could be only 1 active non-scan command at a 112 * time including all total non-scan commands of all pdevs. 113 * 114 * example: pdev1 has 1 non-scan active command and 115 * pdev2 got 1 non-scan command then that command should go to 116 * pdev2's pending queue 117 * 118 * b) There could be only N number of scan commands at a time 119 * including all total scan commands of all pdevs 120 * 121 * example: Let's say N=8, 122 * pdev1's vdev1 has 5 scan command, pdev2's vdev1 has 3 123 * scan commands, if we get scan request on vdev2 then it will go 124 * to pending queue of vdev2 as we reached max allowed scan active 125 * command. 126 */ 127 128 ser_enter(); 129 130 if (!cmd) { 131 ser_err("NULL command"); 132 goto error; 133 } 134 135 if (!cmd->cmd_cb) { 136 ser_err("no cmd_cb for cmd type:%d, id: %d", 137 cmd->cmd_type, 138 cmd->cmd_id); 139 goto error; 140 } 141 142 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 143 if (!pdev) { 144 ser_err("pdev is invalid"); 145 goto error; 146 } 147 148 ser_pdev_obj = 149 wlan_objmgr_pdev_get_comp_private_obj( 150 pdev, 151 WLAN_UMAC_COMP_SERIALIZATION); 152 if (!ser_pdev_obj) { 153 ser_err("Invalid ser_pdev_obj"); 154 goto error; 155 } 156 157 pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, 158 cmd->cmd_type); 159 if (!pdev_queue) { 160 ser_err("pdev_queue is invalid"); 161 goto error; 162 } 163 164 ser_debug("enqueue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 165 cmd->cmd_type, 166 cmd->cmd_id, 167 cmd->is_high_priority, 168 cmd->is_blocking); 169 170 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 171 172 /* Before queuing any non scan command, 173 * as part of wlan_serialization_request, 174 * we check if the vdev queues are disabled. 175 * 176 * The serialization command structure has an 177 * attribute, where after a given command is queued, 178 * we can block the vdev queues. 179 * 180 * For example, after VDEV_DOWN command is queued as 181 * part of a vdev deletion, no other commands should be queued 182 * until the deletion is complete, so with VDEV_DOWN(in case of 183 * vdev deletion) with pass the attribute to disable vdev queues 184 */ 185 if (cmd->cmd_type > WLAN_SER_CMD_SCAN && 186 ser_reason == SER_REQUEST) { 187 ser_vdev_obj = 188 wlan_serialization_get_vdev_obj( 189 wlan_serialization_get_vdev_from_cmd(cmd)); 190 191 if (!ser_vdev_obj) { 192 wlan_serialization_release_lock( 193 &pdev_queue->pdev_queue_lock); 194 goto error; 195 } 196 197 vdev_queue = 198 wlan_serialization_get_vdev_queue_obj( 199 ser_vdev_obj, 200 cmd->cmd_type); 201 202 if (!vdev_queue) { 203 wlan_serialization_release_lock( 204 &pdev_queue->pdev_queue_lock); 205 goto error; 206 } 207 208 if (vdev_queue->queue_disable) { 209 wlan_serialization_release_lock( 210 &pdev_queue->pdev_queue_lock); 211 ser_err("VDEV queue is disabled, ser request denied"); 212 ser_err("cmd id[%d] cmd type[%d]", cmd->cmd_id, 213 cmd->cmd_type); 214 status = WLAN_SER_CMD_QUEUE_DISABLED; 215 goto error; 216 } 217 } 218 219 active_queue = wlan_serialization_is_active_cmd_allowed(cmd); 220 221 if (wlan_serialization_is_cmd_present_queue(cmd, active_queue)) { 222 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 223 ser_err("duplicate command, can't enqueue"); 224 goto error; 225 } 226 227 if (wlan_serialization_remove_front( 228 &pdev_queue->cmd_pool_list, 229 &nnode) != QDF_STATUS_SUCCESS) { 230 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 231 ser_err("Failed to get cmd buffer from global pool"); 232 status = WLAN_SER_CMD_DENIED_LIST_FULL; 233 goto error; 234 } 235 236 ser_debug("Global pool node: %pK", nnode); 237 238 cmd_list = 239 qdf_container_of(nnode, 240 struct wlan_serialization_command_list, 241 pdev_node); 242 243 qdf_mem_copy(&cmd_list->cmd, cmd, 244 sizeof(struct wlan_serialization_command)); 245 246 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) { 247 status = wlan_ser_add_scan_cmd(ser_pdev_obj, 248 cmd_list, 249 active_queue); 250 } else { 251 status = wlan_ser_add_non_scan_cmd(ser_pdev_obj, 252 cmd_list, 253 active_queue); 254 } 255 256 if (status != WLAN_SER_CMD_PENDING && status != WLAN_SER_CMD_ACTIVE) { 257 qdf_mem_zero(&cmd_list->cmd, 258 sizeof(struct wlan_serialization_command)); 259 wlan_serialization_insert_back( 260 &pdev_queue->cmd_pool_list, 261 &cmd_list->pdev_node); 262 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 263 ser_err("Failed to add cmd to active/pending queue"); 264 goto error; 265 } 266 267 if (WLAN_SER_CMD_ACTIVE == status) { 268 qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION, 269 &cmd_list->cmd_in_use); 270 } 271 272 wlan_ser_update_cmd_history(pdev_queue, &cmd_list->cmd, 273 ser_reason, true, active_queue); 274 275 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 276 277 if (WLAN_SER_CMD_ACTIVE == status) 278 wlan_serialization_activate_cmd(cmd_list, 279 ser_pdev_obj, ser_reason); 280 281 error: 282 ser_exit(); 283 284 return status; 285 } 286 287 QDF_STATUS wlan_serialization_activate_cmd( 288 struct wlan_serialization_command_list *cmd_list, 289 struct wlan_ser_pdev_obj *ser_pdev_obj, 290 enum ser_queue_reason ser_reason) 291 { 292 QDF_STATUS status = QDF_STATUS_E_FAILURE; 293 struct wlan_objmgr_psoc *psoc = NULL; 294 struct wlan_serialization_pdev_queue *pdev_queue; 295 296 pdev_queue = wlan_serialization_get_pdev_queue_obj( 297 ser_pdev_obj, cmd_list->cmd.cmd_type); 298 299 psoc = wlan_vdev_get_psoc(cmd_list->cmd.vdev); 300 if (!psoc) { 301 ser_err("invalid psoc"); 302 goto error; 303 } 304 305 /* 306 * command is already pushed to active queue above 307 * now start the timer and notify requestor 308 */ 309 wlan_serialization_find_and_start_timer(psoc, &cmd_list->cmd); 310 /* 311 * Remember that serialization module may send 312 * this callback in same context through which it 313 * received the serialization request. Due to which 314 * it is caller's responsibility to ensure acquiring 315 * and releasing its own lock appropriately. 316 */ 317 318 ser_debug("cmd cb: type[%d] id[%d] : reason: %s", 319 cmd_list->cmd.cmd_type, 320 cmd_list->cmd.cmd_id, 321 "WLAN_SER_CB_ACTIVATE_CMD"); 322 323 cmd_list->cmd.activation_reason = ser_reason; 324 325 status = cmd_list->cmd.cmd_cb(&cmd_list->cmd, 326 WLAN_SER_CB_ACTIVATE_CMD); 327 328 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 329 330 qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION, 331 &cmd_list->cmd_in_use); 332 qdf_atomic_set_bit(CMD_IS_ACTIVE, 333 &cmd_list->cmd_in_use); 334 335 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 336 337 if (QDF_IS_STATUS_ERROR(status)) { 338 wlan_serialization_dequeue_cmd(&cmd_list->cmd, 339 SER_ACTIVATION_FAILED, 340 true); 341 return status; 342 } 343 344 /* 345 * Cmd was marked for activation and delete or cancel 346 * is received before activation completed, then the command 347 * should be immediately removed after activation 348 */ 349 if (qdf_atomic_test_bit(CMD_ACTIVE_MARKED_FOR_REMOVAL, 350 &cmd_list->cmd_in_use)) { 351 wlan_serialization_dequeue_cmd(&cmd_list->cmd, 352 SER_REMOVE, 353 true); 354 return status; 355 } 356 357 if (qdf_atomic_test_bit(CMD_ACTIVE_MARKED_FOR_CANCEL, 358 &cmd_list->cmd_in_use)) 359 wlan_serialization_cmd_cancel_handler( 360 ser_pdev_obj, &cmd_list->cmd, 361 NULL, NULL, cmd_list->cmd.cmd_type, 362 WLAN_SERIALIZATION_ACTIVE_QUEUE); 363 error: 364 return status; 365 } 366 367 bool 368 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd) 369 { 370 struct wlan_objmgr_pdev *pdev; 371 bool active_cmd_allowed = 0; 372 373 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 374 if (!pdev) { 375 ser_err("NULL pdev"); 376 goto error; 377 } 378 379 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 380 active_cmd_allowed = 381 (wlan_serialization_is_active_scan_cmd_allowed(cmd) && 382 wlan_serialization_is_scan_pending_queue_empty(cmd)); 383 else 384 active_cmd_allowed = 385 (wlan_serialization_is_active_non_scan_cmd_allowed(cmd) && 386 wlan_serialization_is_non_scan_pending_queue_empty(cmd)); 387 388 ser_debug("active cmd_type[%d] cmd_id[%d] allowed: %d", 389 cmd->cmd_type, 390 cmd->cmd_id, 391 active_cmd_allowed); 392 393 error: 394 return active_cmd_allowed; 395 } 396 397 enum wlan_serialization_status 398 wlan_serialization_move_pending_to_active( 399 enum wlan_serialization_cmd_type cmd_type, 400 struct wlan_ser_pdev_obj *ser_pdev_obj, 401 struct wlan_objmgr_vdev *vdev, 402 bool blocking_cmd_removed) 403 { 404 enum wlan_serialization_status status; 405 406 if (cmd_type < WLAN_SER_CMD_NONSCAN) { 407 status = 408 wlan_ser_move_scan_pending_to_active( 409 ser_pdev_obj); 410 } else { 411 status = 412 wlan_ser_move_non_scan_pending_to_active( 413 ser_pdev_obj, 414 vdev, 415 blocking_cmd_removed); 416 } 417 418 return status; 419 } 420 421 enum wlan_serialization_cmd_status 422 wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd, 423 enum ser_queue_reason ser_reason, 424 uint8_t active_cmd) 425 { 426 enum wlan_serialization_cmd_status status = 427 WLAN_SER_CMD_NOT_FOUND; 428 enum wlan_serialization_status ser_status = 429 WLAN_SER_CMD_DENIED_UNSPECIFIED; 430 431 QDF_STATUS qdf_status; 432 struct wlan_objmgr_pdev *pdev; 433 struct wlan_objmgr_psoc *psoc; 434 struct wlan_ser_pdev_obj *ser_pdev_obj; 435 struct wlan_serialization_command cmd_bkup; 436 struct wlan_serialization_command_list *cmd_list; 437 struct wlan_serialization_pdev_queue *pdev_queue; 438 bool blocking_cmd_removed = 0; 439 440 ser_enter(); 441 442 if (!cmd) { 443 ser_err("NULL command"); 444 goto error; 445 } 446 447 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 448 if (!pdev) { 449 ser_err("invalid pdev"); 450 goto error; 451 } 452 453 psoc = wlan_pdev_get_psoc(pdev); 454 if (!psoc) { 455 ser_err("invalid psoc"); 456 goto error; 457 } 458 459 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 460 if (!ser_pdev_obj) { 461 ser_err("ser_pdev_obj is empty"); 462 goto error; 463 } 464 465 pdev_queue = wlan_serialization_get_pdev_queue_obj( 466 ser_pdev_obj, cmd->cmd_type); 467 468 ser_debug("dequeue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 469 cmd->cmd_type, 470 cmd->cmd_id, 471 cmd->is_high_priority, 472 cmd->is_blocking); 473 474 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 475 476 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 477 qdf_status = wlan_ser_remove_scan_cmd( 478 ser_pdev_obj, &cmd_list, cmd, active_cmd); 479 else { 480 qdf_status = wlan_ser_remove_non_scan_cmd( 481 ser_pdev_obj, &cmd_list, cmd, active_cmd); 482 } 483 484 if (qdf_status == QDF_STATUS_E_PENDING) { 485 status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION; 486 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 487 goto error; 488 } 489 490 if (qdf_status != QDF_STATUS_SUCCESS) { 491 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 492 status = WLAN_SER_CMD_NOT_FOUND; 493 goto error; 494 } 495 496 if (active_cmd) { 497 if (cmd_list->cmd.cmd_type >= WLAN_SER_CMD_NONSCAN) 498 blocking_cmd_removed = cmd_list->cmd.is_blocking; 499 } 500 501 if (active_cmd) 502 wlan_serialization_find_and_stop_timer(psoc, &cmd_list->cmd); 503 504 qdf_mem_copy(&cmd_bkup, &cmd_list->cmd, 505 sizeof(struct wlan_serialization_command)); 506 qdf_mem_zero(&cmd_list->cmd, 507 sizeof(struct wlan_serialization_command)); 508 cmd_list->cmd_in_use = 0; 509 qdf_status = wlan_serialization_insert_back( 510 &pdev_queue->cmd_pool_list, 511 &cmd_list->pdev_node); 512 513 wlan_ser_update_cmd_history(pdev_queue, &cmd_bkup, ser_reason, 514 false, active_cmd); 515 516 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 517 518 /* Call cmd cb for remove request*/ 519 if (cmd_bkup.cmd_cb) { 520 /* caller should release the memory */ 521 ser_debug("cmd cb: type[%d] id[%d]: reason: %s", 522 cmd_bkup.cmd_type, 523 cmd_bkup.cmd_id, 524 "WLAN_SER_CB_RELEASE_MEM_CMD"); 525 cmd_bkup.cmd_cb(&cmd_bkup, 526 WLAN_SER_CB_RELEASE_MEM_CMD); 527 } 528 529 if (active_cmd) { 530 ser_status = wlan_serialization_move_pending_to_active( 531 cmd_bkup.cmd_type, ser_pdev_obj, 532 cmd_bkup.vdev, 533 blocking_cmd_removed); 534 } 535 536 if (active_cmd) 537 status = WLAN_SER_CMD_IN_ACTIVE_LIST; 538 else 539 status = WLAN_SER_CMD_IN_PENDING_LIST; 540 541 error: 542 ser_exit(); 543 return status; 544 } 545 546 void wlan_serialization_generic_timer_cb(void *arg) 547 { 548 struct wlan_serialization_timer *timer = arg; 549 struct wlan_serialization_command *cmd = timer->cmd; 550 551 if (!cmd) { 552 ser_err("command not found"); 553 QDF_ASSERT(0); 554 return; 555 } 556 557 ser_err("active cmd timeout for cmd_type[%d] vdev[%pK]", 558 cmd->cmd_type, cmd->vdev); 559 560 if (cmd->cmd_cb) 561 cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT); 562 563 /* 564 * dequeue cmd API will cleanup and destroy the timer. If it fails to 565 * dequeue command then we have to destroy the timer. 566 */ 567 wlan_serialization_dequeue_cmd(cmd, SER_TIMEOUT, true); 568 } 569 570 static QDF_STATUS wlan_serialization_mc_flush_noop(struct scheduler_msg *msg) 571 { 572 return QDF_STATUS_SUCCESS; 573 } 574 575 static void 576 wlan_serialization_timer_cb_mc_ctx(void *arg) 577 { 578 struct scheduler_msg msg = {0}; 579 580 msg.type = SYS_MSG_ID_MC_TIMER; 581 msg.reserved = SYS_MSG_COOKIE; 582 msg.callback = wlan_serialization_generic_timer_cb; 583 msg.bodyptr = arg; 584 msg.bodyval = 0; 585 msg.flush_callback = wlan_serialization_mc_flush_noop; 586 587 if (scheduler_post_msg(QDF_MODULE_ID_SYS, &msg) == QDF_STATUS_SUCCESS) 588 return; 589 590 ser_err("Could not enqueue timer to timer queue"); 591 } 592 593 #ifdef CONFIG_MCL 594 static void wlan_serialization_timer_handler(void *arg) 595 { 596 ser_enter(); 597 598 wlan_serialization_timer_cb_mc_ctx(arg); 599 600 ser_exit(); 601 } 602 #else 603 static void wlan_serialization_timer_handler(void *arg) 604 { 605 struct wlan_serialization_timer *timer = arg; 606 struct wlan_serialization_command *cmd = timer->cmd; 607 608 if (!cmd) { 609 ser_err("command not found"); 610 QDF_ASSERT(0); 611 return; 612 } 613 614 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 615 wlan_serialization_timer_cb_mc_ctx(arg); 616 else 617 wlan_serialization_generic_timer_cb(arg); 618 } 619 #endif 620 621 QDF_STATUS 622 wlan_serialization_find_and_update_timer( 623 struct wlan_objmgr_psoc *psoc, 624 struct wlan_serialization_command *cmd) 625 { 626 struct wlan_ser_psoc_obj *psoc_ser_obj; 627 struct wlan_serialization_timer *ser_timer; 628 QDF_STATUS status = QDF_STATUS_E_FAILURE; 629 int i = 0; 630 631 if (!psoc || !cmd) { 632 ser_err("invalid param"); 633 goto exit; 634 } 635 636 psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); 637 /* 638 * Here cmd_id and cmd_type are used to locate the timer being 639 * associated with command. 640 */ 641 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); 642 643 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 644 ser_timer = &psoc_ser_obj->timers[i]; 645 if (!(ser_timer->cmd) || 646 (ser_timer->cmd->cmd_id != cmd->cmd_id) || 647 (ser_timer->cmd->cmd_type != cmd->cmd_type) || 648 (ser_timer->cmd->vdev != cmd->vdev)) 649 continue; 650 651 qdf_timer_mod(&ser_timer->timer, 652 cmd->cmd_timeout_duration); 653 status = QDF_STATUS_SUCCESS; 654 break; 655 } 656 657 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); 658 659 if (QDF_IS_STATUS_SUCCESS(status)) 660 ser_debug("Updated the timer for cmd type:%d, id: %d", 661 cmd->cmd_type, cmd->cmd_id); 662 else 663 ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type); 664 665 exit: 666 return status; 667 } 668 669 QDF_STATUS 670 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc, 671 struct wlan_serialization_command *cmd) 672 { 673 struct wlan_ser_psoc_obj *psoc_ser_obj; 674 struct wlan_serialization_timer *ser_timer; 675 QDF_STATUS status = QDF_STATUS_E_FAILURE; 676 int i = 0; 677 uint32_t phy_version; 678 679 if (!psoc || !cmd) { 680 ser_err("invalid param"); 681 goto exit; 682 } 683 684 if (cmd->cmd_timeout_duration == 0) { 685 phy_version = wlan_psoc_get_nif_phy_version(psoc); 686 if (wlan_is_emulation_platform(phy_version)) { 687 ser_err("[SCAN-EMULATION]: Not performing timer funcs"); 688 status = QDF_STATUS_SUCCESS; 689 goto exit; 690 } 691 } 692 693 psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); 694 /* 695 * Here cmd_id and cmd_type are used to locate the timer being 696 * associated with command. 697 */ 698 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); 699 700 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 701 ser_timer = &psoc_ser_obj->timers[i]; 702 if (!(ser_timer->cmd) || 703 (ser_timer->cmd->cmd_id != cmd->cmd_id) || 704 (ser_timer->cmd->cmd_type != cmd->cmd_type) || 705 (ser_timer->cmd->vdev != cmd->vdev)) 706 continue; 707 708 status = wlan_serialization_stop_timer(ser_timer); 709 break; 710 } 711 712 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); 713 714 if (QDF_IS_STATUS_SUCCESS(status)) 715 ser_debug("Stopped timer for cmd_type %d cmd id %d", 716 cmd->cmd_type, cmd->cmd_id); 717 else 718 ser_err("Can't find timer for cmd_type %d cmd id %d", 719 cmd->cmd_type, cmd->cmd_id); 720 721 exit: 722 return status; 723 } 724 725 QDF_STATUS 726 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc, 727 struct wlan_serialization_command *cmd) 728 { 729 QDF_STATUS status = QDF_STATUS_E_FAILURE; 730 struct wlan_ser_psoc_obj *psoc_ser_obj; 731 struct wlan_serialization_timer *ser_timer; 732 int i = 0; 733 uint32_t nif_phy_ver; 734 735 if (!psoc || !cmd) { 736 ser_err("invalid param"); 737 goto error; 738 } 739 740 nif_phy_ver = wlan_psoc_get_nif_phy_version(psoc); 741 if ((cmd->cmd_timeout_duration == 0) && 742 (wlan_is_emulation_platform(nif_phy_ver))) { 743 ser_err("[SCAN-EMULATION]: Not performing timer functions\n"); 744 status = QDF_STATUS_SUCCESS; 745 goto exit; 746 } 747 748 psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); 749 750 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); 751 752 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 753 /* Keep trying timer */ 754 ser_timer = &psoc_ser_obj->timers[i]; 755 if (ser_timer->cmd) 756 continue; 757 758 /* Remember timer is pointing to command */ 759 ser_timer->cmd = cmd; 760 status = QDF_STATUS_SUCCESS; 761 break; 762 } 763 764 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); 765 766 if (QDF_IS_STATUS_SUCCESS(status)) { 767 qdf_timer_init(NULL, 768 &ser_timer->timer, 769 wlan_serialization_timer_handler, 770 ser_timer, 771 QDF_TIMER_TYPE_SW); 772 qdf_timer_mod(&ser_timer->timer, 773 cmd->cmd_timeout_duration); 774 775 ser_debug("starting timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 776 cmd->cmd_type, 777 cmd->cmd_id, 778 cmd->is_high_priority, 779 cmd->is_blocking); 780 } 781 782 error: 783 exit: 784 785 return status; 786 } 787 788 enum wlan_serialization_cmd_status 789 wlan_serialization_cmd_cancel_handler( 790 struct wlan_ser_pdev_obj *ser_obj, 791 struct wlan_serialization_command *cmd, 792 struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, 793 enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type) 794 { 795 enum wlan_serialization_cmd_status active_status = 796 WLAN_SER_CMD_NOT_FOUND; 797 enum wlan_serialization_cmd_status pending_status = 798 WLAN_SER_CMD_NOT_FOUND; 799 enum wlan_serialization_cmd_status status = 800 WLAN_SER_CMD_NOT_FOUND; 801 802 ser_enter(); 803 804 if (!ser_obj) { 805 ser_err("invalid serial object"); 806 goto error; 807 } 808 809 if (queue_type & WLAN_SERIALIZATION_ACTIVE_QUEUE) { 810 if (cmd_type < WLAN_SER_CMD_NONSCAN) 811 active_status = wlan_ser_cancel_scan_cmd( 812 ser_obj, pdev, vdev, cmd, 813 cmd_type, true); 814 else 815 active_status = wlan_ser_cancel_non_scan_cmd( 816 ser_obj, pdev, vdev, cmd, 817 cmd_type, true); 818 } 819 820 if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) { 821 if (cmd_type < WLAN_SER_CMD_NONSCAN) 822 pending_status = wlan_ser_cancel_scan_cmd( 823 ser_obj, pdev, vdev, cmd, 824 cmd_type, false); 825 else 826 pending_status = wlan_ser_cancel_non_scan_cmd( 827 ser_obj, pdev, vdev, cmd, 828 cmd_type, false); 829 } 830 831 if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST && 832 pending_status == WLAN_SER_CMD_IN_PENDING_LIST) 833 status = WLAN_SER_CMDS_IN_ALL_LISTS; 834 else if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST) 835 status = active_status; 836 else if (pending_status == WLAN_SER_CMD_IN_PENDING_LIST) 837 status = pending_status; 838 839 error: 840 ser_exit(); 841 return status; 842 } 843 844 enum wlan_serialization_cmd_status 845 wlan_serialization_find_and_cancel_cmd( 846 struct wlan_serialization_command *cmd, 847 enum wlan_serialization_cancel_type req_type, 848 uint8_t queue_type) 849 { 850 enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND; 851 struct wlan_ser_pdev_obj *ser_obj = NULL; 852 struct wlan_objmgr_pdev *pdev; 853 854 ser_enter(); 855 856 if (!cmd) { 857 ser_err("Invalid cmd"); 858 goto error; 859 } 860 861 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 862 if (!pdev) { 863 ser_err("Invalid pdev"); 864 goto error; 865 } 866 ser_obj = wlan_serialization_get_pdev_obj(pdev); 867 if (!ser_obj) { 868 ser_err("Invalid ser_obj"); 869 goto error; 870 } 871 872 switch (req_type) { 873 case WLAN_SER_CANCEL_SINGLE_SCAN: 874 /* remove scan cmd which matches the given cmd struct */ 875 status = wlan_serialization_cmd_cancel_handler( 876 ser_obj, cmd, NULL, NULL, 877 WLAN_SER_CMD_SCAN, queue_type); 878 break; 879 case WLAN_SER_CANCEL_PDEV_SCANS: 880 /* remove all scan cmds which matches the pdev object */ 881 status = wlan_serialization_cmd_cancel_handler( 882 ser_obj, NULL, pdev, NULL, 883 WLAN_SER_CMD_SCAN, queue_type); 884 break; 885 case WLAN_SER_CANCEL_VDEV_SCANS: 886 /* remove all scan cmds which matches the vdev object */ 887 status = wlan_serialization_cmd_cancel_handler( 888 ser_obj, NULL, NULL, cmd->vdev, 889 WLAN_SER_CMD_SCAN, queue_type); 890 break; 891 case WLAN_SER_CANCEL_NON_SCAN_CMD: 892 /* remove nonscan cmd which matches the given cmd */ 893 status = wlan_serialization_cmd_cancel_handler( 894 ser_obj, cmd, NULL, NULL, 895 WLAN_SER_CMD_NONSCAN, queue_type); 896 break; 897 case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD: 898 /* remove all non scan cmds which matches the pdev object */ 899 status = wlan_serialization_cmd_cancel_handler( 900 ser_obj, NULL, pdev, NULL, 901 WLAN_SER_CMD_NONSCAN, queue_type); 902 break; 903 case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD: 904 /* remove all non scan cmds which matches the vdev object */ 905 status = wlan_serialization_cmd_cancel_handler( 906 ser_obj, NULL, NULL, cmd->vdev, 907 WLAN_SER_CMD_NONSCAN, queue_type); 908 break; 909 case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE: 910 /* 911 * remove all non scan cmds which matches the vdev 912 * and given cmd type 913 */ 914 status = wlan_serialization_cmd_cancel_handler( 915 ser_obj, NULL, NULL, cmd->vdev, 916 cmd->cmd_type, queue_type); 917 break; 918 default: 919 ser_err("Invalid request"); 920 } 921 922 error: 923 ser_exit(); 924 return status; 925 } 926