1 /* 2 * Copyright (c) 2017-2020 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_non_scan.c 20 * This file defines the functions which deals with 21 * serialization non scan commands. 22 */ 23 24 #include <wlan_objmgr_psoc_obj.h> 25 #include <wlan_objmgr_pdev_obj.h> 26 #include <wlan_objmgr_vdev_obj.h> 27 #include "wlan_serialization_main_i.h" 28 #include "wlan_serialization_utils_i.h" 29 #include "wlan_serialization_non_scan_i.h" 30 31 bool 32 wlan_serialization_is_non_scan_pending_queue_empty( 33 struct wlan_serialization_command *cmd) 34 { 35 struct wlan_objmgr_vdev *vdev = NULL; 36 struct wlan_ser_vdev_obj *ser_vdev_obj = NULL; 37 struct wlan_serialization_vdev_queue *vdev_q; 38 bool status = false; 39 40 vdev = wlan_serialization_get_vdev_from_cmd(cmd); 41 42 if (!vdev) { 43 ser_err("vdev object is invalid"); 44 goto error; 45 } 46 47 ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev); 48 vdev_q = &ser_vdev_obj->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN]; 49 50 if (qdf_list_empty(&vdev_q->pending_list)) 51 status = true; 52 53 error: 54 return status; 55 } 56 57 /** 58 * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed 59 * @pdev: pointer to pdev object 60 * 61 * This API will be called to find out if non scan cmd is allowed. 62 * 63 * Return: true or false 64 */ 65 66 bool 67 wlan_serialization_is_active_non_scan_cmd_allowed( 68 struct wlan_serialization_command *cmd) 69 { 70 struct wlan_serialization_pdev_queue *pdev_queue; 71 struct wlan_ser_pdev_obj *ser_pdev_obj; 72 uint32_t vdev_active_cmd_bitmap; 73 bool blocking_cmd_active = 0; 74 uint8_t blocking_cmd_waiting = 0; 75 bool status = false; 76 uint32_t vdev_id; 77 78 ser_pdev_obj = wlan_serialization_get_pdev_obj( 79 wlan_serialization_get_pdev_from_cmd(cmd)); 80 81 pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, 82 cmd->cmd_type); 83 84 vdev_active_cmd_bitmap = pdev_queue->vdev_active_cmd_bitmap; 85 blocking_cmd_active = pdev_queue->blocking_cmd_active; 86 blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting; 87 88 /* 89 * Command is blocking 90 */ 91 if (cmd->is_blocking) { 92 /* 93 * For blocking commands, no other 94 * commands from any vdev should be active 95 */ 96 if (vdev_active_cmd_bitmap) { 97 status = false; 98 pdev_queue->blocking_cmd_waiting++; 99 } else { 100 status = true; 101 } 102 } else { 103 /* 104 * Command is non blocking 105 * For activating non blocking commands, if there any blocking 106 * commands, waiting or active, put it to pending queue 107 */ 108 if (blocking_cmd_active || blocking_cmd_waiting) { 109 status = false; 110 } else { 111 /* 112 * For non blocking command, and no blocking commands 113 * waiting or active, check if a cmd for that vdev is active 114 * If not active, put to active else pending queue 115 */ 116 vdev_id = wlan_vdev_get_id(cmd->vdev); 117 status = vdev_active_cmd_bitmap & (1 << vdev_id) 118 ? false : true; 119 } 120 } 121 return status; 122 } 123 124 enum wlan_serialization_status wlan_ser_add_non_scan_cmd( 125 struct wlan_ser_pdev_obj *ser_pdev_obj, 126 struct wlan_serialization_command_list *cmd_list, 127 uint8_t is_cmd_for_active_queue) 128 { 129 enum wlan_serialization_status pdev_status, vdev_status; 130 enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 131 struct wlan_serialization_command_list *pcmd_list; 132 uint8_t vdev_id; 133 struct wlan_serialization_pdev_queue *pdev_queue; 134 135 vdev_status = wlan_serialization_add_cmd_to_vdev_queue( 136 ser_pdev_obj, cmd_list, is_cmd_for_active_queue); 137 138 if (vdev_status == WLAN_SER_CMD_DENIED_LIST_FULL) { 139 ser_err_rl("List is full cannot add type %d cmd id %d", 140 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 141 status = vdev_status; 142 goto vdev_error; 143 } 144 145 if (is_cmd_for_active_queue) { 146 if (vdev_status != WLAN_SER_CMD_ACTIVE) { 147 ser_err("Failed to add type %d cmd id %d to vdev active queue", 148 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 149 QDF_ASSERT(0); 150 goto vdev_error; 151 } 152 } else { 153 if (vdev_status != WLAN_SER_CMD_PENDING) { 154 ser_err("Failed to add type %d cmd id %d to vdev pending queue", 155 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 156 QDF_ASSERT(0); 157 goto vdev_error; 158 } 159 } 160 161 pdev_status = wlan_serialization_add_cmd_to_pdev_queue( 162 ser_pdev_obj, cmd_list, is_cmd_for_active_queue); 163 164 if (pdev_status == WLAN_SER_CMD_DENIED_LIST_FULL) { 165 ser_err_rl("pdev List is full cannot add type %d cmd id %d", 166 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 167 status = pdev_status; 168 goto pdev_error; 169 } 170 171 if (is_cmd_for_active_queue) { 172 if (pdev_status != WLAN_SER_CMD_ACTIVE) { 173 ser_err("Failed to add type %d cmd id %d to pdev active queue", 174 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 175 QDF_ASSERT(0); 176 goto pdev_error; 177 } 178 } else { 179 if (pdev_status != WLAN_SER_CMD_PENDING) { 180 ser_err("Failed to add type %d cmd id %d to pdev pending queue", 181 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 182 QDF_ASSERT(0); 183 goto pdev_error; 184 } 185 } 186 pdev_error: 187 /* 188 * If cmd added to vdev queue, but failed while 189 * adding to pdev queue, remove cmd from vdev queue as well 190 */ 191 if (pdev_status != vdev_status) { 192 wlan_serialization_remove_cmd_from_vdev_queue( 193 ser_pdev_obj, &pcmd_list, 194 &cmd_list->cmd, 195 is_cmd_for_active_queue); 196 } else { 197 status = pdev_status; 198 } 199 200 if (is_cmd_for_active_queue) { 201 pdev_queue = wlan_serialization_get_pdev_queue_obj( 202 ser_pdev_obj, cmd_list->cmd.cmd_type); 203 vdev_id = wlan_vdev_get_id(cmd_list->cmd.vdev); 204 pdev_queue->vdev_active_cmd_bitmap |= (1 << vdev_id); 205 206 if (cmd_list->cmd.is_blocking) 207 pdev_queue->blocking_cmd_active = 1; 208 } 209 210 vdev_error: 211 return status; 212 } 213 214 enum wlan_serialization_status 215 wlan_ser_move_non_scan_pending_to_active( 216 struct wlan_ser_pdev_obj *ser_pdev_obj, 217 struct wlan_objmgr_vdev *vdev, 218 bool blocking_cmd_removed) 219 { 220 struct wlan_serialization_command_list *pending_cmd_list = NULL; 221 struct wlan_serialization_command_list *active_cmd_list; 222 struct wlan_serialization_command cmd_to_remove; 223 enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 224 struct wlan_serialization_pdev_queue *pdev_queue; 225 struct wlan_serialization_vdev_queue *vdev_queue; 226 227 struct wlan_ser_vdev_obj *ser_vdev_obj; 228 229 qdf_list_t *pending_queue; 230 qdf_list_node_t *pending_node = NULL; 231 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE; 232 uint32_t blocking_cmd_waiting = 0; 233 uint32_t vdev_id; 234 uint32_t qsize; 235 bool vdev_cmd_active = 0; 236 bool vdev_queue_lookup = false; 237 238 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 239 240 ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev); 241 vdev_queue = &ser_vdev_obj->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN]; 242 243 if (!ser_pdev_obj) { 244 ser_err("Can't find ser_pdev_obj"); 245 goto error; 246 } 247 248 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 249 250 blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting; 251 252 if (!blocking_cmd_removed && !blocking_cmd_waiting) { 253 pending_queue = &vdev_queue->pending_list; 254 vdev_queue_lookup = true; 255 } else { 256 pending_queue = &pdev_queue->pending_list; 257 } 258 259 qsize = wlan_serialization_list_size(pending_queue); 260 if (!qsize) { 261 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 262 goto error; 263 } 264 265 while (qsize--) { 266 qdf_status = wlan_serialization_get_cmd_from_queue( 267 pending_queue, &pending_node); 268 if (qdf_status != QDF_STATUS_SUCCESS) { 269 ser_err("can't peek cmd"); 270 break; 271 } 272 273 if (vdev_queue_lookup) { 274 pending_cmd_list = 275 qdf_container_of( 276 pending_node, 277 struct wlan_serialization_command_list, 278 vdev_node); 279 } else { 280 pending_cmd_list = 281 qdf_container_of( 282 pending_node, 283 struct wlan_serialization_command_list, 284 pdev_node); 285 } 286 287 if (!pending_cmd_list) { 288 wlan_serialization_release_lock( 289 &pdev_queue->pdev_queue_lock); 290 ser_debug( 291 "non scan cmd cannot move frm pendin to actv"); 292 goto error; 293 } 294 295 vdev_id = wlan_vdev_get_id(pending_cmd_list->cmd.vdev); 296 vdev_cmd_active = 297 pdev_queue->vdev_active_cmd_bitmap & 298 (1 << vdev_id); 299 300 if (!vdev_queue_lookup) { 301 if (pending_cmd_list->cmd.is_blocking && 302 pdev_queue->vdev_active_cmd_bitmap) { 303 break; 304 } 305 if (vdev_cmd_active) 306 continue; 307 } else { 308 if (vdev_cmd_active) 309 break; 310 } 311 312 qdf_mem_copy(&cmd_to_remove, &pending_cmd_list->cmd, 313 sizeof(struct wlan_serialization_command)); 314 315 qdf_status = wlan_ser_remove_non_scan_cmd(ser_pdev_obj, 316 &pending_cmd_list, 317 &cmd_to_remove, 318 false); 319 320 wlan_ser_update_cmd_history( 321 pdev_queue, &pending_cmd_list->cmd, 322 SER_PENDING_TO_ACTIVE, 323 false, false); 324 325 if (QDF_STATUS_SUCCESS != qdf_status) { 326 wlan_serialization_release_lock( 327 &pdev_queue->pdev_queue_lock); 328 ser_err("Can't remove cmd from pendingQ id-%d type-%d", 329 pending_cmd_list->cmd.cmd_id, 330 pending_cmd_list->cmd.cmd_type); 331 QDF_ASSERT(0); 332 status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 333 goto error; 334 } 335 336 active_cmd_list = pending_cmd_list; 337 338 status = wlan_ser_add_non_scan_cmd( 339 ser_pdev_obj, active_cmd_list, true); 340 341 if (WLAN_SER_CMD_ACTIVE != status) { 342 wlan_serialization_release_lock( 343 &pdev_queue->pdev_queue_lock); 344 ser_err("Can't move cmd to activeQ id-%d type-%d", 345 pending_cmd_list->cmd.cmd_id, 346 pending_cmd_list->cmd.cmd_type); 347 wlan_serialization_insert_back( 348 &pdev_queue->cmd_pool_list, 349 &active_cmd_list->pdev_node); 350 status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 351 QDF_ASSERT(0); 352 goto error; 353 } 354 355 wlan_ser_update_cmd_history( 356 pdev_queue, &active_cmd_list->cmd, 357 SER_PENDING_TO_ACTIVE, 358 true, true); 359 360 qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION, 361 &active_cmd_list->cmd_in_use); 362 363 if (active_cmd_list->cmd.is_blocking) 364 pdev_queue->blocking_cmd_waiting--; 365 366 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 367 368 wlan_serialization_activate_cmd(active_cmd_list, ser_pdev_obj, 369 SER_PENDING_TO_ACTIVE); 370 371 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 372 373 if (vdev_queue_lookup || pdev_queue->blocking_cmd_active) 374 break; 375 376 pending_node = NULL; 377 378 } 379 380 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 381 error: 382 383 return status; 384 } 385 386 QDF_STATUS wlan_ser_remove_non_scan_cmd( 387 struct wlan_ser_pdev_obj *ser_pdev_obj, 388 struct wlan_serialization_command_list **pcmd_list, 389 struct wlan_serialization_command *cmd, 390 uint8_t is_active_cmd) 391 { 392 QDF_STATUS pdev_status, vdev_status; 393 QDF_STATUS status = QDF_STATUS_E_FAILURE; 394 uint32_t vdev_id; 395 bool blocking_cmd_removed = 0; 396 struct wlan_serialization_pdev_queue *pdev_queue; 397 398 vdev_status = 399 wlan_serialization_remove_cmd_from_vdev_queue(ser_pdev_obj, 400 pcmd_list, 401 cmd, 402 is_active_cmd); 403 404 /* Here command removal can fail for 2 reasons 405 * 1. The cmd is not present 406 * 2. The command had not returned from activation 407 * and will not be removed now. 408 * 409 * In the second case, we should not flag it as error 410 * since it will removed after the activation completes. 411 */ 412 413 if (vdev_status != QDF_STATUS_SUCCESS) { 414 status = vdev_status; 415 if (vdev_status != QDF_STATUS_E_PENDING) 416 ser_debug("Failed to remove type %d id %d from vdev queue", 417 cmd->cmd_type, cmd->cmd_id); 418 goto error; 419 } 420 421 pdev_status = 422 wlan_serialization_remove_cmd_from_pdev_queue(ser_pdev_obj, 423 pcmd_list, 424 cmd, 425 is_active_cmd); 426 427 if (pdev_status != QDF_STATUS_SUCCESS) { 428 ser_debug("Failed to remove type %d id %d from pdev active/pending queue", 429 cmd->cmd_type, cmd->cmd_id); 430 goto error; 431 } 432 433 if (is_active_cmd) { 434 blocking_cmd_removed = (*pcmd_list)->cmd.is_blocking; 435 pdev_queue = wlan_serialization_get_pdev_queue_obj( 436 ser_pdev_obj, (*pcmd_list)->cmd.cmd_type); 437 438 if (blocking_cmd_removed) 439 pdev_queue->blocking_cmd_active = 0; 440 441 vdev_id = wlan_vdev_get_id(cmd->vdev); 442 pdev_queue->vdev_active_cmd_bitmap &= ~(1 << vdev_id); 443 } 444 445 status = QDF_STATUS_SUCCESS; 446 447 error: 448 return status; 449 } 450 451 enum wlan_serialization_cmd_status 452 wlan_ser_cancel_non_scan_cmd( 453 struct wlan_ser_pdev_obj *ser_pdev_obj, 454 struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, 455 struct wlan_serialization_command *cmd, 456 enum wlan_serialization_cmd_type cmd_type, 457 uint8_t is_active_queue, enum wlan_ser_cmd_attr cmd_attr) 458 { 459 qdf_list_t *pdev_queue; 460 qdf_list_t *vdev_queue; 461 struct wlan_serialization_pdev_queue *pdev_q; 462 uint32_t qsize; 463 uint8_t vdev_id; 464 bool is_blocking; 465 struct wlan_serialization_command_list *cmd_list = NULL; 466 struct wlan_serialization_command cmd_bkup; 467 qdf_list_node_t *nnode = NULL, *pnode = NULL; 468 enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND; 469 struct wlan_objmgr_psoc *psoc = NULL; 470 QDF_STATUS qdf_status; 471 QDF_STATUS pdev_status, vdev_status; 472 struct wlan_ser_vdev_obj *ser_vdev_obj; 473 474 pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type); 475 476 pdev_queue = wlan_serialization_get_list_from_pdev_queue( 477 ser_pdev_obj, cmd_type, is_active_queue); 478 479 if (pdev) 480 psoc = wlan_pdev_get_psoc(pdev); 481 else if (vdev) 482 psoc = wlan_vdev_get_psoc(vdev); 483 else if (cmd && cmd->vdev) 484 psoc = wlan_vdev_get_psoc(cmd->vdev); 485 else 486 ser_debug("Can't find psoc"); 487 488 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 489 490 qsize = wlan_serialization_list_size(pdev_queue); 491 while (!wlan_serialization_list_empty(pdev_queue) && qsize--) { 492 if (wlan_serialization_get_cmd_from_queue(pdev_queue, &nnode) 493 != QDF_STATUS_SUCCESS) { 494 ser_err("can't read cmd from queue"); 495 status = WLAN_SER_CMD_NOT_FOUND; 496 break; 497 } 498 cmd_list = 499 qdf_container_of(nnode, 500 struct wlan_serialization_command_list, 501 pdev_node); 502 if (cmd && !wlan_serialization_match_cmd_id_type( 503 nnode, cmd, 504 WLAN_SER_PDEV_NODE)) { 505 pnode = nnode; 506 continue; 507 } 508 509 if (vdev && 510 !wlan_serialization_match_cmd_vdev(nnode, 511 vdev, 512 WLAN_SER_PDEV_NODE)) { 513 pnode = nnode; 514 continue; 515 } 516 517 if (pdev && 518 !wlan_serialization_match_cmd_pdev(nnode, 519 pdev, 520 WLAN_SER_PDEV_NODE)) { 521 pnode = nnode; 522 continue; 523 } 524 525 if (cmd_type > WLAN_SER_CMD_NONSCAN && vdev && 526 (!wlan_serialization_match_cmd_type(nnode, cmd_type, 527 WLAN_SER_PDEV_NODE) || 528 !wlan_serialization_match_cmd_vdev(nnode, vdev, 529 WLAN_SER_PDEV_NODE))) { 530 pnode = nnode; 531 continue; 532 } 533 534 /* 535 * If a non-blocking cmd is required to be cancelled, but 536 * the nnode cmd is a blocking cmd then continue with the 537 * next command in the list else proceed with cmd cancel. 538 */ 539 if ((cmd_attr == WLAN_SER_CMD_ATTR_NONBLOCK) && 540 wlan_serialization_match_cmd_blocking(nnode, 541 WLAN_SER_PDEV_NODE)) { 542 pnode = nnode; 543 continue; 544 } 545 546 /* 547 * active queue can't be removed directly, requester needs to 548 * wait for active command response and send remove request for 549 * active command separately 550 */ 551 if (is_active_queue) { 552 if (!psoc || !cmd_list) { 553 ser_err("psoc:0x%pK, cmd_list:0x%pK", 554 psoc, cmd_list); 555 status = WLAN_SER_CMD_NOT_FOUND; 556 break; 557 } 558 559 /* Cancel request received for a cmd in active 560 * queue which has not been activated yet, we mark 561 * it as CMD_ACTIVE_MARKED_FOR_CANCEL and remove 562 * the cmd after activation 563 */ 564 if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION, 565 &cmd_list->cmd_in_use)) { 566 qdf_atomic_set_bit(CMD_ACTIVE_MARKED_FOR_CANCEL, 567 &cmd_list->cmd_in_use); 568 status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION; 569 continue; 570 } 571 572 qdf_status = wlan_serialization_find_and_stop_timer( 573 psoc, &cmd_list->cmd, 574 SER_CANCEL); 575 if (QDF_IS_STATUS_ERROR(qdf_status)) { 576 ser_err("Can't find timer for active cmd"); 577 status = WLAN_SER_CMD_NOT_FOUND; 578 /* 579 * This should not happen, as an active command 580 * should always have the timer. 581 */ 582 QDF_BUG(0); 583 break; 584 } 585 586 status = WLAN_SER_CMD_IN_ACTIVE_LIST; 587 } 588 589 qdf_mem_copy(&cmd_bkup, &cmd_list->cmd, 590 sizeof(struct wlan_serialization_command)); 591 592 pdev_status = 593 wlan_serialization_remove_node(pdev_queue, 594 &cmd_list->pdev_node); 595 596 ser_vdev_obj = wlan_serialization_get_vdev_obj( 597 cmd_list->cmd.vdev); 598 599 vdev_queue = wlan_serialization_get_list_from_vdev_queue( 600 ser_vdev_obj, cmd_type, is_active_queue); 601 602 vdev_status = 603 wlan_serialization_remove_node(vdev_queue, 604 &cmd_list->vdev_node); 605 606 if (pdev_status != QDF_STATUS_SUCCESS || 607 vdev_status != QDF_STATUS_SUCCESS) { 608 ser_err("can't remove cmd from pdev/vdev queue"); 609 status = WLAN_SER_CMD_NOT_FOUND; 610 break; 611 } 612 613 qdf_mem_zero(&cmd_list->cmd, 614 sizeof(struct wlan_serialization_command)); 615 cmd_list->cmd_in_use = 0; 616 qdf_status = wlan_serialization_insert_back( 617 &pdev_q->cmd_pool_list, 618 &cmd_list->pdev_node); 619 620 if (QDF_STATUS_SUCCESS != qdf_status) { 621 ser_err("can't remove cmd from queue"); 622 status = WLAN_SER_CMD_NOT_FOUND; 623 break; 624 } 625 nnode = pnode; 626 627 vdev_id = wlan_vdev_get_id(cmd_bkup.vdev); 628 is_blocking = cmd_bkup.is_blocking; 629 630 wlan_ser_update_cmd_history(pdev_q, &cmd_bkup, 631 SER_CANCEL, false, is_active_queue); 632 633 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 634 /* 635 * call pending cmd's callback to notify that 636 * it is being removed 637 */ 638 if (cmd_bkup.cmd_cb) { 639 /* caller should now do necessary clean up */ 640 ser_debug("Cancel command: type %d id %d and Release memory", 641 cmd_bkup.cmd_type, cmd_bkup.cmd_id); 642 cmd_bkup.cmd_cb(&cmd_bkup, WLAN_SER_CB_CANCEL_CMD); 643 /* caller should release the memory */ 644 cmd_bkup.cmd_cb(&cmd_bkup, WLAN_SER_CB_RELEASE_MEM_CMD); 645 } 646 647 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 648 649 if (is_active_queue) { 650 if (is_blocking) 651 pdev_q->blocking_cmd_active = 0; 652 pdev_q->vdev_active_cmd_bitmap &= ~(1 << vdev_id); 653 ser_debug("pdev_q->vdev_active_cmd_bitmap %x after reseting for vdev %d", 654 pdev_q->vdev_active_cmd_bitmap, 655 vdev_id); 656 } else { 657 if (is_blocking) 658 pdev_q->blocking_cmd_waiting--; 659 660 status = WLAN_SER_CMD_IN_PENDING_LIST; 661 } 662 663 664 if (!vdev && !pdev) 665 break; 666 } 667 668 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 669 670 return status; 671 } 672