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