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_utils.c 20 * This file defines the utility helper functions for serialization component. 21 */ 22 23 #ifdef CONFIG_SERIALIZATION_V1 24 #include "wlan_serialization_utils_i.h" 25 #include "wlan_serialization_main_i.h" 26 #include "wlan_serialization_api.h" 27 #include "wlan_objmgr_vdev_obj.h" 28 #include "wlan_objmgr_pdev_obj.h" 29 #include "qdf_mc_timer.h" 30 #include "wlan_utility.h" 31 #include "qdf_platform.h" 32 33 QDF_STATUS 34 wlan_serialization_put_back_to_global_list(qdf_list_t *queue, 35 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 36 struct wlan_serialization_command_list *cmd_list) 37 { 38 QDF_STATUS status; 39 uint32_t cmd_id, cmd_type; 40 41 if (!queue || !ser_pdev_obj || !cmd_list) { 42 serialization_err("input parameters are invalid"); 43 return QDF_STATUS_E_FAILURE; 44 } 45 /* 46 * if the command is already removed in other context, 47 * then it will be marked as inactive with the same 48 * below code. So, test before proceeding. 49 */ 50 if (!qdf_atomic_test_and_clear_bit(CMD_IS_ACTIVE, 51 &cmd_list->cmd_in_use)) { 52 serialization_debug("CMD is not active or being used"); 53 return QDF_STATUS_SUCCESS; 54 } 55 status = wlan_serialization_remove_node(queue, &cmd_list->node, 56 ser_pdev_obj); 57 if (QDF_STATUS_SUCCESS != status) { 58 serialization_err("can't remove cmd from queue"); 59 /* assert to catch any leaks */ 60 QDF_ASSERT(0); 61 return status; 62 } 63 cmd_id = cmd_list->cmd.cmd_id; 64 cmd_type = cmd_list->cmd.cmd_type; 65 qdf_mem_zero(&cmd_list->cmd, sizeof(struct wlan_serialization_command)); 66 status = wlan_serialization_insert_back( 67 &ser_pdev_obj->global_cmd_pool_list, 68 &cmd_list->node, ser_pdev_obj); 69 qdf_atomic_clear_bit(CMD_MARKED_FOR_DELETE, &cmd_list->cmd_in_use); 70 if (QDF_STATUS_SUCCESS != status) { 71 serialization_err("can't put command back to global pool"); 72 QDF_ASSERT(0); 73 } 74 serialization_debug("cmd_id-%d, cmd_type-%d", cmd_id, cmd_type); 75 76 return status; 77 } 78 79 struct wlan_objmgr_pdev* 80 wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd) 81 { 82 struct wlan_objmgr_pdev *pdev = NULL; 83 84 if (!cmd) { 85 serialization_err("invalid cmd"); 86 return pdev; 87 } 88 if (!cmd->vdev) { 89 serialization_err("invalid cmd->vdev"); 90 return pdev; 91 } 92 pdev = wlan_vdev_get_pdev(cmd->vdev); 93 94 return pdev; 95 } 96 97 QDF_STATUS wlan_serialization_get_cmd_from_queue(qdf_list_t *queue, 98 qdf_list_node_t **nnode, 99 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 100 { 101 QDF_STATUS status; 102 qdf_list_node_t *pnode; 103 104 if (!queue || !ser_pdev_obj) { 105 serialization_err("input parameters are invalid"); 106 return QDF_STATUS_E_FAILURE; 107 } 108 109 pnode = *nnode; 110 if (!pnode) 111 status = wlan_serialization_peek_front(queue, nnode, 112 ser_pdev_obj); 113 else 114 status = wlan_serialization_peek_next(queue, pnode, nnode, 115 ser_pdev_obj); 116 117 if (status != QDF_STATUS_SUCCESS) { 118 serialization_err("can't get next node from queue"); 119 } 120 121 return status; 122 } 123 124 /** 125 * wlan_serialization_timer_destroy() - destroys the timer 126 * @ser_timer: pointer to particular timer 127 * 128 * This API destroys the memory allocated by timer and assigns cmd member of 129 * that timer structure to NULL 130 * 131 * Return: QDF_STATUS 132 */ 133 static QDF_STATUS wlan_serialization_timer_destroy( 134 struct wlan_serialization_timer *ser_timer) 135 { 136 QDF_STATUS status = QDF_STATUS_E_FAILURE; 137 138 if (!ser_timer || !ser_timer->cmd) { 139 serialization_debug("Invalid ser_timer"); 140 return status; 141 } 142 status = qdf_mc_timer_destroy(&ser_timer->timer); 143 if (!QDF_IS_STATUS_SUCCESS(status)) { 144 serialization_err("Failed to destroy timer for cmd_id[%d]", 145 ser_timer->cmd->cmd_id); 146 QDF_ASSERT(0); 147 return status; 148 } 149 ser_timer->cmd = NULL; 150 151 return status; 152 } 153 154 static void wlan_serialization_non_scan_timeout_action(void) 155 { 156 qdf_trigger_self_recovery(); 157 } 158 159 /** 160 * wlan_serialization_generic_timer_callback() - timer callback when timer fire 161 * @arg: argument that timer passes to this callback 162 * 163 * All the timers in serialization module calls this callback when they fire, 164 * and this API in turn calls command specific timeout callback and remove 165 * timed-out command from active queue and move any pending command to active 166 * queue of same cmd_type. 167 * 168 * Return: none 169 */ 170 static void wlan_serialization_generic_timer_callback(void *arg) 171 { 172 struct wlan_serialization_timer *timer = arg; 173 struct wlan_serialization_command *cmd = timer->cmd; 174 uint8_t vdev_id = WLAN_INVALID_VDEV_ID; 175 176 if (!cmd) { 177 serialization_err("command not found"); 178 QDF_ASSERT(0); 179 return; 180 } 181 182 if (cmd->vdev) 183 vdev_id = wlan_vdev_get_id(cmd->vdev); 184 185 serialization_err("active cmd timeout for cmd_type[%d] vdev_id[%d]", 186 cmd->cmd_type, vdev_id); 187 188 if (cmd->cmd_cb) 189 cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT); 190 191 if (cmd->cmd_type >= WLAN_SER_CMD_NONSCAN) 192 wlan_serialization_non_scan_timeout_action(); 193 /* 194 * dequeue cmd API will cleanup and destroy the timer. If it fails to 195 * dequeue command then we have to destroy the timer. It will also call 196 * cmd callback with WLAN_SER_CB_RELEASE_MEM_CMD to free the memory. 197 */ 198 if (WLAN_SER_CMD_NOT_FOUND == wlan_serialization_dequeue_cmd(cmd, true)) 199 wlan_serialization_timer_destroy(timer); 200 if (cmd->cmd_cb) 201 cmd->cmd_cb(cmd, WLAN_SER_CB_RELEASE_MEM_CMD); 202 } 203 204 /** 205 * wlan_serialization_stop_timer() - to stop particular timer 206 * @ser_timer: pointer to serialization timer 207 * 208 * This API stops the particular timer 209 * 210 * Return: QDF_STATUS 211 */ 212 static QDF_STATUS 213 wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer) 214 { 215 QDF_TIMER_STATE state; 216 QDF_STATUS status; 217 218 state = qdf_mc_timer_get_current_state(&ser_timer->timer); 219 if (QDF_TIMER_STATE_RUNNING != state && 220 QDF_TIMER_STATE_STARTING != state) { 221 serialization_debug("nothing to stop"); 222 wlan_serialization_timer_destroy(ser_timer); 223 return QDF_STATUS_SUCCESS; 224 } 225 status = qdf_mc_timer_stop(&ser_timer->timer); 226 if (!QDF_IS_STATUS_SUCCESS(status)) { 227 serialization_err("Failed to stop timer"); 228 /* to catch the bug */ 229 QDF_ASSERT(0); 230 return status; 231 } 232 wlan_serialization_timer_destroy(ser_timer); 233 status = QDF_STATUS_SUCCESS; 234 235 return status; 236 } 237 238 QDF_STATUS wlan_serialization_cleanup_all_timers( 239 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj) 240 { 241 struct wlan_serialization_timer *ser_timer; 242 QDF_STATUS status = QDF_STATUS_SUCCESS; 243 uint32_t i = 0; 244 245 if (!psoc_ser_obj) { 246 serialization_err("Invalid psoc_ser_obj"); 247 return QDF_STATUS_E_FAILURE; 248 } 249 250 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 251 ser_timer = &psoc_ser_obj->timers[i]; 252 if (!ser_timer->cmd) 253 continue; 254 status = wlan_serialization_stop_timer(ser_timer); 255 if (QDF_STATUS_SUCCESS != status) { 256 /* lets not break the loop but report error */ 257 serialization_err("some error in stopping timer"); 258 } 259 } 260 261 return status; 262 } 263 264 QDF_STATUS 265 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc, 266 struct wlan_serialization_command *cmd) 267 { 268 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj; 269 struct wlan_serialization_timer *ser_timer; 270 QDF_STATUS status = QDF_STATUS_E_FAILURE; 271 int i = 0; 272 273 if (!psoc || !cmd) { 274 serialization_err("invalid param"); 275 return status; 276 } 277 278 if ((cmd->cmd_timeout_duration == 0) && 279 (wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc) 280 ))) { 281 serialization_err("[SCAN-EMULATION]: Not performing timer functions\n"); 282 return QDF_STATUS_SUCCESS; 283 } 284 285 psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc); 286 /* 287 * Here cmd_id and cmd_type are used to locate the timer being 288 * associated with command. For scan command, cmd_id is expected to 289 * be unique and For non-scan command, there should be only one active 290 * command per pdev 291 */ 292 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 293 ser_timer = &psoc_ser_obj->timers[i]; 294 if (!(ser_timer->cmd) || 295 (ser_timer->cmd->cmd_id != cmd->cmd_id) || 296 (ser_timer->cmd->cmd_type != cmd->cmd_type) || 297 (ser_timer->cmd->vdev != cmd->vdev)) 298 continue; 299 status = wlan_serialization_stop_timer(ser_timer); 300 if (QDF_STATUS_SUCCESS != status) { 301 serialization_err("Failed to stop timer for cmd_id[%d]", 302 cmd->cmd_id); 303 } 304 break; 305 } 306 307 if (QDF_STATUS_SUCCESS != status) { 308 serialization_err("can't find timer for cmd_type[%d]", 309 cmd->cmd_type); 310 } 311 return status; 312 } 313 314 QDF_STATUS 315 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc, 316 struct wlan_serialization_command *cmd) 317 { 318 QDF_STATUS status = QDF_STATUS_E_FAILURE; 319 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj; 320 struct wlan_serialization_timer *ser_timer; 321 int i = 0; 322 323 if (!psoc || !cmd) { 324 serialization_err("invalid param"); 325 return status; 326 } 327 328 if ((cmd->cmd_timeout_duration == 0) && 329 (wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc) 330 ))) { 331 serialization_err("[SCAN-EMULATION]: Not performing timer functions\n"); 332 return QDF_STATUS_SUCCESS; 333 } 334 335 336 psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc); 337 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 338 /* Keep trying timer */ 339 ser_timer = &psoc_ser_obj->timers[i]; 340 if (ser_timer->cmd) 341 continue; 342 /* Remember timer is pointing to command */ 343 ser_timer->cmd = cmd; 344 if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_init(&ser_timer->timer, 345 QDF_TIMER_TYPE_SW, 346 wlan_serialization_generic_timer_callback, 347 ser_timer))) { 348 serialization_err("Failed to init timer cmdid [%d]", 349 cmd->cmd_id); 350 QDF_ASSERT(0); 351 continue; 352 } 353 if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_start(&ser_timer->timer, 354 cmd->cmd_timeout_duration))) { 355 serialization_err("Failed to start timer cmdid [%d]", 356 cmd->cmd_id); 357 wlan_serialization_timer_destroy(ser_timer); 358 QDF_ASSERT(0); 359 continue; 360 } 361 status = QDF_STATUS_SUCCESS; 362 break; 363 } 364 365 return status; 366 } 367 368 /** 369 * wlan_serialization_active_scan_cmd_count_handler() - count active scan cmds 370 * @psoc: pointer to soc strucutre 371 * @obj : pointer to pdev object 372 * @arg: pointer to argument 373 * 374 * This API will be called while iterating each pdev object and it will count 375 * number of scan commands present in that pdev object's active queue. count 376 * will be updated in *arg 377 * 378 * Return: none 379 */ 380 static void 381 wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc, 382 void *obj, void *arg) 383 { 384 struct wlan_objmgr_pdev *pdev = obj; 385 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 386 uint32_t *count = arg; 387 388 if (!pdev) { 389 serialization_err("invalid pdev"); 390 return; 391 } 392 393 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( 394 pdev, WLAN_UMAC_COMP_SERIALIZATION); 395 *count += wlan_serialization_list_size(&ser_pdev_obj->active_scan_list, 396 ser_pdev_obj); 397 } 398 399 /** 400 * wlan_serialization_is_active_scan_cmd_allowed() - find if scan cmd allowed 401 * @pdev: pointer to pdev object 402 * 403 * This API will be called to find out if active scan cmd is allowed. It has 404 * to iterate through all pdev to find out total number of active scan cmds. 405 * If total number of active scan cmds reach to allowed threshold then don't 406 * allow more scan cmd. 407 * 408 * Return: true or false 409 */ 410 static bool 411 wlan_serialization_is_active_scan_cmd_allowed(struct wlan_objmgr_pdev *pdev) 412 { 413 uint32_t count = 0; 414 struct wlan_objmgr_psoc *psoc; 415 416 if (!pdev) { 417 serialization_err("invalid pdev"); 418 return false; 419 } 420 421 psoc = wlan_pdev_get_psoc(pdev); 422 423 if (!psoc) { 424 serialization_err("invalid psoc"); 425 return false; 426 } 427 428 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 429 wlan_serialization_active_scan_cmd_count_handler, 430 &count, 1, WLAN_SERIALIZATION_ID); 431 if (count < ucfg_scan_get_max_active_scans(psoc)) { 432 serialization_debug("count is [%d]", count); 433 return true; 434 } 435 436 return false; 437 } 438 439 /** 440 * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed 441 * @pdev: pointer to pdev object 442 * 443 * This API will be called to find out if non scan cmd is allowed. 444 * 445 * Return: true or false 446 */ 447 static bool 448 wlan_serialization_is_active_nonscan_cmd_allowed(struct wlan_objmgr_pdev *pdev) 449 { 450 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 451 452 if (!pdev) { 453 serialization_err("invalid pdev"); 454 return false; 455 } 456 457 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( 458 pdev, WLAN_UMAC_COMP_SERIALIZATION); 459 460 if (!ser_pdev_obj) { 461 serialization_err("invalid ser_pdev_obj"); 462 return false; 463 } 464 465 if (wlan_serialization_list_empty(&ser_pdev_obj->active_list, 466 ser_pdev_obj)) 467 return true; 468 469 return false; 470 } 471 472 bool 473 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd) 474 { 475 struct wlan_objmgr_pdev *pdev; 476 477 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 478 if (!pdev) { 479 serialization_err("NULL pdev"); 480 return false; 481 } 482 483 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 484 return wlan_serialization_is_active_scan_cmd_allowed(pdev); 485 else 486 return wlan_serialization_is_active_nonscan_cmd_allowed(pdev); 487 } 488 489 QDF_STATUS wlan_serialization_validate_cmdtype( 490 enum wlan_serialization_cmd_type cmd_type) 491 { 492 serialization_debug("validate cmd_type:%d", cmd_type); 493 494 if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) { 495 serialization_err("Invalid cmd or comp passed"); 496 return QDF_STATUS_E_INVAL; 497 } 498 499 return QDF_STATUS_SUCCESS; 500 } 501 502 QDF_STATUS wlan_serialization_validate_cmd( 503 enum wlan_umac_comp_id comp_id, 504 enum wlan_serialization_cmd_type cmd_type) 505 { 506 serialization_debug("validate cmd_type:%d, comp_id:%d", 507 cmd_type, comp_id); 508 if (cmd_type < 0 || comp_id < 0 || 509 cmd_type >= WLAN_SER_CMD_MAX || 510 comp_id >= WLAN_UMAC_COMP_ID_MAX) { 511 serialization_err("Invalid cmd or comp passed"); 512 return QDF_STATUS_E_INVAL; 513 } 514 515 return QDF_STATUS_SUCCESS; 516 } 517 518 static void wlan_serialization_release_list_cmds( 519 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 520 qdf_list_t *list) 521 { 522 qdf_list_node_t *node = NULL; 523 524 while (!wlan_serialization_list_empty(list, ser_pdev_obj)) { 525 wlan_serialization_remove_front(list, &node, ser_pdev_obj); 526 wlan_serialization_insert_back( 527 &ser_pdev_obj->global_cmd_pool_list, 528 node, ser_pdev_obj); 529 } 530 531 return; 532 } 533 534 void wlan_serialization_destroy_list( 535 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 536 qdf_list_t *list) 537 { 538 wlan_serialization_release_list_cmds(ser_pdev_obj, list); 539 qdf_list_destroy(list); 540 } 541 542 struct wlan_serialization_psoc_priv_obj *wlan_serialization_get_psoc_priv_obj( 543 struct wlan_objmgr_psoc *psoc) 544 { 545 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 546 ser_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 547 WLAN_UMAC_COMP_SERIALIZATION); 548 549 return ser_soc_obj; 550 } 551 552 struct wlan_serialization_pdev_priv_obj *wlan_serialization_get_pdev_priv_obj( 553 struct wlan_objmgr_pdev *pdev) 554 { 555 struct wlan_serialization_pdev_priv_obj *obj; 556 obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 557 WLAN_UMAC_COMP_SERIALIZATION); 558 559 return obj; 560 } 561 562 struct wlan_serialization_psoc_priv_obj * 563 wlan_serialization_get_psoc_obj(struct wlan_serialization_command *cmd) 564 { 565 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = NULL; 566 struct wlan_objmgr_psoc *psoc; 567 568 if (!cmd->vdev) 569 return ser_soc_obj; 570 571 psoc = wlan_vdev_get_psoc(cmd->vdev); 572 ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc); 573 574 return ser_soc_obj; 575 } 576 577 bool wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev *vdev, 578 qdf_list_t *queue) 579 { 580 uint32_t queuelen; 581 qdf_list_node_t *nnode = NULL; 582 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 583 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 584 wlan_serialization_get_pdev_priv_obj(pdev); 585 QDF_STATUS status; 586 587 queuelen = wlan_serialization_list_size(queue, ser_pdev_obj); 588 if (!queuelen) { 589 serialization_debug("queue empty"); 590 return false; 591 } 592 593 while (queuelen--) { 594 status = wlan_serialization_get_cmd_from_queue(queue, &nnode, 595 ser_pdev_obj); 596 if (status != QDF_STATUS_SUCCESS) 597 break; 598 if (wlan_serialization_match_cmd_vdev(nnode, vdev)) 599 return true; 600 } 601 602 return false; 603 } 604 605 bool wlan_serialization_is_cmd_in_pdev_list( 606 struct wlan_objmgr_pdev *pdev, 607 qdf_list_t *queue) 608 { 609 uint32_t queuelen; 610 qdf_list_node_t *nnode = NULL; 611 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 612 wlan_serialization_get_pdev_priv_obj(pdev); 613 QDF_STATUS status; 614 615 queuelen = wlan_serialization_list_size(queue, ser_pdev_obj); 616 if (!queuelen) { 617 serialization_debug("queue empty"); 618 return false; 619 } 620 621 while (queuelen--) { 622 status = wlan_serialization_get_cmd_from_queue(queue, &nnode, 623 ser_pdev_obj); 624 if (status != QDF_STATUS_SUCCESS) 625 break; 626 if (wlan_serialization_match_cmd_pdev(nnode, pdev)) 627 return true; 628 } 629 630 return false; 631 } 632 633 enum wlan_serialization_cmd_status 634 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active, 635 bool cmd_in_pending) 636 { 637 if (cmd_in_active && cmd_in_pending) 638 return WLAN_SER_CMDS_IN_ALL_LISTS; 639 else if (cmd_in_active) 640 return WLAN_SER_CMD_IN_ACTIVE_LIST; 641 else if (cmd_in_pending) 642 return WLAN_SER_CMD_IN_PENDING_LIST; 643 else 644 return WLAN_SER_CMD_NOT_FOUND; 645 } 646 647 static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue, 648 struct wlan_serialization_command *cmd, 649 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 650 { 651 uint32_t qsize; 652 QDF_STATUS status; 653 struct wlan_serialization_command_list *cmd_list = NULL; 654 qdf_list_node_t *nnode = NULL, *pnode = NULL; 655 bool found = false; 656 657 qsize = wlan_serialization_list_size(queue, ser_pdev_obj); 658 while (qsize--) { 659 if (!cmd_list) 660 status = wlan_serialization_peek_front(queue, &nnode, 661 ser_pdev_obj); 662 else 663 status = wlan_serialization_peek_next(queue, pnode, 664 &nnode, 665 ser_pdev_obj); 666 667 if (status != QDF_STATUS_SUCCESS) 668 break; 669 670 pnode = nnode; 671 cmd_list = qdf_container_of(nnode, 672 struct wlan_serialization_command_list, node); 673 if (wlan_serialization_match_cmd_id_type(nnode, cmd, 674 ser_pdev_obj) && 675 wlan_serialization_match_cmd_vdev(nnode, cmd->vdev)) { 676 found = true; 677 break; 678 } 679 nnode = NULL; 680 } 681 682 return found; 683 } 684 685 bool wlan_serialization_is_cmd_present_queue( 686 struct wlan_serialization_command *cmd, 687 uint8_t is_active_queue) 688 { 689 qdf_list_t *queue; 690 struct wlan_objmgr_pdev *pdev; 691 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 692 693 if (!cmd) { 694 serialization_err("invalid params"); 695 return false; 696 } 697 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 698 if (!pdev) { 699 serialization_err("invalid pdev"); 700 return false; 701 } 702 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 703 WLAN_UMAC_COMP_SERIALIZATION); 704 if (!ser_pdev_obj) { 705 serialization_err("invalid ser_pdev_obj"); 706 return false; 707 } 708 if (!is_active_queue) { 709 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 710 queue = &ser_pdev_obj->pending_scan_list; 711 else 712 queue = &ser_pdev_obj->pending_list; 713 } else { 714 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 715 queue = &ser_pdev_obj->active_scan_list; 716 else 717 queue = &ser_pdev_obj->active_list; 718 } 719 720 return wlan_serialization_is_cmd_present_in_given_queue(queue, cmd, 721 ser_pdev_obj); 722 } 723 724 bool wlan_serialization_list_empty( 725 qdf_list_t *queue, 726 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 727 { 728 bool is_empty; 729 730 wlan_serialization_acquire_lock(ser_pdev_obj); 731 if (qdf_list_empty(queue)) 732 is_empty = true; 733 else 734 is_empty = false; 735 wlan_serialization_release_lock(ser_pdev_obj); 736 737 return is_empty; 738 } 739 740 uint32_t wlan_serialization_list_size( 741 qdf_list_t *queue, 742 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 743 { 744 uint32_t size; 745 746 wlan_serialization_acquire_lock(ser_pdev_obj); 747 size = qdf_list_size(queue); 748 wlan_serialization_release_lock(ser_pdev_obj); 749 750 return size; 751 } 752 753 QDF_STATUS wlan_serialization_remove_front( 754 qdf_list_t *list, 755 qdf_list_node_t **node, 756 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 757 { 758 QDF_STATUS status; 759 760 wlan_serialization_acquire_lock(ser_pdev_obj); 761 status = qdf_list_remove_front(list, node); 762 wlan_serialization_release_lock(ser_pdev_obj); 763 764 return status; 765 } 766 767 QDF_STATUS wlan_serialization_remove_node( 768 qdf_list_t *list, 769 qdf_list_node_t *node, 770 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 771 { 772 QDF_STATUS status; 773 774 wlan_serialization_acquire_lock(ser_pdev_obj); 775 status = qdf_list_remove_node(list, node); 776 wlan_serialization_release_lock(ser_pdev_obj); 777 778 return status; 779 } 780 781 QDF_STATUS wlan_serialization_insert_front( 782 qdf_list_t *list, 783 qdf_list_node_t *node, 784 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 785 { 786 QDF_STATUS status; 787 788 wlan_serialization_acquire_lock(ser_pdev_obj); 789 status = qdf_list_insert_front(list, node); 790 wlan_serialization_release_lock(ser_pdev_obj); 791 792 return status; 793 } 794 795 QDF_STATUS wlan_serialization_insert_back( 796 qdf_list_t *list, 797 qdf_list_node_t *node, 798 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 799 { 800 QDF_STATUS status; 801 802 wlan_serialization_acquire_lock(ser_pdev_obj); 803 status = qdf_list_insert_back(list, node); 804 wlan_serialization_release_lock(ser_pdev_obj); 805 806 return status; 807 } 808 809 QDF_STATUS wlan_serialization_peek_front( 810 qdf_list_t *list, 811 qdf_list_node_t **node, 812 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 813 { 814 QDF_STATUS status; 815 816 wlan_serialization_acquire_lock(ser_pdev_obj); 817 status = qdf_list_peek_front(list, node); 818 wlan_serialization_release_lock(ser_pdev_obj); 819 820 return status; 821 } 822 823 QDF_STATUS wlan_serialization_peek_next( 824 qdf_list_t *list, 825 qdf_list_node_t *node1, qdf_list_node_t **node2, 826 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 827 { 828 QDF_STATUS status; 829 830 wlan_serialization_acquire_lock(ser_pdev_obj); 831 status = qdf_list_peek_next(list, node1, node2); 832 wlan_serialization_release_lock(ser_pdev_obj); 833 834 return status; 835 } 836 837 bool wlan_serialization_match_cmd_scan_id( 838 qdf_list_node_t *nnode, 839 struct wlan_serialization_command **cmd, 840 uint16_t scan_id, struct wlan_objmgr_vdev *vdev, 841 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 842 { 843 struct wlan_serialization_command_list *cmd_list = NULL; 844 bool match_found = false; 845 846 wlan_serialization_acquire_lock(ser_pdev_obj); 847 cmd_list = qdf_container_of(nnode, 848 struct wlan_serialization_command_list, 849 node); 850 if ((cmd_list->cmd.cmd_id == scan_id) && 851 (cmd_list->cmd.vdev == vdev)) { 852 *cmd = &cmd_list->cmd; 853 match_found = true; 854 }; 855 wlan_serialization_release_lock(ser_pdev_obj); 856 857 return match_found; 858 } 859 860 bool wlan_serialization_match_cmd_id_type( 861 qdf_list_node_t *nnode, 862 struct wlan_serialization_command *cmd, 863 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 864 { 865 struct wlan_serialization_command_list *cmd_list = NULL; 866 bool match_found = true; 867 868 if (!cmd) 869 return false; 870 wlan_serialization_acquire_lock(ser_pdev_obj); 871 cmd_list = qdf_container_of(nnode, 872 struct wlan_serialization_command_list, 873 node); 874 if ((cmd_list->cmd.cmd_id != cmd->cmd_id) || 875 (cmd_list->cmd.cmd_type != cmd->cmd_type)) { 876 match_found = false; 877 }; 878 wlan_serialization_release_lock(ser_pdev_obj); 879 880 return match_found; 881 } 882 883 bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode, 884 struct wlan_objmgr_vdev *vdev) 885 { 886 struct wlan_serialization_command_list *cmd_list = NULL; 887 bool match_found = false; 888 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 889 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 890 wlan_serialization_get_pdev_priv_obj(pdev); 891 892 wlan_serialization_acquire_lock(ser_pdev_obj); 893 cmd_list = qdf_container_of(nnode, 894 struct wlan_serialization_command_list, 895 node); 896 if (cmd_list->cmd.vdev == vdev) 897 match_found = true; 898 wlan_serialization_release_lock(ser_pdev_obj); 899 900 return match_found; 901 } 902 903 bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode, 904 struct wlan_objmgr_pdev *pdev) 905 { 906 struct wlan_serialization_command_list *cmd_list = NULL; 907 bool match_found = false; 908 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 909 wlan_serialization_get_pdev_priv_obj(pdev); 910 struct wlan_objmgr_pdev *node_pdev = NULL; 911 912 wlan_serialization_acquire_lock(ser_pdev_obj); 913 cmd_list = qdf_container_of(nnode, 914 struct wlan_serialization_command_list, 915 node); 916 node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev); 917 if (node_pdev == pdev) 918 match_found = true; 919 wlan_serialization_release_lock(ser_pdev_obj); 920 921 return match_found; 922 } 923 924 #ifdef WLAN_CMD_SERIALIZATION_LOCKING 925 QDF_STATUS 926 wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj) 927 { 928 if (!obj) { 929 serialization_err("invalid object"); 930 return QDF_STATUS_E_FAILURE; 931 } 932 qdf_spin_lock_bh(&obj->pdev_ser_list_lock); 933 934 return QDF_STATUS_SUCCESS; 935 } 936 937 QDF_STATUS 938 wlan_serialization_release_lock(struct wlan_serialization_pdev_priv_obj *obj) 939 { 940 if (!obj) { 941 serialization_err("invalid object"); 942 return QDF_STATUS_E_FAILURE; 943 } 944 qdf_spin_unlock_bh(&obj->pdev_ser_list_lock); 945 946 return QDF_STATUS_SUCCESS; 947 } 948 949 QDF_STATUS 950 wlan_serialization_create_lock(struct wlan_serialization_pdev_priv_obj *obj) 951 { 952 if (!obj) { 953 serialization_err("invalid object"); 954 return QDF_STATUS_E_FAILURE; 955 } 956 qdf_spinlock_create(&obj->pdev_ser_list_lock); 957 958 return QDF_STATUS_SUCCESS; 959 } 960 961 QDF_STATUS 962 wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj) 963 { 964 if (!obj) { 965 serialization_err("invalid object"); 966 return QDF_STATUS_E_FAILURE; 967 } 968 qdf_spinlock_destroy(&obj->pdev_ser_list_lock); 969 970 return QDF_STATUS_SUCCESS; 971 } 972 #else 973 QDF_STATUS 974 wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj) 975 { 976 return QDF_STATUS_SUCCESS; 977 } 978 979 QDF_STATUS 980 wlan_serialization_release_lock(struct wlan_serialization_pdev_priv_obj *obj) 981 { 982 return QDF_STATUS_SUCCESS; 983 } 984 985 QDF_STATUS 986 wlan_serialization_create_lock(struct wlan_serialization_pdev_priv_obj *obj) 987 { 988 return QDF_STATUS_SUCCESS; 989 } 990 991 QDF_STATUS 992 wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj) 993 { 994 return QDF_STATUS_SUCCESS; 995 } 996 #endif 997 #else /*New serialization code*/ 998 #include <wlan_objmgr_vdev_obj.h> 999 #include <wlan_objmgr_pdev_obj.h> 1000 #include <qdf_mc_timer.h> 1001 #include <wlan_utility.h> 1002 #include "wlan_serialization_utils_i.h" 1003 #include "wlan_serialization_main_i.h" 1004 #include "wlan_serialization_queue_i.h" 1005 #include "wlan_serialization_api.h" 1006 1007 struct wlan_objmgr_pdev* 1008 wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd) 1009 { 1010 struct wlan_objmgr_pdev *pdev = NULL; 1011 1012 if (!cmd) { 1013 ser_err("invalid cmd"); 1014 return pdev; 1015 } 1016 if (!cmd->vdev) { 1017 ser_err("invalid cmd->vdev"); 1018 return pdev; 1019 } 1020 pdev = wlan_vdev_get_pdev(cmd->vdev); 1021 1022 return pdev; 1023 } 1024 1025 struct wlan_objmgr_psoc* 1026 wlan_serialization_get_psoc_from_cmd(struct wlan_serialization_command *cmd) 1027 { 1028 struct wlan_objmgr_psoc *psoc = NULL; 1029 1030 if (!cmd) { 1031 ser_err("invalid cmd"); 1032 return psoc; 1033 } 1034 if (!cmd->vdev) { 1035 ser_err("invalid cmd->vdev"); 1036 return psoc; 1037 } 1038 psoc = wlan_vdev_get_psoc(cmd->vdev); 1039 1040 return psoc; 1041 } 1042 1043 struct wlan_objmgr_vdev* 1044 wlan_serialization_get_vdev_from_cmd(struct wlan_serialization_command *cmd) 1045 { 1046 struct wlan_objmgr_vdev *vdev = NULL; 1047 1048 if (!cmd) { 1049 ser_err("invalid cmd"); 1050 goto error; 1051 } 1052 1053 vdev = cmd->vdev; 1054 1055 error: 1056 return vdev; 1057 } 1058 1059 QDF_STATUS 1060 wlan_serialization_get_cmd_from_queue(qdf_list_t *queue, 1061 qdf_list_node_t **nnode) 1062 { 1063 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1064 qdf_list_node_t *pnode; 1065 1066 if (!queue) { 1067 ser_err("input parameters are invalid"); 1068 goto error; 1069 } 1070 1071 pnode = *nnode; 1072 if (!pnode) 1073 status = wlan_serialization_peek_front(queue, nnode); 1074 else 1075 status = wlan_serialization_peek_next(queue, pnode, nnode); 1076 1077 if (status != QDF_STATUS_SUCCESS) 1078 ser_err("can't get next node from queue"); 1079 1080 error: 1081 return status; 1082 } 1083 1084 QDF_STATUS wlan_serialization_timer_destroy( 1085 struct wlan_serialization_timer *ser_timer) 1086 { 1087 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 1088 1089 if (!ser_timer || !ser_timer->cmd) { 1090 ser_debug("Invalid ser_timer"); 1091 qdf_status = QDF_STATUS_E_FAILURE; 1092 goto error; 1093 } 1094 1095 ser_debug("Destroying the timer"); 1096 qdf_timer_stop(&ser_timer->timer); 1097 ser_timer->cmd = NULL; 1098 1099 error: 1100 return qdf_status; 1101 } 1102 1103 /** 1104 * wlan_serialization_stop_timer() - to stop particular timer 1105 * @ser_timer: pointer to serialization timer 1106 * 1107 * This API stops the particular timer 1108 * 1109 * Return: QDF_STATUS 1110 */ 1111 QDF_STATUS 1112 wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer) 1113 { 1114 wlan_serialization_timer_destroy(ser_timer); 1115 1116 return QDF_STATUS_SUCCESS; 1117 } 1118 1119 QDF_STATUS wlan_serialization_cleanup_all_timers( 1120 struct wlan_ser_psoc_obj *psoc_ser_obj) 1121 { 1122 struct wlan_serialization_timer *ser_timer; 1123 QDF_STATUS status = QDF_STATUS_SUCCESS; 1124 uint32_t i = 0; 1125 1126 ser_enter(); 1127 1128 if (!psoc_ser_obj) { 1129 ser_err("Invalid psoc_ser_obj"); 1130 status = QDF_STATUS_E_FAILURE; 1131 goto error; 1132 } 1133 1134 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); 1135 1136 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 1137 ser_timer = &psoc_ser_obj->timers[i]; 1138 if (!ser_timer->cmd) 1139 continue; 1140 status = wlan_serialization_stop_timer(ser_timer); 1141 if (QDF_STATUS_SUCCESS != status) { 1142 /* lets not break the loop but report error */ 1143 ser_err("some error in stopping timer"); 1144 } 1145 } 1146 1147 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); 1148 error: 1149 ser_exit(); 1150 return status; 1151 } 1152 1153 QDF_STATUS wlan_serialization_validate_cmdtype( 1154 enum wlan_serialization_cmd_type cmd_type) 1155 { 1156 if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) { 1157 ser_err("Invalid cmd or comp passed"); 1158 return QDF_STATUS_E_INVAL; 1159 } 1160 1161 return QDF_STATUS_SUCCESS; 1162 } 1163 1164 QDF_STATUS wlan_serialization_validate_cmd( 1165 enum wlan_umac_comp_id comp_id, 1166 enum wlan_serialization_cmd_type cmd_type) 1167 { 1168 QDF_STATUS status = QDF_STATUS_E_INVAL; 1169 1170 ser_debug("validate cmd_type:%d, comp_id:%d", 1171 cmd_type, comp_id); 1172 if (cmd_type < 0 || comp_id < 0 || 1173 cmd_type >= WLAN_SER_CMD_MAX || 1174 comp_id >= WLAN_UMAC_COMP_ID_MAX) { 1175 ser_err("Invalid cmd or comp passed"); 1176 goto error; 1177 } 1178 1179 status = QDF_STATUS_SUCCESS; 1180 error: 1181 return status; 1182 } 1183 1184 QDF_STATUS wlan_serialization_validate_cmd_list( 1185 struct wlan_serialization_command_list *cmd_list) 1186 { 1187 QDF_STATUS status = QDF_STATUS_E_INVAL; 1188 1189 if (!cmd_list->cmd.cmd_cb) { 1190 ser_err("no cmd_cb for cmd type:%d, id: %d", 1191 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 1192 QDF_ASSERT(0); 1193 goto error; 1194 } 1195 1196 if (!cmd_list->cmd.vdev) { 1197 ser_err("invalid cmd.vdev"); 1198 goto error; 1199 } 1200 1201 status = QDF_STATUS_SUCCESS; 1202 1203 error: 1204 return status; 1205 } 1206 1207 static void wlan_serialization_release_pdev_list_cmds( 1208 struct wlan_serialization_pdev_queue *pdev_queue) 1209 { 1210 qdf_list_node_t *node = NULL; 1211 1212 ser_enter(); 1213 1214 while (!wlan_serialization_list_empty(&pdev_queue->active_list)) { 1215 wlan_serialization_remove_front( 1216 &pdev_queue->active_list, &node); 1217 wlan_serialization_insert_back( 1218 &pdev_queue->cmd_pool_list, node); 1219 } 1220 1221 while (!wlan_serialization_list_empty(&pdev_queue->pending_list)) { 1222 wlan_serialization_remove_front( 1223 &pdev_queue->pending_list, &node); 1224 wlan_serialization_insert_back( 1225 &pdev_queue->cmd_pool_list, node); 1226 } 1227 1228 ser_exit(); 1229 } 1230 1231 static void wlan_serialization_release_vdev_list_cmds(qdf_list_t *list) 1232 { 1233 qdf_list_node_t *node = NULL; 1234 1235 ser_enter(); 1236 1237 while (!wlan_serialization_list_empty(list)) 1238 wlan_serialization_remove_front(list, &node); 1239 1240 ser_exit(); 1241 } 1242 1243 void wlan_serialization_destroy_pdev_list( 1244 struct wlan_serialization_pdev_queue *pdev_queue) 1245 { 1246 ser_enter(); 1247 1248 wlan_serialization_release_pdev_list_cmds(pdev_queue); 1249 qdf_list_destroy(&pdev_queue->active_list); 1250 qdf_list_destroy(&pdev_queue->pending_list); 1251 1252 ser_exit(); 1253 } 1254 1255 void wlan_serialization_destroy_vdev_list(qdf_list_t *list) 1256 { 1257 ser_enter(); 1258 1259 wlan_serialization_release_vdev_list_cmds(list); 1260 qdf_list_destroy(list); 1261 1262 ser_exit(); 1263 } 1264 1265 struct wlan_ser_psoc_obj *wlan_serialization_get_psoc_obj( 1266 struct wlan_objmgr_psoc *psoc) 1267 { 1268 struct wlan_ser_psoc_obj *ser_soc_obj; 1269 1270 ser_soc_obj = 1271 wlan_objmgr_psoc_get_comp_private_obj( 1272 psoc, WLAN_UMAC_COMP_SERIALIZATION); 1273 1274 return ser_soc_obj; 1275 } 1276 1277 struct wlan_ser_pdev_obj *wlan_serialization_get_pdev_obj( 1278 struct wlan_objmgr_pdev *pdev) 1279 { 1280 struct wlan_ser_pdev_obj *obj; 1281 1282 obj = wlan_objmgr_pdev_get_comp_private_obj( 1283 pdev, WLAN_UMAC_COMP_SERIALIZATION); 1284 1285 return obj; 1286 } 1287 1288 struct wlan_ser_vdev_obj *wlan_serialization_get_vdev_obj( 1289 struct wlan_objmgr_vdev *vdev) 1290 { 1291 struct wlan_ser_vdev_obj *obj; 1292 1293 obj = wlan_objmgr_vdev_get_comp_private_obj( 1294 vdev, WLAN_UMAC_COMP_SERIALIZATION); 1295 1296 return obj; 1297 } 1298 1299 bool wlan_serialization_is_cmd_in_vdev_list( 1300 struct wlan_objmgr_vdev *vdev, 1301 qdf_list_t *queue, 1302 enum wlan_serialization_node node_type) 1303 { 1304 qdf_list_node_t *node = NULL; 1305 bool cmd_found = false; 1306 1307 ser_enter(); 1308 1309 node = wlan_serialization_find_cmd( 1310 queue, WLAN_SER_MATCH_VDEV, 1311 NULL, 0, NULL, vdev, node_type); 1312 1313 if (node) 1314 cmd_found = true; 1315 1316 ser_exit(); 1317 return cmd_found; 1318 } 1319 1320 bool wlan_serialization_is_cmd_in_pdev_list( 1321 struct wlan_objmgr_pdev *pdev, 1322 qdf_list_t *queue) 1323 { 1324 qdf_list_node_t *node = NULL; 1325 bool cmd_found = false; 1326 1327 ser_enter(); 1328 1329 node = wlan_serialization_find_cmd( 1330 queue, WLAN_SER_MATCH_PDEV, 1331 NULL, 0, pdev, NULL, WLAN_SER_PDEV_NODE); 1332 1333 if (node) 1334 cmd_found = true; 1335 1336 ser_exit(); 1337 return cmd_found; 1338 } 1339 1340 enum wlan_serialization_cmd_status 1341 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active, 1342 bool cmd_in_pending) 1343 { 1344 enum wlan_serialization_cmd_status status; 1345 1346 if (cmd_in_active && cmd_in_pending) 1347 status = WLAN_SER_CMDS_IN_ALL_LISTS; 1348 else if (cmd_in_active) 1349 status = WLAN_SER_CMD_IN_ACTIVE_LIST; 1350 else if (cmd_in_pending) 1351 status = WLAN_SER_CMD_IN_PENDING_LIST; 1352 else 1353 status = WLAN_SER_CMD_NOT_FOUND; 1354 1355 return status; 1356 } 1357 1358 bool 1359 wlan_serialization_is_cmd_present_in_given_queue( 1360 qdf_list_t *queue, 1361 struct wlan_serialization_command *cmd, 1362 enum wlan_serialization_node node_type) 1363 { 1364 qdf_list_node_t *node = NULL; 1365 bool found = false; 1366 1367 node = wlan_serialization_find_cmd( 1368 queue, WLAN_SER_MATCH_CMD_ID_VDEV, 1369 cmd, 0, NULL, cmd->vdev, node_type); 1370 1371 if (node) 1372 found = true; 1373 1374 return found; 1375 } 1376 1377 /** 1378 * wlan_serialization_remove_cmd_from_queue() - to remove command from 1379 * given queue 1380 * @queue: queue from which command needs to be removed 1381 * @cmd: command to match in the queue 1382 * @ser_pdev_obj: pointer to private pdev serialization object 1383 * 1384 * This API takes the queue, it matches the provided command from this queue 1385 * and removes it. Before removing the command, it will notify the caller 1386 * that if it needs to remove any memory allocated by caller. 1387 * 1388 * Return: none 1389 */ 1390 QDF_STATUS 1391 wlan_serialization_remove_cmd_from_queue( 1392 qdf_list_t *queue, 1393 struct wlan_serialization_command *cmd, 1394 struct wlan_serialization_command_list **pcmd_list, 1395 struct wlan_ser_pdev_obj *ser_pdev_obj, 1396 enum wlan_serialization_node node_type) 1397 { 1398 struct wlan_serialization_command_list *cmd_list; 1399 qdf_list_node_t *node = NULL; 1400 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1401 1402 if (!cmd) 1403 goto error; 1404 1405 if (wlan_serialization_list_empty(queue)) { 1406 ser_err("Empty queue"); 1407 goto error; 1408 } 1409 1410 node = wlan_serialization_find_cmd(queue, WLAN_SER_MATCH_CMD_ID_VDEV, 1411 cmd, 0, NULL, cmd->vdev, node_type); 1412 1413 if (!node) 1414 goto error; 1415 1416 if (node_type == WLAN_SER_PDEV_NODE) 1417 cmd_list = 1418 qdf_container_of(node, 1419 struct wlan_serialization_command_list, 1420 pdev_node); 1421 else 1422 cmd_list = 1423 qdf_container_of(node, 1424 struct wlan_serialization_command_list, 1425 vdev_node); 1426 1427 ser_debug("Matching command found for removal from queue"); 1428 ser_debug("remove cmd: type[%d] id[%d] prio[%d] blocking[%d]", 1429 cmd_list->cmd.cmd_type, 1430 cmd_list->cmd.cmd_id, 1431 cmd_list->cmd.is_high_priority, 1432 cmd_list->cmd.is_blocking); 1433 1434 status = wlan_serialization_remove_node(queue, node); 1435 1436 if (QDF_STATUS_SUCCESS != status) 1437 ser_err("Fail to add to free pool type[%d]", 1438 cmd->cmd_type); 1439 1440 *pcmd_list = cmd_list; 1441 1442 error: 1443 return status; 1444 } 1445 1446 enum wlan_serialization_status 1447 wlan_serialization_add_cmd_to_queue( 1448 qdf_list_t *queue, 1449 struct wlan_serialization_command_list *cmd_list, 1450 struct wlan_ser_pdev_obj *ser_pdev_obj, 1451 uint8_t is_cmd_for_active_queue, 1452 enum wlan_serialization_node node_type) 1453 { 1454 enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 1455 QDF_STATUS qdf_status; 1456 qdf_list_node_t *node; 1457 1458 if (!cmd_list || !queue || !ser_pdev_obj) { 1459 ser_err("Input arguments are not valid"); 1460 goto error; 1461 } 1462 1463 if (node_type == WLAN_SER_PDEV_NODE) { 1464 node = &cmd_list->pdev_node; 1465 ser_debug("pdev_queue: %pK", queue); 1466 } else { 1467 node = &cmd_list->vdev_node; 1468 ser_debug("vdev_queue: %pK", queue); 1469 } 1470 1471 ser_debug("add cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 1472 cmd_list->cmd.cmd_type, 1473 cmd_list->cmd.cmd_id, 1474 cmd_list->cmd.is_high_priority, 1475 cmd_list->cmd.is_blocking); 1476 1477 if (qdf_list_size(queue) == qdf_list_max_size(queue)) { 1478 status = WLAN_SER_CMD_DENIED_LIST_FULL; 1479 goto error; 1480 } 1481 1482 if (cmd_list->cmd.is_high_priority) 1483 qdf_status = wlan_serialization_insert_front(queue, node); 1484 else 1485 qdf_status = wlan_serialization_insert_back(queue, node); 1486 1487 if (QDF_IS_STATUS_ERROR(qdf_status)) 1488 goto error; 1489 1490 ser_debug("adding cmd to node: %pK", node); 1491 1492 if (is_cmd_for_active_queue) 1493 status = WLAN_SER_CMD_ACTIVE; 1494 else 1495 status = WLAN_SER_CMD_PENDING; 1496 1497 error: 1498 return status; 1499 } 1500 1501 bool wlan_serialization_list_empty(qdf_list_t *queue) 1502 { 1503 bool is_empty; 1504 1505 if (qdf_list_empty(queue)) 1506 is_empty = true; 1507 else 1508 is_empty = false; 1509 1510 return is_empty; 1511 } 1512 1513 uint32_t wlan_serialization_list_size(qdf_list_t *queue) 1514 { 1515 uint32_t size; 1516 1517 size = qdf_list_size(queue); 1518 1519 return size; 1520 } 1521 1522 QDF_STATUS wlan_serialization_remove_front(qdf_list_t *list, 1523 qdf_list_node_t **node) 1524 { 1525 QDF_STATUS status; 1526 1527 if (wlan_serialization_list_empty(list)) { 1528 ser_err("The list is empty"); 1529 status = QDF_STATUS_E_EMPTY; 1530 goto error; 1531 } 1532 1533 status = qdf_list_remove_front(list, node); 1534 error: 1535 return status; 1536 } 1537 1538 QDF_STATUS wlan_serialization_remove_node(qdf_list_t *list, 1539 qdf_list_node_t *node) 1540 { 1541 QDF_STATUS status; 1542 1543 if (wlan_serialization_list_empty(list)) { 1544 ser_err("The list is empty"); 1545 status = QDF_STATUS_E_EMPTY; 1546 goto error; 1547 } 1548 status = qdf_list_remove_node(list, node); 1549 1550 error: 1551 return status; 1552 } 1553 1554 QDF_STATUS wlan_serialization_insert_front(qdf_list_t *list, 1555 qdf_list_node_t *node) 1556 { 1557 QDF_STATUS status; 1558 1559 status = qdf_list_insert_front(list, node); 1560 1561 return status; 1562 } 1563 1564 QDF_STATUS wlan_serialization_insert_back(qdf_list_t *list, 1565 qdf_list_node_t *node) 1566 { 1567 QDF_STATUS status; 1568 1569 status = qdf_list_insert_back(list, node); 1570 1571 return status; 1572 } 1573 1574 QDF_STATUS wlan_serialization_peek_front(qdf_list_t *list, 1575 qdf_list_node_t **node) 1576 { 1577 QDF_STATUS status; 1578 1579 status = qdf_list_peek_front(list, node); 1580 1581 return status; 1582 } 1583 1584 QDF_STATUS wlan_serialization_peek_next(qdf_list_t *list, 1585 qdf_list_node_t *node1, 1586 qdf_list_node_t **node2) 1587 { 1588 QDF_STATUS status; 1589 1590 status = qdf_list_peek_next(list, node1, node2); 1591 1592 return status; 1593 } 1594 1595 bool 1596 wlan_serialization_match_cmd_type(qdf_list_node_t *nnode, 1597 enum wlan_serialization_cmd_type cmd_type, 1598 enum wlan_serialization_node node_type) 1599 { 1600 struct wlan_serialization_command_list *cmd_list = NULL; 1601 bool match_found = true; 1602 1603 if (node_type == WLAN_SER_PDEV_NODE) 1604 cmd_list = 1605 qdf_container_of(nnode, 1606 struct wlan_serialization_command_list, 1607 pdev_node); 1608 else 1609 cmd_list = 1610 qdf_container_of(nnode, 1611 struct wlan_serialization_command_list, 1612 vdev_node); 1613 1614 if (cmd_list->cmd.cmd_type != cmd_type) 1615 match_found = false; 1616 1617 return match_found; 1618 } 1619 1620 bool 1621 wlan_serialization_match_cmd_id_type(qdf_list_node_t *nnode, 1622 struct wlan_serialization_command *cmd, 1623 enum wlan_serialization_node node_type) 1624 { 1625 struct wlan_serialization_command_list *cmd_list = NULL; 1626 bool match_found = true; 1627 1628 if (!cmd) { 1629 match_found = false; 1630 goto error; 1631 } 1632 1633 if (node_type == WLAN_SER_PDEV_NODE) 1634 cmd_list = 1635 qdf_container_of(nnode, 1636 struct wlan_serialization_command_list, 1637 pdev_node); 1638 else 1639 cmd_list = 1640 qdf_container_of(nnode, 1641 struct wlan_serialization_command_list, 1642 vdev_node); 1643 1644 if ((cmd_list->cmd.cmd_id != cmd->cmd_id) || 1645 (cmd_list->cmd.cmd_type != cmd->cmd_type)) { 1646 match_found = false; 1647 }; 1648 1649 error: 1650 return match_found; 1651 } 1652 1653 bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode, 1654 struct wlan_objmgr_vdev *vdev, 1655 enum wlan_serialization_node node_type) 1656 { 1657 struct wlan_serialization_command_list *cmd_list = NULL; 1658 bool match_found = false; 1659 1660 if (node_type == WLAN_SER_PDEV_NODE) 1661 cmd_list = 1662 qdf_container_of(nnode, 1663 struct wlan_serialization_command_list, 1664 pdev_node); 1665 else 1666 cmd_list = 1667 qdf_container_of(nnode, 1668 struct wlan_serialization_command_list, 1669 vdev_node); 1670 1671 if (cmd_list->cmd.vdev == vdev) 1672 match_found = true; 1673 1674 ser_debug("matching cmd found(vdev:%pK): %d", vdev, match_found); 1675 return match_found; 1676 } 1677 1678 bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode, 1679 struct wlan_objmgr_pdev *pdev, 1680 enum wlan_serialization_node node_type) 1681 { 1682 struct wlan_serialization_command_list *cmd_list = NULL; 1683 bool match_found = false; 1684 struct wlan_objmgr_pdev *node_pdev = NULL; 1685 1686 if (node_type == WLAN_SER_PDEV_NODE) 1687 cmd_list = 1688 qdf_container_of(nnode, 1689 struct wlan_serialization_command_list, 1690 pdev_node); 1691 else 1692 cmd_list = 1693 qdf_container_of(nnode, 1694 struct wlan_serialization_command_list, 1695 vdev_node); 1696 1697 node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev); 1698 if (node_pdev == pdev) 1699 match_found = true; 1700 1701 return match_found; 1702 } 1703 1704 qdf_list_node_t * 1705 wlan_serialization_find_cmd(qdf_list_t *queue, 1706 enum wlan_serialization_match_type match_type, 1707 struct wlan_serialization_command *cmd, 1708 enum wlan_serialization_cmd_type cmd_type, 1709 struct wlan_objmgr_pdev *pdev, 1710 struct wlan_objmgr_vdev *vdev, 1711 enum wlan_serialization_node node_type) 1712 { 1713 qdf_list_node_t *cmd_node = NULL; 1714 uint32_t queuelen; 1715 qdf_list_node_t *nnode = NULL; 1716 QDF_STATUS status; 1717 bool node_found = 0; 1718 1719 queuelen = wlan_serialization_list_size(queue); 1720 1721 if (!queuelen) { 1722 ser_debug("queue empty"); 1723 goto error; 1724 } 1725 1726 while (queuelen--) { 1727 status = wlan_serialization_get_cmd_from_queue(queue, &nnode); 1728 if (status != QDF_STATUS_SUCCESS) 1729 break; 1730 1731 switch (match_type) { 1732 case WLAN_SER_MATCH_PDEV: 1733 if (wlan_serialization_match_cmd_pdev( 1734 nnode, pdev, WLAN_SER_PDEV_NODE)) 1735 node_found = 1; 1736 break; 1737 case WLAN_SER_MATCH_VDEV: 1738 if (wlan_serialization_match_cmd_vdev( 1739 nnode, vdev, node_type)) 1740 node_found = 1; 1741 break; 1742 case WLAN_SER_MATCH_CMD_TYPE: 1743 if (wlan_serialization_match_cmd_type( 1744 nnode, cmd_type, node_type)) 1745 node_found = 1; 1746 break; 1747 case WLAN_SER_MATCH_CMD_ID: 1748 if (wlan_serialization_match_cmd_id_type( 1749 nnode, cmd, node_type)) 1750 node_found = 1; 1751 break; 1752 case WLAN_SER_MATCH_CMD_TYPE_VDEV: 1753 if (wlan_serialization_match_cmd_type( 1754 nnode, cmd_type, node_type) && 1755 wlan_serialization_match_cmd_vdev( 1756 nnode, vdev, node_type)) 1757 node_found = 1; 1758 break; 1759 case WLAN_SER_MATCH_CMD_ID_VDEV: 1760 if (wlan_serialization_match_cmd_id_type( 1761 nnode, cmd, node_type) && 1762 wlan_serialization_match_cmd_vdev( 1763 nnode, vdev, node_type)) 1764 node_found = 1; 1765 break; 1766 default: 1767 break; 1768 } 1769 1770 if (node_found) { 1771 cmd_node = nnode; 1772 break; 1773 } 1774 } 1775 error: 1776 return cmd_node; 1777 } 1778 1779 QDF_STATUS 1780 wlan_serialization_acquire_lock(qdf_spinlock_t *lock) 1781 { 1782 qdf_spin_lock_bh(lock); 1783 1784 return QDF_STATUS_SUCCESS; 1785 } 1786 1787 QDF_STATUS 1788 wlan_serialization_release_lock(qdf_spinlock_t *lock) 1789 { 1790 qdf_spin_unlock_bh(lock); 1791 1792 return QDF_STATUS_SUCCESS; 1793 } 1794 1795 QDF_STATUS 1796 wlan_serialization_create_lock(qdf_spinlock_t *lock) 1797 { 1798 qdf_spinlock_create(lock); 1799 1800 return QDF_STATUS_SUCCESS; 1801 } 1802 1803 QDF_STATUS 1804 wlan_serialization_destroy_lock(qdf_spinlock_t *lock) 1805 { 1806 qdf_spinlock_destroy(lock); 1807 1808 return QDF_STATUS_SUCCESS; 1809 } 1810 #endif 1811