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 #include "wlan_serialization_utils_i.h" 24 #include "wlan_serialization_main_i.h" 25 #include "wlan_serialization_api.h" 26 #include "wlan_objmgr_vdev_obj.h" 27 #include "wlan_objmgr_pdev_obj.h" 28 #include "qdf_mc_timer.h" 29 #include "wlan_utility.h" 30 31 QDF_STATUS 32 wlan_serialization_put_back_to_global_list(qdf_list_t *queue, 33 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 34 struct wlan_serialization_command_list *cmd_list) 35 { 36 QDF_STATUS status; 37 uint32_t cmd_id, cmd_type; 38 39 if (!queue || !ser_pdev_obj || !cmd_list) { 40 serialization_err("input parameters are invalid"); 41 return QDF_STATUS_E_FAILURE; 42 } 43 /* 44 * if the command is already removed in other context, 45 * then it will be marked as inactive with the same 46 * below code. So, test before proceeding. 47 */ 48 if (!qdf_atomic_test_and_clear_bit(CMD_IS_ACTIVE, 49 &cmd_list->cmd_in_use)) { 50 serialization_debug("CMD is not active or being used"); 51 return QDF_STATUS_SUCCESS; 52 } 53 status = wlan_serialization_remove_node(queue, &cmd_list->node, 54 ser_pdev_obj); 55 if (QDF_STATUS_SUCCESS != status) { 56 serialization_err("can't remove cmd from queue"); 57 /* assert to catch any leaks */ 58 QDF_ASSERT(0); 59 return status; 60 } 61 cmd_id = cmd_list->cmd.cmd_id; 62 cmd_type = cmd_list->cmd.cmd_type; 63 qdf_mem_zero(&cmd_list->cmd, sizeof(struct wlan_serialization_command)); 64 status = wlan_serialization_insert_back( 65 &ser_pdev_obj->global_cmd_pool_list, 66 &cmd_list->node, ser_pdev_obj); 67 qdf_atomic_clear_bit(CMD_MARKED_FOR_DELETE, &cmd_list->cmd_in_use); 68 if (QDF_STATUS_SUCCESS != status) { 69 serialization_err("can't put command back to global pool"); 70 QDF_ASSERT(0); 71 } 72 serialization_debug("cmd_id-%d, cmd_type-%d", cmd_id, cmd_type); 73 74 return status; 75 } 76 77 struct wlan_objmgr_pdev* 78 wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd) 79 { 80 struct wlan_objmgr_pdev *pdev = NULL; 81 82 if (!cmd) { 83 serialization_err("invalid cmd"); 84 return pdev; 85 } 86 if (!cmd->vdev) { 87 serialization_err("invalid cmd->vdev"); 88 return pdev; 89 } 90 pdev = wlan_vdev_get_pdev(cmd->vdev); 91 92 return pdev; 93 } 94 95 QDF_STATUS wlan_serialization_get_cmd_from_queue(qdf_list_t *queue, 96 qdf_list_node_t **nnode, 97 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 98 { 99 QDF_STATUS status; 100 qdf_list_node_t *pnode; 101 102 if (!queue || !ser_pdev_obj) { 103 serialization_err("input parameters are invalid"); 104 return QDF_STATUS_E_FAILURE; 105 } 106 107 pnode = *nnode; 108 if (!pnode) 109 status = wlan_serialization_peek_front(queue, nnode, 110 ser_pdev_obj); 111 else 112 status = wlan_serialization_peek_next(queue, pnode, nnode, 113 ser_pdev_obj); 114 115 if (status != QDF_STATUS_SUCCESS) { 116 serialization_err("can't get next node from queue"); 117 } 118 119 return status; 120 } 121 122 /** 123 * wlan_serialization_timer_destroy() - destroys the timer 124 * @ser_timer: pointer to particular timer 125 * 126 * This API destroys the memory allocated by timer and assigns cmd member of 127 * that timer structure to NULL 128 * 129 * Return: QDF_STATUS 130 */ 131 static QDF_STATUS wlan_serialization_timer_destroy( 132 struct wlan_serialization_timer *ser_timer) 133 { 134 QDF_STATUS status = QDF_STATUS_E_FAILURE; 135 136 if (!ser_timer || !ser_timer->cmd) { 137 serialization_debug("Invalid ser_timer"); 138 return status; 139 } 140 status = qdf_mc_timer_destroy(&ser_timer->timer); 141 if (!QDF_IS_STATUS_SUCCESS(status)) { 142 serialization_err("Failed to destroy timer for cmd_id[%d]", 143 ser_timer->cmd->cmd_id); 144 QDF_ASSERT(0); 145 return status; 146 } 147 ser_timer->cmd = NULL; 148 149 return status; 150 } 151 152 /** 153 * wlan_serialization_generic_timer_callback() - timer callback when timer fire 154 * @arg: argument that timer passes to this callback 155 * 156 * All the timers in serialization module calls this callback when they fire, 157 * and this API in turn calls command specific timeout callback and remove 158 * timed-out command from active queue and move any pending command to active 159 * queue of same cmd_type. 160 * 161 * Return: none 162 */ 163 static void wlan_serialization_generic_timer_callback(void *arg) 164 { 165 struct wlan_serialization_timer *timer = arg; 166 struct wlan_serialization_command *cmd = timer->cmd; 167 168 if (!cmd) { 169 serialization_err("command not found"); 170 QDF_ASSERT(0); 171 return; 172 } 173 174 serialization_err("active cmd timeout for cmd_type[%d] vdev[%pK]", 175 cmd->cmd_type, cmd->vdev); 176 if (cmd->cmd_cb) 177 cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT); 178 179 if (cmd->cmd_type >= WLAN_SER_CMD_NONSCAN) 180 QDF_BUG(0); 181 /* 182 * dequeue cmd API will cleanup and destroy the timer. If it fails to 183 * dequeue command then we have to destroy the timer. It will also call 184 * cmd callback with WLAN_SER_CB_RELEASE_MEM_CMD to free the memory. 185 */ 186 if (WLAN_SER_CMD_NOT_FOUND == wlan_serialization_dequeue_cmd(cmd, true)) 187 wlan_serialization_timer_destroy(timer); 188 if (cmd->cmd_cb) 189 cmd->cmd_cb(cmd, WLAN_SER_CB_RELEASE_MEM_CMD); 190 } 191 192 /** 193 * wlan_serialization_stop_timer() - to stop particular timer 194 * @ser_timer: pointer to serialization timer 195 * 196 * This API stops the particular timer 197 * 198 * Return: QDF_STATUS 199 */ 200 static QDF_STATUS 201 wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer) 202 { 203 QDF_TIMER_STATE state; 204 QDF_STATUS status; 205 206 state = qdf_mc_timer_get_current_state(&ser_timer->timer); 207 if (QDF_TIMER_STATE_RUNNING != state && 208 QDF_TIMER_STATE_STARTING != state) { 209 serialization_debug("nothing to stop"); 210 wlan_serialization_timer_destroy(ser_timer); 211 return QDF_STATUS_SUCCESS; 212 } 213 status = qdf_mc_timer_stop(&ser_timer->timer); 214 if (!QDF_IS_STATUS_SUCCESS(status)) { 215 serialization_err("Failed to stop timer"); 216 /* to catch the bug */ 217 QDF_ASSERT(0); 218 return status; 219 } 220 wlan_serialization_timer_destroy(ser_timer); 221 status = QDF_STATUS_SUCCESS; 222 223 return status; 224 } 225 226 QDF_STATUS wlan_serialization_cleanup_all_timers( 227 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj) 228 { 229 struct wlan_serialization_timer *ser_timer; 230 QDF_STATUS status = QDF_STATUS_SUCCESS; 231 uint32_t i = 0; 232 233 if (!psoc_ser_obj) { 234 serialization_err("Invalid psoc_ser_obj"); 235 return QDF_STATUS_E_FAILURE; 236 } 237 238 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 239 ser_timer = &psoc_ser_obj->timers[i]; 240 if (!ser_timer->cmd) 241 continue; 242 status = wlan_serialization_stop_timer(ser_timer); 243 if (QDF_STATUS_SUCCESS != status) { 244 /* lets not break the loop but report error */ 245 serialization_err("some error in stopping timer"); 246 } 247 } 248 249 return status; 250 } 251 252 QDF_STATUS 253 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc, 254 struct wlan_serialization_command *cmd) 255 { 256 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj; 257 struct wlan_serialization_timer *ser_timer; 258 QDF_STATUS status = QDF_STATUS_E_FAILURE; 259 int i = 0; 260 261 if (!psoc || !cmd) { 262 serialization_err("invalid param"); 263 return status; 264 } 265 266 if ((cmd->cmd_timeout_duration == 0) && 267 (wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc) 268 ))) { 269 serialization_err("[SCAN-EMULATION]: Not performing timer functions\n"); 270 return QDF_STATUS_SUCCESS; 271 } 272 273 psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc); 274 /* 275 * Here cmd_id and cmd_type are used to locate the timer being 276 * associated with command. For scan command, cmd_id is expected to 277 * be unique and For non-scan command, there should be only one active 278 * command per pdev 279 */ 280 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 281 ser_timer = &psoc_ser_obj->timers[i]; 282 if (!(ser_timer->cmd) || 283 (ser_timer->cmd->cmd_id != cmd->cmd_id) || 284 (ser_timer->cmd->cmd_type != cmd->cmd_type) || 285 (ser_timer->cmd->vdev != cmd->vdev)) 286 continue; 287 status = wlan_serialization_stop_timer(ser_timer); 288 if (QDF_STATUS_SUCCESS != status) { 289 serialization_err("Failed to stop timer for cmd_id[%d]", 290 cmd->cmd_id); 291 } 292 break; 293 } 294 295 if (QDF_STATUS_SUCCESS != status) { 296 serialization_err("can't find timer for cmd_type[%d]", 297 cmd->cmd_type); 298 } 299 return status; 300 } 301 302 QDF_STATUS 303 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc, 304 struct wlan_serialization_command *cmd) 305 { 306 QDF_STATUS status = QDF_STATUS_E_FAILURE; 307 struct wlan_serialization_psoc_priv_obj *psoc_ser_obj; 308 struct wlan_serialization_timer *ser_timer; 309 int i = 0; 310 311 if (!psoc || !cmd) { 312 serialization_err("invalid param"); 313 return status; 314 } 315 316 if ((cmd->cmd_timeout_duration == 0) && 317 (wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc) 318 ))) { 319 serialization_err("[SCAN-EMULATION]: Not performing timer functions\n"); 320 return QDF_STATUS_SUCCESS; 321 } 322 323 324 psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc); 325 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) { 326 /* Keep trying timer */ 327 ser_timer = &psoc_ser_obj->timers[i]; 328 if (ser_timer->cmd) 329 continue; 330 /* Remember timer is pointing to command */ 331 ser_timer->cmd = cmd; 332 if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_init(&ser_timer->timer, 333 QDF_TIMER_TYPE_SW, 334 wlan_serialization_generic_timer_callback, 335 ser_timer))) { 336 serialization_err("Failed to init timer cmdid [%d]", 337 cmd->cmd_id); 338 QDF_ASSERT(0); 339 continue; 340 } 341 if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_start(&ser_timer->timer, 342 cmd->cmd_timeout_duration))) { 343 serialization_err("Failed to start timer cmdid [%d]", 344 cmd->cmd_id); 345 wlan_serialization_timer_destroy(ser_timer); 346 QDF_ASSERT(0); 347 continue; 348 } 349 status = QDF_STATUS_SUCCESS; 350 break; 351 } 352 353 return status; 354 } 355 356 /** 357 * wlan_serialization_active_scan_cmd_count_handler() - count active scan cmds 358 * @psoc: pointer to soc strucutre 359 * @obj : pointer to pdev object 360 * @arg: pointer to argument 361 * 362 * This API will be called while iterating each pdev object and it will count 363 * number of scan commands present in that pdev object's active queue. count 364 * will be updated in *arg 365 * 366 * Return: none 367 */ 368 static void 369 wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc, 370 void *obj, void *arg) 371 { 372 struct wlan_objmgr_pdev *pdev = obj; 373 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 374 uint32_t *count = arg; 375 376 if (!pdev) { 377 serialization_err("invalid pdev"); 378 return; 379 } 380 381 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( 382 pdev, WLAN_UMAC_COMP_SERIALIZATION); 383 *count += wlan_serialization_list_size(&ser_pdev_obj->active_scan_list, 384 ser_pdev_obj); 385 } 386 387 /** 388 * wlan_serialization_is_active_scan_cmd_allowed() - find if scan cmd allowed 389 * @pdev: pointer to pdev object 390 * 391 * This API will be called to find out if active scan cmd is allowed. It has 392 * to iterate through all pdev to find out total number of active scan cmds. 393 * If total number of active scan cmds reach to allowed threshold then don't 394 * allow more scan cmd. 395 * 396 * Return: true or false 397 */ 398 static bool 399 wlan_serialization_is_active_scan_cmd_allowed(struct wlan_objmgr_pdev *pdev) 400 { 401 uint32_t count = 0; 402 struct wlan_objmgr_psoc *psoc; 403 404 if (!pdev) { 405 serialization_err("invalid pdev"); 406 return false; 407 } 408 409 psoc = wlan_pdev_get_psoc(pdev); 410 411 if (!psoc) { 412 serialization_err("invalid psoc"); 413 return false; 414 } 415 416 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 417 wlan_serialization_active_scan_cmd_count_handler, 418 &count, 1, WLAN_SERIALIZATION_ID); 419 if (count < ucfg_scan_get_max_active_scans(psoc)) { 420 serialization_debug("count is [%d]", count); 421 return true; 422 } 423 424 return false; 425 } 426 427 /** 428 * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed 429 * @pdev: pointer to pdev object 430 * 431 * This API will be called to find out if non scan cmd is allowed. 432 * 433 * Return: true or false 434 */ 435 static bool 436 wlan_serialization_is_active_nonscan_cmd_allowed(struct wlan_objmgr_pdev *pdev) 437 { 438 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 439 440 if (!pdev) { 441 serialization_err("invalid pdev"); 442 return false; 443 } 444 445 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( 446 pdev, WLAN_UMAC_COMP_SERIALIZATION); 447 448 if (!ser_pdev_obj) { 449 serialization_err("invalid ser_pdev_obj"); 450 return false; 451 } 452 453 if (wlan_serialization_list_empty(&ser_pdev_obj->active_list, 454 ser_pdev_obj)) 455 return true; 456 457 return false; 458 } 459 460 bool 461 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd) 462 { 463 struct wlan_objmgr_pdev *pdev; 464 465 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 466 if (!pdev) { 467 serialization_err("NULL pdev"); 468 return false; 469 } 470 471 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 472 return wlan_serialization_is_active_scan_cmd_allowed(pdev); 473 else 474 return wlan_serialization_is_active_nonscan_cmd_allowed(pdev); 475 } 476 477 QDF_STATUS wlan_serialization_validate_cmdtype( 478 enum wlan_serialization_cmd_type cmd_type) 479 { 480 serialization_debug("validate cmd_type:%d", cmd_type); 481 482 if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) { 483 serialization_err("Invalid cmd or comp passed"); 484 return QDF_STATUS_E_INVAL; 485 } 486 487 return QDF_STATUS_SUCCESS; 488 } 489 490 QDF_STATUS wlan_serialization_validate_cmd( 491 enum wlan_umac_comp_id comp_id, 492 enum wlan_serialization_cmd_type cmd_type) 493 { 494 serialization_debug("validate cmd_type:%d, comp_id:%d", 495 cmd_type, comp_id); 496 if (cmd_type < 0 || comp_id < 0 || 497 cmd_type >= WLAN_SER_CMD_MAX || 498 comp_id >= WLAN_UMAC_COMP_ID_MAX) { 499 serialization_err("Invalid cmd or comp passed"); 500 return QDF_STATUS_E_INVAL; 501 } 502 503 return QDF_STATUS_SUCCESS; 504 } 505 506 static void wlan_serialization_release_list_cmds( 507 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 508 qdf_list_t *list) 509 { 510 qdf_list_node_t *node = NULL; 511 512 while (!wlan_serialization_list_empty(list, ser_pdev_obj)) { 513 wlan_serialization_remove_front(list, &node, ser_pdev_obj); 514 wlan_serialization_insert_back( 515 &ser_pdev_obj->global_cmd_pool_list, 516 node, ser_pdev_obj); 517 } 518 519 return; 520 } 521 522 void wlan_serialization_destroy_list( 523 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, 524 qdf_list_t *list) 525 { 526 wlan_serialization_release_list_cmds(ser_pdev_obj, list); 527 qdf_list_destroy(list); 528 } 529 530 struct wlan_serialization_psoc_priv_obj *wlan_serialization_get_psoc_priv_obj( 531 struct wlan_objmgr_psoc *psoc) 532 { 533 struct wlan_serialization_psoc_priv_obj *ser_soc_obj; 534 ser_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 535 WLAN_UMAC_COMP_SERIALIZATION); 536 537 return ser_soc_obj; 538 } 539 540 struct wlan_serialization_pdev_priv_obj *wlan_serialization_get_pdev_priv_obj( 541 struct wlan_objmgr_pdev *pdev) 542 { 543 struct wlan_serialization_pdev_priv_obj *obj; 544 obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 545 WLAN_UMAC_COMP_SERIALIZATION); 546 547 return obj; 548 } 549 550 struct wlan_serialization_psoc_priv_obj * 551 wlan_serialization_get_psoc_obj(struct wlan_serialization_command *cmd) 552 { 553 struct wlan_serialization_psoc_priv_obj *ser_soc_obj = NULL; 554 struct wlan_objmgr_psoc *psoc; 555 556 if (!cmd->vdev) 557 return ser_soc_obj; 558 559 psoc = wlan_vdev_get_psoc(cmd->vdev); 560 ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc); 561 562 return ser_soc_obj; 563 } 564 565 bool wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev *vdev, 566 qdf_list_t *queue) 567 { 568 uint32_t queuelen; 569 qdf_list_node_t *nnode = NULL; 570 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 571 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 572 wlan_serialization_get_pdev_priv_obj(pdev); 573 QDF_STATUS status; 574 575 queuelen = wlan_serialization_list_size(queue, ser_pdev_obj); 576 if (!queuelen) { 577 serialization_debug("queue empty"); 578 return false; 579 } 580 581 while (queuelen--) { 582 status = wlan_serialization_get_cmd_from_queue(queue, &nnode, 583 ser_pdev_obj); 584 if (status != QDF_STATUS_SUCCESS) 585 break; 586 if (wlan_serialization_match_cmd_vdev(nnode, vdev)) 587 return true; 588 } 589 590 return false; 591 } 592 593 bool wlan_serialization_is_cmd_in_pdev_list( 594 struct wlan_objmgr_pdev *pdev, 595 qdf_list_t *queue) 596 { 597 uint32_t queuelen; 598 qdf_list_node_t *nnode = NULL; 599 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 600 wlan_serialization_get_pdev_priv_obj(pdev); 601 QDF_STATUS status; 602 603 queuelen = wlan_serialization_list_size(queue, ser_pdev_obj); 604 if (!queuelen) { 605 serialization_debug("queue empty"); 606 return false; 607 } 608 609 while (queuelen--) { 610 status = wlan_serialization_get_cmd_from_queue(queue, &nnode, 611 ser_pdev_obj); 612 if (status != QDF_STATUS_SUCCESS) 613 break; 614 if (wlan_serialization_match_cmd_pdev(nnode, pdev)) 615 return true; 616 } 617 618 return false; 619 } 620 621 enum wlan_serialization_cmd_status 622 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active, 623 bool cmd_in_pending) 624 { 625 if (cmd_in_active && cmd_in_pending) 626 return WLAN_SER_CMDS_IN_ALL_LISTS; 627 else if (cmd_in_active) 628 return WLAN_SER_CMD_IN_ACTIVE_LIST; 629 else if (cmd_in_pending) 630 return WLAN_SER_CMD_IN_PENDING_LIST; 631 else 632 return WLAN_SER_CMD_NOT_FOUND; 633 } 634 635 static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue, 636 struct wlan_serialization_command *cmd, 637 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 638 { 639 uint32_t qsize; 640 QDF_STATUS status; 641 struct wlan_serialization_command_list *cmd_list = NULL; 642 qdf_list_node_t *nnode = NULL, *pnode = NULL; 643 bool found = false; 644 645 qsize = wlan_serialization_list_size(queue, ser_pdev_obj); 646 while (qsize--) { 647 if (!cmd_list) 648 status = wlan_serialization_peek_front(queue, &nnode, 649 ser_pdev_obj); 650 else 651 status = wlan_serialization_peek_next(queue, pnode, 652 &nnode, 653 ser_pdev_obj); 654 655 if (status != QDF_STATUS_SUCCESS) 656 break; 657 658 pnode = nnode; 659 cmd_list = qdf_container_of(nnode, 660 struct wlan_serialization_command_list, node); 661 if (wlan_serialization_match_cmd_id_type(nnode, cmd, 662 ser_pdev_obj) && 663 wlan_serialization_match_cmd_vdev(nnode, cmd->vdev)) { 664 found = true; 665 break; 666 } 667 nnode = NULL; 668 } 669 670 return found; 671 } 672 673 bool wlan_serialization_is_cmd_present_queue( 674 struct wlan_serialization_command *cmd, 675 uint8_t is_active_queue) 676 { 677 qdf_list_t *queue; 678 struct wlan_objmgr_pdev *pdev; 679 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; 680 681 if (!cmd) { 682 serialization_err("invalid params"); 683 return false; 684 } 685 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 686 if (!pdev) { 687 serialization_err("invalid pdev"); 688 return false; 689 } 690 ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 691 WLAN_UMAC_COMP_SERIALIZATION); 692 if (!ser_pdev_obj) { 693 serialization_err("invalid ser_pdev_obj"); 694 return false; 695 } 696 if (!is_active_queue) { 697 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 698 queue = &ser_pdev_obj->pending_scan_list; 699 else 700 queue = &ser_pdev_obj->pending_list; 701 } else { 702 if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) 703 queue = &ser_pdev_obj->active_scan_list; 704 else 705 queue = &ser_pdev_obj->active_list; 706 } 707 708 return wlan_serialization_is_cmd_present_in_given_queue(queue, cmd, 709 ser_pdev_obj); 710 } 711 712 bool wlan_serialization_list_empty( 713 qdf_list_t *queue, 714 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 715 { 716 bool is_empty; 717 718 wlan_serialization_acquire_lock(ser_pdev_obj); 719 if (qdf_list_empty(queue)) 720 is_empty = true; 721 else 722 is_empty = false; 723 wlan_serialization_release_lock(ser_pdev_obj); 724 725 return is_empty; 726 } 727 728 uint32_t wlan_serialization_list_size( 729 qdf_list_t *queue, 730 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 731 { 732 uint32_t size; 733 734 wlan_serialization_acquire_lock(ser_pdev_obj); 735 size = qdf_list_size(queue); 736 wlan_serialization_release_lock(ser_pdev_obj); 737 738 return size; 739 } 740 741 QDF_STATUS wlan_serialization_remove_front( 742 qdf_list_t *list, 743 qdf_list_node_t **node, 744 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 745 { 746 QDF_STATUS status; 747 748 wlan_serialization_acquire_lock(ser_pdev_obj); 749 status = qdf_list_remove_front(list, node); 750 wlan_serialization_release_lock(ser_pdev_obj); 751 752 return status; 753 } 754 755 QDF_STATUS wlan_serialization_remove_node( 756 qdf_list_t *list, 757 qdf_list_node_t *node, 758 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 759 { 760 QDF_STATUS status; 761 762 wlan_serialization_acquire_lock(ser_pdev_obj); 763 status = qdf_list_remove_node(list, node); 764 wlan_serialization_release_lock(ser_pdev_obj); 765 766 return status; 767 } 768 769 QDF_STATUS wlan_serialization_insert_front( 770 qdf_list_t *list, 771 qdf_list_node_t *node, 772 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 773 { 774 QDF_STATUS status; 775 776 wlan_serialization_acquire_lock(ser_pdev_obj); 777 status = qdf_list_insert_front(list, node); 778 wlan_serialization_release_lock(ser_pdev_obj); 779 780 return status; 781 } 782 783 QDF_STATUS wlan_serialization_insert_back( 784 qdf_list_t *list, 785 qdf_list_node_t *node, 786 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 787 { 788 QDF_STATUS status; 789 790 wlan_serialization_acquire_lock(ser_pdev_obj); 791 status = qdf_list_insert_back(list, node); 792 wlan_serialization_release_lock(ser_pdev_obj); 793 794 return status; 795 } 796 797 QDF_STATUS wlan_serialization_peek_front( 798 qdf_list_t *list, 799 qdf_list_node_t **node, 800 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 801 { 802 QDF_STATUS status; 803 804 wlan_serialization_acquire_lock(ser_pdev_obj); 805 status = qdf_list_peek_front(list, node); 806 wlan_serialization_release_lock(ser_pdev_obj); 807 808 return status; 809 } 810 811 QDF_STATUS wlan_serialization_peek_next( 812 qdf_list_t *list, 813 qdf_list_node_t *node1, qdf_list_node_t **node2, 814 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 815 { 816 QDF_STATUS status; 817 818 wlan_serialization_acquire_lock(ser_pdev_obj); 819 status = qdf_list_peek_next(list, node1, node2); 820 wlan_serialization_release_lock(ser_pdev_obj); 821 822 return status; 823 } 824 825 bool wlan_serialization_match_cmd_scan_id( 826 qdf_list_node_t *nnode, 827 struct wlan_serialization_command **cmd, 828 uint16_t scan_id, struct wlan_objmgr_vdev *vdev, 829 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 830 { 831 struct wlan_serialization_command_list *cmd_list = NULL; 832 bool match_found = false; 833 834 wlan_serialization_acquire_lock(ser_pdev_obj); 835 cmd_list = qdf_container_of(nnode, 836 struct wlan_serialization_command_list, 837 node); 838 if ((cmd_list->cmd.cmd_id == scan_id) && 839 (cmd_list->cmd.vdev == vdev)) { 840 *cmd = &cmd_list->cmd; 841 match_found = true; 842 }; 843 wlan_serialization_release_lock(ser_pdev_obj); 844 845 return match_found; 846 } 847 848 bool wlan_serialization_match_cmd_id_type( 849 qdf_list_node_t *nnode, 850 struct wlan_serialization_command *cmd, 851 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) 852 { 853 struct wlan_serialization_command_list *cmd_list = NULL; 854 bool match_found = true; 855 856 if (!cmd) 857 return false; 858 wlan_serialization_acquire_lock(ser_pdev_obj); 859 cmd_list = qdf_container_of(nnode, 860 struct wlan_serialization_command_list, 861 node); 862 if ((cmd_list->cmd.cmd_id != cmd->cmd_id) || 863 (cmd_list->cmd.cmd_type != cmd->cmd_type)) { 864 match_found = false; 865 }; 866 wlan_serialization_release_lock(ser_pdev_obj); 867 868 return match_found; 869 } 870 871 bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode, 872 struct wlan_objmgr_vdev *vdev) 873 { 874 struct wlan_serialization_command_list *cmd_list = NULL; 875 bool match_found = false; 876 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 877 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 878 wlan_serialization_get_pdev_priv_obj(pdev); 879 880 wlan_serialization_acquire_lock(ser_pdev_obj); 881 cmd_list = qdf_container_of(nnode, 882 struct wlan_serialization_command_list, 883 node); 884 if (cmd_list->cmd.vdev == vdev) 885 match_found = true; 886 wlan_serialization_release_lock(ser_pdev_obj); 887 888 return match_found; 889 } 890 891 bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode, 892 struct wlan_objmgr_pdev *pdev) 893 { 894 struct wlan_serialization_command_list *cmd_list = NULL; 895 bool match_found = false; 896 struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = 897 wlan_serialization_get_pdev_priv_obj(pdev); 898 struct wlan_objmgr_pdev *node_pdev = NULL; 899 900 wlan_serialization_acquire_lock(ser_pdev_obj); 901 cmd_list = qdf_container_of(nnode, 902 struct wlan_serialization_command_list, 903 node); 904 node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev); 905 if (node_pdev == pdev) 906 match_found = true; 907 wlan_serialization_release_lock(ser_pdev_obj); 908 909 return match_found; 910 } 911 912 #ifdef WLAN_CMD_SERIALIZATION_LOCKING 913 QDF_STATUS 914 wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj) 915 { 916 if (!obj) { 917 serialization_err("invalid object"); 918 return QDF_STATUS_E_FAILURE; 919 } 920 qdf_spin_lock_bh(&obj->pdev_ser_list_lock); 921 922 return QDF_STATUS_SUCCESS; 923 } 924 925 QDF_STATUS 926 wlan_serialization_release_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_unlock_bh(&obj->pdev_ser_list_lock); 933 934 return QDF_STATUS_SUCCESS; 935 } 936 937 QDF_STATUS 938 wlan_serialization_create_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_spinlock_create(&obj->pdev_ser_list_lock); 945 946 return QDF_STATUS_SUCCESS; 947 } 948 949 QDF_STATUS 950 wlan_serialization_destroy_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_destroy(&obj->pdev_ser_list_lock); 957 958 return QDF_STATUS_SUCCESS; 959 } 960 #else 961 QDF_STATUS 962 wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj) 963 { 964 return QDF_STATUS_SUCCESS; 965 } 966 967 QDF_STATUS 968 wlan_serialization_release_lock(struct wlan_serialization_pdev_priv_obj *obj) 969 { 970 return QDF_STATUS_SUCCESS; 971 } 972 973 QDF_STATUS 974 wlan_serialization_create_lock(struct wlan_serialization_pdev_priv_obj *obj) 975 { 976 return QDF_STATUS_SUCCESS; 977 } 978 979 QDF_STATUS 980 wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj) 981 { 982 return QDF_STATUS_SUCCESS; 983 } 984 #endif 985