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 #ifndef WLAN_SER_DEBUG 1008 void wlan_ser_update_cmd_history( 1009 struct wlan_serialization_pdev_queue *pdev_queue, 1010 struct wlan_serialization_command *cmd, 1011 enum ser_queue_reason ser_reason, 1012 bool add_remove, 1013 bool active_queue){ } 1014 #endif 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_vdev_timers( 1129 struct wlan_objmgr_vdev *vdev) 1130 { 1131 struct wlan_ser_psoc_obj *psoc_ser_obj; 1132 struct wlan_serialization_timer *ser_timer; 1133 QDF_STATUS status = QDF_STATUS_SUCCESS; 1134 uint32_t i = 0; 1135 1136 ser_enter(); 1137 psoc_ser_obj = wlan_serialization_get_psoc_obj( 1138 wlan_vdev_get_psoc(vdev)); 1139 1140 if (!psoc_ser_obj) { 1141 ser_err("Invalid psoc_ser_obj"); 1142 status = QDF_STATUS_E_FAILURE; 1143 goto error; 1144 } 1145 1146 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); 1147 1148 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 1149 ser_timer = &psoc_ser_obj->timers[i]; 1150 if (!ser_timer->cmd) 1151 continue; 1152 /* 1153 * Check if the timer is for the given vdev 1154 */ 1155 if (ser_timer->cmd->vdev != vdev) 1156 continue; 1157 1158 ser_debug("Stopping the timer for vdev id[%d]", 1159 wlan_vdev_get_id(vdev)); 1160 1161 status = wlan_serialization_stop_timer(ser_timer); 1162 if (QDF_STATUS_SUCCESS != status) { 1163 /* lets not break the loop but report error */ 1164 ser_err("some error in stopping timer"); 1165 } 1166 } 1167 1168 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); 1169 error: 1170 ser_exit(); 1171 return status; 1172 } 1173 1174 QDF_STATUS wlan_serialization_cleanup_all_timers( 1175 struct wlan_ser_psoc_obj *psoc_ser_obj) 1176 { 1177 struct wlan_serialization_timer *ser_timer; 1178 QDF_STATUS status = QDF_STATUS_SUCCESS; 1179 uint32_t i = 0; 1180 1181 ser_enter(); 1182 1183 if (!psoc_ser_obj) { 1184 ser_err("Invalid psoc_ser_obj"); 1185 status = QDF_STATUS_E_FAILURE; 1186 goto error; 1187 } 1188 1189 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock); 1190 1191 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 1192 ser_timer = &psoc_ser_obj->timers[i]; 1193 if (!ser_timer->cmd) 1194 continue; 1195 status = wlan_serialization_stop_timer(ser_timer); 1196 if (QDF_STATUS_SUCCESS != status) { 1197 /* lets not break the loop but report error */ 1198 ser_err("some error in stopping timer"); 1199 } 1200 } 1201 1202 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock); 1203 error: 1204 ser_exit(); 1205 return status; 1206 } 1207 1208 QDF_STATUS wlan_serialization_validate_cmdtype( 1209 enum wlan_serialization_cmd_type cmd_type) 1210 { 1211 if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) { 1212 ser_err("Invalid cmd or comp passed"); 1213 return QDF_STATUS_E_INVAL; 1214 } 1215 1216 return QDF_STATUS_SUCCESS; 1217 } 1218 1219 QDF_STATUS wlan_serialization_validate_cmd( 1220 enum wlan_umac_comp_id comp_id, 1221 enum wlan_serialization_cmd_type cmd_type) 1222 { 1223 QDF_STATUS status = QDF_STATUS_E_INVAL; 1224 1225 if (cmd_type < 0 || comp_id < 0 || 1226 cmd_type >= WLAN_SER_CMD_MAX || 1227 comp_id >= WLAN_UMAC_COMP_ID_MAX) { 1228 ser_err("Invalid cmd or comp passed"); 1229 goto error; 1230 } 1231 1232 status = QDF_STATUS_SUCCESS; 1233 error: 1234 return status; 1235 } 1236 1237 QDF_STATUS wlan_serialization_validate_cmd_list( 1238 struct wlan_serialization_command_list *cmd_list) 1239 { 1240 QDF_STATUS status = QDF_STATUS_E_INVAL; 1241 1242 if (!cmd_list->cmd.cmd_cb) { 1243 ser_err("no cmd_cb for cmd type:%d, id: %d", 1244 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); 1245 QDF_ASSERT(0); 1246 goto error; 1247 } 1248 1249 if (!cmd_list->cmd.vdev) { 1250 ser_err("invalid cmd.vdev"); 1251 goto error; 1252 } 1253 1254 status = QDF_STATUS_SUCCESS; 1255 1256 error: 1257 return status; 1258 } 1259 1260 static void wlan_serialization_release_pdev_list_cmds( 1261 struct wlan_serialization_pdev_queue *pdev_queue) 1262 { 1263 qdf_list_node_t *node = NULL; 1264 1265 while (!wlan_serialization_list_empty(&pdev_queue->active_list)) { 1266 wlan_serialization_remove_front( 1267 &pdev_queue->active_list, &node); 1268 wlan_serialization_insert_back( 1269 &pdev_queue->cmd_pool_list, node); 1270 } 1271 1272 while (!wlan_serialization_list_empty(&pdev_queue->pending_list)) { 1273 wlan_serialization_remove_front( 1274 &pdev_queue->pending_list, &node); 1275 wlan_serialization_insert_back( 1276 &pdev_queue->cmd_pool_list, node); 1277 } 1278 1279 } 1280 1281 static void wlan_serialization_release_vdev_list_cmds(qdf_list_t *list) 1282 { 1283 qdf_list_node_t *node = NULL; 1284 1285 1286 while (!wlan_serialization_list_empty(list)) 1287 wlan_serialization_remove_front(list, &node); 1288 1289 } 1290 1291 void wlan_serialization_destroy_pdev_list( 1292 struct wlan_serialization_pdev_queue *pdev_queue) 1293 { 1294 1295 wlan_serialization_release_pdev_list_cmds(pdev_queue); 1296 qdf_list_destroy(&pdev_queue->pending_list); 1297 qdf_list_destroy(&pdev_queue->active_list); 1298 1299 } 1300 1301 void wlan_serialization_destroy_vdev_list(qdf_list_t *list) 1302 { 1303 ser_enter(); 1304 1305 wlan_serialization_release_vdev_list_cmds(list); 1306 qdf_list_destroy(list); 1307 1308 ser_exit(); 1309 } 1310 1311 struct wlan_ser_psoc_obj *wlan_serialization_get_psoc_obj( 1312 struct wlan_objmgr_psoc *psoc) 1313 { 1314 struct wlan_ser_psoc_obj *ser_soc_obj; 1315 1316 ser_soc_obj = 1317 wlan_objmgr_psoc_get_comp_private_obj( 1318 psoc, WLAN_UMAC_COMP_SERIALIZATION); 1319 1320 return ser_soc_obj; 1321 } 1322 1323 struct wlan_ser_pdev_obj *wlan_serialization_get_pdev_obj( 1324 struct wlan_objmgr_pdev *pdev) 1325 { 1326 struct wlan_ser_pdev_obj *obj; 1327 1328 obj = wlan_objmgr_pdev_get_comp_private_obj( 1329 pdev, WLAN_UMAC_COMP_SERIALIZATION); 1330 1331 return obj; 1332 } 1333 1334 struct wlan_ser_vdev_obj *wlan_serialization_get_vdev_obj( 1335 struct wlan_objmgr_vdev *vdev) 1336 { 1337 struct wlan_ser_vdev_obj *obj; 1338 1339 obj = wlan_objmgr_vdev_get_comp_private_obj( 1340 vdev, WLAN_UMAC_COMP_SERIALIZATION); 1341 1342 return obj; 1343 } 1344 1345 bool wlan_serialization_is_cmd_in_vdev_list( 1346 struct wlan_objmgr_vdev *vdev, 1347 qdf_list_t *queue, 1348 enum wlan_serialization_node node_type) 1349 { 1350 qdf_list_node_t *node = NULL; 1351 bool cmd_found = false; 1352 1353 node = wlan_serialization_find_cmd( 1354 queue, WLAN_SER_MATCH_VDEV, 1355 NULL, 0, NULL, vdev, node_type); 1356 1357 if (node) 1358 cmd_found = true; 1359 1360 return cmd_found; 1361 } 1362 1363 bool wlan_serialization_is_cmd_in_pdev_list( 1364 struct wlan_objmgr_pdev *pdev, 1365 qdf_list_t *queue) 1366 { 1367 qdf_list_node_t *node = NULL; 1368 bool cmd_found = false; 1369 1370 node = wlan_serialization_find_cmd( 1371 queue, WLAN_SER_MATCH_PDEV, 1372 NULL, 0, pdev, NULL, WLAN_SER_PDEV_NODE); 1373 1374 if (node) 1375 cmd_found = true; 1376 1377 return cmd_found; 1378 } 1379 1380 enum wlan_serialization_cmd_status 1381 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active, 1382 bool cmd_in_pending) 1383 { 1384 enum wlan_serialization_cmd_status status; 1385 1386 if (cmd_in_active && cmd_in_pending) 1387 status = WLAN_SER_CMDS_IN_ALL_LISTS; 1388 else if (cmd_in_active) 1389 status = WLAN_SER_CMD_IN_ACTIVE_LIST; 1390 else if (cmd_in_pending) 1391 status = WLAN_SER_CMD_IN_PENDING_LIST; 1392 else 1393 status = WLAN_SER_CMD_NOT_FOUND; 1394 1395 return status; 1396 } 1397 1398 bool 1399 wlan_serialization_is_cmd_present_in_given_queue( 1400 qdf_list_t *queue, 1401 struct wlan_serialization_command *cmd, 1402 enum wlan_serialization_node node_type) 1403 { 1404 qdf_list_node_t *node = NULL; 1405 bool found = false; 1406 1407 node = wlan_serialization_find_cmd( 1408 queue, WLAN_SER_MATCH_CMD_ID_VDEV, 1409 cmd, 0, NULL, cmd->vdev, node_type); 1410 1411 if (node) 1412 found = true; 1413 1414 return found; 1415 } 1416 1417 /** 1418 * wlan_serialization_remove_cmd_from_queue() - to remove command from 1419 * given queue 1420 * @queue: queue from which command needs to be removed 1421 * @cmd: command to match in the queue 1422 * @ser_pdev_obj: pointer to private pdev serialization object 1423 * 1424 * This API takes the queue, it matches the provided command from this queue 1425 * and removes it. Before removing the command, it will notify the caller 1426 * that if it needs to remove any memory allocated by caller. 1427 * 1428 * Return: none 1429 */ 1430 QDF_STATUS 1431 wlan_serialization_remove_cmd_from_queue( 1432 qdf_list_t *queue, 1433 struct wlan_serialization_command *cmd, 1434 struct wlan_serialization_command_list **pcmd_list, 1435 struct wlan_ser_pdev_obj *ser_pdev_obj, 1436 enum wlan_serialization_node node_type) 1437 { 1438 struct wlan_serialization_command_list *cmd_list; 1439 qdf_list_node_t *node = NULL; 1440 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1441 1442 if (!cmd) 1443 goto error; 1444 1445 if (!queue || wlan_serialization_list_empty(queue)) { 1446 ser_err("Empty queue"); 1447 goto error; 1448 } 1449 1450 node = wlan_serialization_find_cmd(queue, WLAN_SER_MATCH_CMD_ID_VDEV, 1451 cmd, 0, NULL, cmd->vdev, node_type); 1452 1453 if (!node) 1454 goto error; 1455 1456 if (node_type == WLAN_SER_PDEV_NODE) 1457 cmd_list = 1458 qdf_container_of(node, 1459 struct wlan_serialization_command_list, 1460 pdev_node); 1461 else 1462 cmd_list = 1463 qdf_container_of(node, 1464 struct wlan_serialization_command_list, 1465 vdev_node); 1466 1467 ser_debug("Matching command found for removal from queue"); 1468 ser_debug("remove cmd: type[%d] id[%d] prio[%d] blocking[%d]", 1469 cmd_list->cmd.cmd_type, 1470 cmd_list->cmd.cmd_id, 1471 cmd_list->cmd.is_high_priority, 1472 cmd_list->cmd.is_blocking); 1473 1474 if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION, 1475 &cmd_list->cmd_in_use)) { 1476 qdf_atomic_set_bit(CMD_ACTIVE_MARKED_FOR_REMOVAL, 1477 &cmd_list->cmd_in_use); 1478 status = QDF_STATUS_E_PENDING; 1479 goto error; 1480 } 1481 1482 status = wlan_serialization_remove_node(queue, node); 1483 1484 if (QDF_STATUS_SUCCESS != status) 1485 ser_err("Fail to add to free pool type[%d]", 1486 cmd->cmd_type); 1487 1488 *pcmd_list = cmd_list; 1489 1490 error: 1491 return status; 1492 } 1493 1494 enum wlan_serialization_status 1495 wlan_serialization_add_cmd_to_queue( 1496 qdf_list_t *queue, 1497 struct wlan_serialization_command_list *cmd_list, 1498 struct wlan_ser_pdev_obj *ser_pdev_obj, 1499 uint8_t is_cmd_for_active_queue, 1500 enum wlan_serialization_node node_type) 1501 { 1502 enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 1503 QDF_STATUS qdf_status; 1504 qdf_list_node_t *node; 1505 1506 if (!cmd_list || !queue || !ser_pdev_obj) { 1507 ser_err("Input arguments are not valid"); 1508 goto error; 1509 } 1510 1511 if (node_type == WLAN_SER_PDEV_NODE) { 1512 node = &cmd_list->pdev_node; 1513 ser_debug("pdev_queue: %pK", queue); 1514 } else { 1515 node = &cmd_list->vdev_node; 1516 ser_debug("vdev_queue: %pK", queue); 1517 } 1518 1519 ser_debug("add cmd: type[%d] id[%d] high_priority[%d] blocking[%d]", 1520 cmd_list->cmd.cmd_type, 1521 cmd_list->cmd.cmd_id, 1522 cmd_list->cmd.is_high_priority, 1523 cmd_list->cmd.is_blocking); 1524 1525 if (qdf_list_size(queue) == qdf_list_max_size(queue)) { 1526 status = WLAN_SER_CMD_DENIED_LIST_FULL; 1527 goto error; 1528 } 1529 1530 if (cmd_list->cmd.is_high_priority) 1531 qdf_status = wlan_serialization_insert_front(queue, node); 1532 else 1533 qdf_status = wlan_serialization_insert_back(queue, node); 1534 1535 if (QDF_IS_STATUS_ERROR(qdf_status)) 1536 goto error; 1537 1538 ser_debug("adding cmd to node: %pK", node); 1539 1540 if (is_cmd_for_active_queue) 1541 status = WLAN_SER_CMD_ACTIVE; 1542 else 1543 status = WLAN_SER_CMD_PENDING; 1544 1545 error: 1546 return status; 1547 } 1548 1549 bool wlan_serialization_list_empty(qdf_list_t *queue) 1550 { 1551 bool is_empty; 1552 1553 if (qdf_list_empty(queue)) 1554 is_empty = true; 1555 else 1556 is_empty = false; 1557 1558 return is_empty; 1559 } 1560 1561 uint32_t wlan_serialization_list_size(qdf_list_t *queue) 1562 { 1563 uint32_t size; 1564 1565 size = qdf_list_size(queue); 1566 1567 return size; 1568 } 1569 1570 QDF_STATUS wlan_serialization_remove_front(qdf_list_t *list, 1571 qdf_list_node_t **node) 1572 { 1573 QDF_STATUS status; 1574 1575 if (wlan_serialization_list_empty(list)) { 1576 ser_err("The list is empty"); 1577 status = QDF_STATUS_E_EMPTY; 1578 goto error; 1579 } 1580 1581 status = qdf_list_remove_front(list, node); 1582 error: 1583 return status; 1584 } 1585 1586 QDF_STATUS wlan_serialization_remove_node(qdf_list_t *list, 1587 qdf_list_node_t *node) 1588 { 1589 QDF_STATUS status; 1590 1591 if (wlan_serialization_list_empty(list)) { 1592 ser_err("The list is empty"); 1593 status = QDF_STATUS_E_EMPTY; 1594 goto error; 1595 } 1596 status = qdf_list_remove_node(list, node); 1597 1598 error: 1599 return status; 1600 } 1601 1602 QDF_STATUS wlan_serialization_insert_front(qdf_list_t *list, 1603 qdf_list_node_t *node) 1604 { 1605 QDF_STATUS status; 1606 1607 status = qdf_list_insert_front(list, node); 1608 1609 return status; 1610 } 1611 1612 QDF_STATUS wlan_serialization_insert_back(qdf_list_t *list, 1613 qdf_list_node_t *node) 1614 { 1615 QDF_STATUS status; 1616 1617 status = qdf_list_insert_back(list, node); 1618 1619 return status; 1620 } 1621 1622 QDF_STATUS wlan_serialization_peek_front(qdf_list_t *list, 1623 qdf_list_node_t **node) 1624 { 1625 QDF_STATUS status; 1626 1627 status = qdf_list_peek_front(list, node); 1628 1629 return status; 1630 } 1631 1632 QDF_STATUS wlan_serialization_peek_next(qdf_list_t *list, 1633 qdf_list_node_t *node1, 1634 qdf_list_node_t **node2) 1635 { 1636 QDF_STATUS status; 1637 1638 status = qdf_list_peek_next(list, node1, node2); 1639 1640 return status; 1641 } 1642 1643 bool 1644 wlan_serialization_match_cmd_type(qdf_list_node_t *nnode, 1645 enum wlan_serialization_cmd_type cmd_type, 1646 enum wlan_serialization_node node_type) 1647 { 1648 struct wlan_serialization_command_list *cmd_list = NULL; 1649 bool match_found = true; 1650 1651 if (node_type == WLAN_SER_PDEV_NODE) 1652 cmd_list = 1653 qdf_container_of(nnode, 1654 struct wlan_serialization_command_list, 1655 pdev_node); 1656 else 1657 cmd_list = 1658 qdf_container_of(nnode, 1659 struct wlan_serialization_command_list, 1660 vdev_node); 1661 1662 if (cmd_list->cmd.cmd_type != cmd_type) 1663 match_found = false; 1664 1665 return match_found; 1666 } 1667 1668 bool 1669 wlan_serialization_match_cmd_id_type(qdf_list_node_t *nnode, 1670 struct wlan_serialization_command *cmd, 1671 enum wlan_serialization_node node_type) 1672 { 1673 struct wlan_serialization_command_list *cmd_list = NULL; 1674 bool match_found = true; 1675 1676 if (!cmd) { 1677 match_found = false; 1678 goto error; 1679 } 1680 1681 if (node_type == WLAN_SER_PDEV_NODE) 1682 cmd_list = 1683 qdf_container_of(nnode, 1684 struct wlan_serialization_command_list, 1685 pdev_node); 1686 else 1687 cmd_list = 1688 qdf_container_of(nnode, 1689 struct wlan_serialization_command_list, 1690 vdev_node); 1691 1692 if ((cmd_list->cmd.cmd_id != cmd->cmd_id) || 1693 (cmd_list->cmd.cmd_type != cmd->cmd_type)) { 1694 match_found = false; 1695 }; 1696 1697 error: 1698 return match_found; 1699 } 1700 1701 bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode, 1702 struct wlan_objmgr_vdev *vdev, 1703 enum wlan_serialization_node node_type) 1704 { 1705 struct wlan_serialization_command_list *cmd_list = NULL; 1706 bool match_found = false; 1707 1708 if (node_type == WLAN_SER_PDEV_NODE) 1709 cmd_list = 1710 qdf_container_of(nnode, 1711 struct wlan_serialization_command_list, 1712 pdev_node); 1713 else 1714 cmd_list = 1715 qdf_container_of(nnode, 1716 struct wlan_serialization_command_list, 1717 vdev_node); 1718 1719 if (cmd_list->cmd.vdev == vdev) 1720 match_found = true; 1721 1722 ser_debug("matching cmd found(vdev:%pK): %d", vdev, match_found); 1723 return match_found; 1724 } 1725 1726 bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode, 1727 struct wlan_objmgr_pdev *pdev, 1728 enum wlan_serialization_node node_type) 1729 { 1730 struct wlan_serialization_command_list *cmd_list = NULL; 1731 bool match_found = false; 1732 struct wlan_objmgr_pdev *node_pdev = NULL; 1733 1734 if (node_type == WLAN_SER_PDEV_NODE) 1735 cmd_list = 1736 qdf_container_of(nnode, 1737 struct wlan_serialization_command_list, 1738 pdev_node); 1739 else 1740 cmd_list = 1741 qdf_container_of(nnode, 1742 struct wlan_serialization_command_list, 1743 vdev_node); 1744 1745 node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev); 1746 if (node_pdev == pdev) 1747 match_found = true; 1748 1749 return match_found; 1750 } 1751 1752 qdf_list_node_t * 1753 wlan_serialization_find_cmd(qdf_list_t *queue, 1754 enum wlan_serialization_match_type match_type, 1755 struct wlan_serialization_command *cmd, 1756 enum wlan_serialization_cmd_type cmd_type, 1757 struct wlan_objmgr_pdev *pdev, 1758 struct wlan_objmgr_vdev *vdev, 1759 enum wlan_serialization_node node_type) 1760 { 1761 qdf_list_node_t *cmd_node = NULL; 1762 uint32_t queuelen; 1763 qdf_list_node_t *nnode = NULL; 1764 QDF_STATUS status; 1765 bool node_found = 0; 1766 1767 queuelen = wlan_serialization_list_size(queue); 1768 1769 if (!queuelen) { 1770 ser_debug("queue empty"); 1771 goto error; 1772 } 1773 1774 while (queuelen--) { 1775 status = wlan_serialization_get_cmd_from_queue(queue, &nnode); 1776 if (status != QDF_STATUS_SUCCESS) 1777 break; 1778 1779 switch (match_type) { 1780 case WLAN_SER_MATCH_PDEV: 1781 if (wlan_serialization_match_cmd_pdev( 1782 nnode, pdev, WLAN_SER_PDEV_NODE)) 1783 node_found = 1; 1784 break; 1785 case WLAN_SER_MATCH_VDEV: 1786 if (wlan_serialization_match_cmd_vdev( 1787 nnode, vdev, node_type)) 1788 node_found = 1; 1789 break; 1790 case WLAN_SER_MATCH_CMD_TYPE: 1791 if (wlan_serialization_match_cmd_type( 1792 nnode, cmd_type, node_type)) 1793 node_found = 1; 1794 break; 1795 case WLAN_SER_MATCH_CMD_ID: 1796 if (wlan_serialization_match_cmd_id_type( 1797 nnode, cmd, node_type)) 1798 node_found = 1; 1799 break; 1800 case WLAN_SER_MATCH_CMD_TYPE_VDEV: 1801 if (wlan_serialization_match_cmd_type( 1802 nnode, cmd_type, node_type) && 1803 wlan_serialization_match_cmd_vdev( 1804 nnode, vdev, node_type)) 1805 node_found = 1; 1806 break; 1807 case WLAN_SER_MATCH_CMD_ID_VDEV: 1808 if (wlan_serialization_match_cmd_id_type( 1809 nnode, cmd, node_type) && 1810 wlan_serialization_match_cmd_vdev( 1811 nnode, vdev, node_type)) 1812 node_found = 1; 1813 break; 1814 default: 1815 break; 1816 } 1817 1818 if (node_found) { 1819 cmd_node = nnode; 1820 break; 1821 } 1822 } 1823 error: 1824 return cmd_node; 1825 } 1826 1827 QDF_STATUS 1828 wlan_serialization_acquire_lock(qdf_spinlock_t *lock) 1829 { 1830 qdf_spin_lock_bh(lock); 1831 1832 return QDF_STATUS_SUCCESS; 1833 } 1834 1835 QDF_STATUS 1836 wlan_serialization_release_lock(qdf_spinlock_t *lock) 1837 { 1838 qdf_spin_unlock_bh(lock); 1839 1840 return QDF_STATUS_SUCCESS; 1841 } 1842 1843 QDF_STATUS 1844 wlan_serialization_create_lock(qdf_spinlock_t *lock) 1845 { 1846 qdf_spinlock_create(lock); 1847 1848 return QDF_STATUS_SUCCESS; 1849 } 1850 1851 QDF_STATUS 1852 wlan_serialization_destroy_lock(qdf_spinlock_t *lock) 1853 { 1854 qdf_spinlock_destroy(lock); 1855 1856 return QDF_STATUS_SUCCESS; 1857 } 1858 #endif 1859