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