1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: wlan_serialization_api.c 22 * This file provides an interface for the external components 23 * to utilize the services provided by the serialization 24 * component. 25 */ 26 27 #include <wlan_objmgr_psoc_obj.h> 28 #include <wlan_objmgr_pdev_obj.h> 29 #include <wlan_objmgr_vdev_obj.h> 30 #include "wlan_serialization_main_i.h" 31 #include "wlan_serialization_utils_i.h" 32 #include "wlan_serialization_queue_i.h" 33 #include "wlan_serialization_scan_i.h" 34 #include "wlan_serialization_internal_i.h" 35 36 bool wlan_serialization_is_cmd_present_in_pending_queue( 37 struct wlan_objmgr_psoc *psoc, 38 struct wlan_serialization_command *cmd) 39 { 40 bool status = false; 41 struct wlan_objmgr_pdev *pdev; 42 struct wlan_ser_pdev_obj *ser_pdev_obj; 43 struct wlan_serialization_pdev_queue *pdev_queue; 44 45 if (!cmd) { 46 ser_err("invalid cmd"); 47 goto error; 48 } 49 50 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 51 if (!pdev) { 52 ser_err("invalid pdev"); 53 goto error; 54 } 55 56 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 57 if (!ser_pdev_obj) { 58 ser_err("invalid ser pdev obj"); 59 goto error; 60 } 61 62 pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, 63 cmd->cmd_type); 64 if (!pdev_queue) { 65 ser_err("pdev_queue is invalid"); 66 goto error; 67 } 68 69 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 70 71 status = wlan_serialization_is_cmd_present_queue(cmd, false); 72 73 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 74 error: 75 return status; 76 } 77 78 bool wlan_serialization_is_cmd_present_in_active_queue( 79 struct wlan_objmgr_psoc *psoc, 80 struct wlan_serialization_command *cmd) 81 { 82 bool status = false; 83 struct wlan_objmgr_pdev *pdev; 84 struct wlan_ser_pdev_obj *ser_pdev_obj; 85 struct wlan_serialization_pdev_queue *pdev_queue; 86 87 if (!cmd) { 88 ser_err("invalid cmd"); 89 goto error; 90 } 91 92 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 93 if (!pdev) { 94 ser_err("invalid pdev"); 95 goto error; 96 } 97 98 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 99 if (!ser_pdev_obj) { 100 ser_err("invalid ser pdev obj"); 101 goto error; 102 } 103 104 pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, 105 cmd->cmd_type); 106 if (!pdev_queue) { 107 ser_err("pdev_queue is invalid"); 108 goto error; 109 } 110 111 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 112 113 status = wlan_serialization_is_cmd_present_queue(cmd, true); 114 115 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 116 117 error: 118 return status; 119 } 120 121 QDF_STATUS 122 wlan_serialization_register_apply_rules_cb( 123 struct wlan_objmgr_psoc *psoc, 124 enum wlan_serialization_cmd_type cmd_type, 125 wlan_serialization_apply_rules_cb cb) 126 { 127 struct wlan_ser_psoc_obj *ser_soc_obj; 128 QDF_STATUS status; 129 130 status = wlan_serialization_validate_cmdtype(cmd_type); 131 if (QDF_IS_STATUS_ERROR(status)) { 132 ser_err("invalid cmd_type %d", cmd_type); 133 goto error; 134 } 135 136 ser_soc_obj = wlan_serialization_get_psoc_obj(psoc); 137 if (!ser_soc_obj) { 138 ser_err("invalid ser_soc_obj"); 139 status = QDF_STATUS_E_FAILURE; 140 goto error; 141 } 142 143 ser_soc_obj->apply_rules_cb[cmd_type] = cb; 144 status = QDF_STATUS_SUCCESS; 145 146 error: 147 return status; 148 } 149 150 QDF_STATUS 151 wlan_serialization_deregister_apply_rules_cb( 152 struct wlan_objmgr_psoc *psoc, 153 enum wlan_serialization_cmd_type cmd_type) 154 { 155 struct wlan_ser_psoc_obj *ser_soc_obj; 156 QDF_STATUS status; 157 158 status = wlan_serialization_validate_cmdtype(cmd_type); 159 if (QDF_IS_STATUS_ERROR(status)) { 160 ser_err("invalid cmd_type %d", cmd_type); 161 goto error; 162 } 163 ser_soc_obj = wlan_serialization_get_psoc_obj(psoc); 164 if (!ser_soc_obj) { 165 ser_err("invalid ser_soc_obj"); 166 status = QDF_STATUS_E_FAILURE; 167 goto error; 168 } 169 ser_soc_obj->apply_rules_cb[cmd_type] = NULL; 170 status = QDF_STATUS_SUCCESS; 171 172 error: 173 return status; 174 } 175 176 QDF_STATUS 177 wlan_serialization_register_comp_info_cb( 178 struct wlan_objmgr_psoc *psoc, 179 enum wlan_umac_comp_id comp_id, 180 enum wlan_serialization_cmd_type cmd_type, 181 wlan_serialization_comp_info_cb cb) 182 { 183 struct wlan_ser_psoc_obj *ser_soc_obj; 184 QDF_STATUS status; 185 186 status = wlan_serialization_validate_cmd(comp_id, cmd_type); 187 if (QDF_IS_STATUS_ERROR(status)) { 188 ser_err("invalid comp_id %d or cmd_type %d", 189 comp_id, cmd_type); 190 goto error; 191 } 192 ser_soc_obj = wlan_serialization_get_psoc_obj(psoc); 193 if (!ser_soc_obj) { 194 ser_err("invalid ser_soc_obj"); 195 status = QDF_STATUS_E_FAILURE; 196 goto error; 197 } 198 ser_soc_obj->comp_info_cb[cmd_type][comp_id] = cb; 199 status = QDF_STATUS_SUCCESS; 200 201 error: 202 return status; 203 } 204 205 QDF_STATUS 206 wlan_serialization_deregister_comp_info_cb(struct wlan_objmgr_psoc *psoc, 207 enum wlan_umac_comp_id comp_id, 208 enum wlan_serialization_cmd_type cmd_type) 209 { 210 struct wlan_ser_psoc_obj *ser_soc_obj; 211 QDF_STATUS status; 212 213 status = wlan_serialization_validate_cmd(comp_id, cmd_type); 214 if (QDF_IS_STATUS_ERROR(status)) { 215 ser_err("invalid comp_id %d or cmd_type %d", 216 comp_id, cmd_type); 217 goto error; 218 } 219 ser_soc_obj = wlan_serialization_get_psoc_obj(psoc); 220 if (!ser_soc_obj) { 221 ser_err("invalid ser_soc_obj"); 222 status = QDF_STATUS_E_FAILURE; 223 goto error; 224 } 225 ser_soc_obj->comp_info_cb[cmd_type][comp_id] = NULL; 226 status = QDF_STATUS_SUCCESS; 227 228 error: 229 return status; 230 } 231 232 enum wlan_serialization_cmd_status 233 wlan_serialization_non_scan_cmd_status( 234 struct wlan_objmgr_pdev *pdev, 235 enum wlan_serialization_cmd_type cmd_type) 236 { 237 bool cmd_in_active = 0; 238 bool cmd_in_pending = 0; 239 struct wlan_ser_pdev_obj *ser_pdev_obj = 240 wlan_serialization_get_pdev_obj(pdev); 241 enum wlan_serialization_cmd_status cmd_status = WLAN_SER_CMD_NOT_FOUND; 242 struct wlan_serialization_pdev_queue *pdev_q; 243 qdf_list_node_t *node = NULL; 244 qdf_list_t *queue = NULL; 245 246 pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 247 248 /* Look in the pdev non scan active queue */ 249 queue = &pdev_q->active_list; 250 251 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 252 253 node = wlan_serialization_find_cmd( 254 queue, WLAN_SER_MATCH_CMD_TYPE, 255 NULL, cmd_type, NULL, NULL, WLAN_SER_PDEV_NODE); 256 257 if (node) 258 cmd_in_active = true; 259 260 node = NULL; 261 262 /* Look in the pdev non scan pending queue */ 263 queue = &pdev_q->pending_list; 264 265 node = wlan_serialization_find_cmd( 266 queue, WLAN_SER_MATCH_CMD_TYPE, 267 NULL, cmd_type, NULL, NULL, WLAN_SER_PDEV_NODE); 268 269 if (node) 270 cmd_in_pending = true; 271 272 cmd_status = wlan_serialization_is_cmd_in_active_pending( 273 cmd_in_active, cmd_in_pending); 274 275 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 276 277 return cmd_status; 278 } 279 280 enum wlan_serialization_cmd_status 281 wlan_serialization_cancel_request( 282 struct wlan_serialization_queued_cmd_info *req) 283 { 284 QDF_STATUS status; 285 enum wlan_serialization_cmd_status cmd_status; 286 287 struct wlan_serialization_command cmd; 288 struct wlan_objmgr_pdev *pdev; 289 struct wlan_ser_pdev_obj *ser_pdev_obj; 290 struct wlan_serialization_pdev_queue *pdev_queue; 291 292 if (!req) { 293 ser_err("given request is empty"); 294 cmd_status = WLAN_SER_CMD_NOT_FOUND; 295 goto error; 296 } 297 298 status = wlan_serialization_validate_cmd(req->requestor, req->cmd_type); 299 if (QDF_IS_STATUS_ERROR(status)) { 300 ser_err("req is not valid"); 301 cmd_status = WLAN_SER_CMD_NOT_FOUND; 302 goto error; 303 } 304 305 cmd.cmd_type = req->cmd_type; 306 cmd.cmd_id = req->cmd_id; 307 cmd.source = req->requestor; 308 cmd.vdev = req->vdev; 309 310 ser_debug("Type %d id %d vdev %d source %d req type %d queue type %d", 311 cmd.cmd_type, cmd.cmd_id, 312 cmd.vdev ? wlan_vdev_get_id(cmd.vdev) : WLAN_INVALID_VDEV_ID, 313 cmd.source, req->req_type, req->queue_type); 314 pdev = wlan_serialization_get_pdev_from_cmd(&cmd); 315 if (!pdev) { 316 ser_err("pdev is invalid"); 317 cmd_status = WLAN_SER_CMD_NOT_FOUND; 318 goto error; 319 } 320 321 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 322 323 pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, 324 cmd.cmd_type); 325 326 if (!pdev_queue) { 327 ser_err("pdev_queue is invalid"); 328 cmd_status = WLAN_SER_CMD_NOT_FOUND; 329 goto error; 330 } 331 332 cmd_status = wlan_serialization_find_and_cancel_cmd( 333 &cmd, req->req_type, req->queue_type); 334 335 error: 336 337 return cmd_status; 338 } 339 340 void wlan_serialization_remove_cmd( 341 struct wlan_serialization_queued_cmd_info *cmd_info) 342 { 343 QDF_STATUS status; 344 enum wlan_serialization_cmd_status ser_status; 345 struct wlan_serialization_command cmd = {0}; 346 347 if (!cmd_info) { 348 ser_err("given request is empty"); 349 QDF_ASSERT(0); 350 return; 351 } 352 status = wlan_serialization_validate_cmd(cmd_info->requestor, 353 cmd_info->cmd_type); 354 if (QDF_IS_STATUS_ERROR(status)) { 355 ser_err("cmd type %d is not valid", cmd_info->cmd_type); 356 QDF_ASSERT(0); 357 return; 358 } 359 360 cmd.cmd_type = cmd_info->cmd_type; 361 cmd.cmd_id = cmd_info->cmd_id; 362 cmd.source = cmd_info->requestor; 363 cmd.vdev = cmd_info->vdev; 364 365 ser_status = wlan_serialization_dequeue_cmd( 366 &cmd, SER_REMOVE, true); 367 368 if (ser_status != WLAN_SER_CMD_IN_ACTIVE_LIST) { 369 if (ser_status != WLAN_SER_CMD_MARKED_FOR_ACTIVATION) 370 ser_debug("Can't dequeue requested id %d type %d requestor %d", 371 cmd.cmd_id, cmd.cmd_type, 372 cmd_info->requestor); 373 } 374 } 375 376 enum wlan_serialization_status 377 wlan_serialization_request(struct wlan_serialization_command *cmd) 378 { 379 QDF_STATUS status; 380 enum wlan_serialization_status serialization_status; 381 uint8_t comp_id; 382 struct wlan_ser_psoc_obj *ser_soc_obj; 383 union wlan_serialization_rules_info info; 384 struct wlan_objmgr_psoc *psoc; 385 386 serialization_status = WLAN_SER_CMD_DENIED_UNSPECIFIED; 387 388 if (!cmd) { 389 ser_err("serialization cmd is null"); 390 goto error; 391 } 392 status = wlan_serialization_validate_cmd(cmd->source, cmd->cmd_type); 393 if (QDF_IS_STATUS_ERROR(status)) 394 goto error; 395 396 psoc = wlan_serialization_get_psoc_from_cmd(cmd); 397 if (!psoc) { 398 ser_err("psoc _obj is invalid"); 399 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 400 } 401 ser_soc_obj = wlan_serialization_get_psoc_obj(psoc); 402 403 if (!ser_soc_obj) { 404 ser_err("ser_soc_obj is invalid"); 405 return WLAN_SER_CMD_DENIED_UNSPECIFIED; 406 } 407 408 /* 409 * Get Component Info callback by calling 410 * each registered module 411 */ 412 for (comp_id = 0; comp_id < WLAN_UMAC_COMP_ID_MAX; comp_id++) { 413 if (!ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id]) 414 continue; 415 ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id](cmd->vdev, 416 &info, cmd); 417 if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type]) 418 continue; 419 if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type](&info, comp_id)) 420 return WLAN_SER_CMD_DENIED_RULES_FAILED; 421 } 422 423 serialization_status = wlan_serialization_enqueue_cmd(cmd, SER_REQUEST); 424 425 error: 426 return serialization_status; 427 } 428 429 QDF_STATUS 430 wlan_serialization_update_timer(struct wlan_serialization_command *cmd) 431 { 432 QDF_STATUS status = QDF_STATUS_E_FAILURE; 433 struct wlan_objmgr_pdev *pdev; 434 struct wlan_objmgr_psoc *psoc; 435 436 if (!cmd) { 437 ser_err("NULL command"); 438 goto error; 439 } 440 441 pdev = wlan_serialization_get_pdev_from_cmd(cmd); 442 if (!pdev) { 443 ser_err("invalid pdev"); 444 goto error; 445 } 446 447 psoc = wlan_pdev_get_psoc(pdev); 448 if (!psoc) { 449 ser_err("invalid psoc"); 450 goto error; 451 } 452 453 status = wlan_serialization_find_and_update_timer(psoc, cmd); 454 455 error: 456 return status; 457 } 458 459 enum wlan_serialization_cmd_status 460 wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev) 461 { 462 bool cmd_in_active = 0, cmd_in_pending = 0; 463 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 464 struct wlan_ser_pdev_obj *ser_pdev_obj = 465 wlan_serialization_get_pdev_obj(pdev); 466 struct wlan_serialization_pdev_queue *pdev_q; 467 enum wlan_serialization_cmd_status status; 468 469 pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 470 471 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 472 473 cmd_in_active = 474 wlan_serialization_is_cmd_in_vdev_list( 475 vdev, &pdev_q->active_list, WLAN_SER_PDEV_NODE); 476 477 cmd_in_pending = 478 wlan_serialization_is_cmd_in_vdev_list( 479 vdev, &pdev_q->pending_list, WLAN_SER_PDEV_NODE); 480 481 status = wlan_serialization_is_cmd_in_active_pending( 482 cmd_in_active, cmd_in_pending); 483 484 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 485 486 return status; 487 } 488 489 enum wlan_serialization_cmd_status 490 wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev) 491 { 492 bool cmd_in_active, cmd_in_pending; 493 struct wlan_ser_pdev_obj *ser_pdev_obj = 494 wlan_serialization_get_pdev_obj(pdev); 495 struct wlan_serialization_pdev_queue *pdev_q; 496 enum wlan_serialization_cmd_status status; 497 498 pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 499 500 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 501 502 cmd_in_active = !qdf_list_empty(&pdev_q->active_list); 503 cmd_in_pending = !qdf_list_empty(&pdev_q->pending_list); 504 505 status = wlan_serialization_is_cmd_in_active_pending( 506 cmd_in_active, cmd_in_pending); 507 508 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 509 510 return status; 511 } 512 513 struct wlan_serialization_command* 514 wlan_serialization_get_scan_cmd_using_scan_id( 515 struct wlan_objmgr_psoc *psoc, 516 uint8_t vdev_id, uint16_t scan_id, 517 uint8_t is_scan_cmd_from_active_queue) 518 { 519 struct wlan_objmgr_vdev *vdev; 520 struct wlan_objmgr_pdev *pdev; 521 struct wlan_ser_pdev_obj *ser_pdev_obj; 522 struct wlan_serialization_command cmd = {0}; 523 struct wlan_serialization_command *pcmd = NULL; 524 struct wlan_serialization_command_list *cmd_list; 525 qdf_list_node_t *node = NULL; 526 qdf_list_t *queue; 527 struct wlan_serialization_pdev_queue *pdev_q; 528 529 if (!psoc) { 530 ser_err("invalid psoc"); 531 goto error; 532 } 533 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 534 WLAN_SERIALIZATION_ID); 535 if (!vdev) { 536 ser_err("invalid vdev"); 537 goto error; 538 } 539 540 pdev = wlan_vdev_get_pdev(vdev); 541 if (!pdev) { 542 ser_err("invalid pdev"); 543 goto release_vdev_ref; 544 } 545 546 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 547 if (!ser_pdev_obj) { 548 ser_err("invalid ser_pdev_obj"); 549 goto release_vdev_ref; 550 } 551 552 pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; 553 554 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 555 556 if (is_scan_cmd_from_active_queue) 557 queue = &pdev_q->active_list; 558 else 559 queue = &pdev_q->pending_list; 560 561 cmd.cmd_type = WLAN_SER_CMD_SCAN; 562 cmd.cmd_id = scan_id; 563 cmd.vdev = vdev; 564 565 node = wlan_serialization_find_cmd( 566 queue, WLAN_SER_MATCH_CMD_ID_VDEV, 567 &cmd, 0, NULL, vdev, WLAN_SER_PDEV_NODE); 568 569 if (node) { 570 cmd_list = qdf_container_of( 571 node, 572 struct wlan_serialization_command_list, 573 pdev_node); 574 575 pcmd = &cmd_list->cmd; 576 } 577 578 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 579 580 release_vdev_ref: 581 wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); 582 error: 583 return pcmd; 584 } 585 586 void *wlan_serialization_get_active_cmd( 587 struct wlan_objmgr_psoc *psoc, 588 uint8_t vdev_id, 589 enum wlan_serialization_cmd_type cmd_type) 590 { 591 struct wlan_objmgr_vdev *vdev; 592 struct wlan_objmgr_pdev *pdev; 593 struct wlan_ser_pdev_obj *ser_pdev_obj; 594 struct wlan_serialization_command_list *cmd_list = NULL; 595 void *umac_cmd = NULL; 596 qdf_list_node_t *node = NULL; 597 qdf_list_t *queue; 598 struct wlan_serialization_pdev_queue *pdev_q; 599 600 if (!psoc) { 601 ser_err("invalid psoc"); 602 goto error; 603 } 604 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 605 WLAN_SERIALIZATION_ID); 606 if (!vdev) { 607 ser_err("invalid vdev"); 608 goto error; 609 } 610 611 pdev = wlan_vdev_get_pdev(vdev); 612 if (!pdev) { 613 ser_err("invalid pdev"); 614 goto release_vdev_ref; 615 } 616 617 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 618 if (!ser_pdev_obj) { 619 ser_err("invalid ser_pdev_obj"); 620 goto release_vdev_ref; 621 } 622 623 pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type); 624 625 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 626 627 queue = &pdev_q->active_list; 628 629 node = wlan_serialization_find_cmd( 630 queue, WLAN_SER_MATCH_CMD_TYPE_VDEV, 631 NULL, cmd_type, NULL, vdev, WLAN_SER_PDEV_NODE); 632 633 if (node) { 634 cmd_list = qdf_container_of( 635 node, 636 struct wlan_serialization_command_list, 637 pdev_node); 638 639 umac_cmd = cmd_list->cmd.umac_cmd; 640 } 641 642 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 643 644 release_vdev_ref: 645 wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); 646 error: 647 648 return umac_cmd; 649 } 650 651 enum wlan_serialization_cmd_type 652 wlan_serialization_get_vdev_active_cmd_type(struct wlan_objmgr_vdev *vdev) 653 { 654 enum wlan_serialization_cmd_type cmd_type = WLAN_SER_CMD_MAX; 655 struct wlan_ser_pdev_obj *ser_pdev_obj; 656 struct wlan_ser_vdev_obj *ser_vdev_obj; 657 struct wlan_serialization_pdev_queue *pdev_queue; 658 struct wlan_serialization_vdev_queue *vdev_queue; 659 struct wlan_serialization_command_list *cmd_list = NULL; 660 qdf_list_node_t *node; 661 662 ser_pdev_obj = wlan_serialization_get_pdev_obj( 663 wlan_vdev_get_pdev(vdev)); 664 665 if (!ser_pdev_obj) { 666 ser_err("invalid ser_pdev_obj"); 667 goto error; 668 } 669 pdev_queue = wlan_serialization_get_pdev_queue_obj( 670 ser_pdev_obj, cmd_type); 671 672 ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev); 673 if (!ser_vdev_obj) { 674 ser_err("invalid ser_vdev_obj"); 675 goto error; 676 } 677 vdev_queue = wlan_serialization_get_vdev_queue_obj( 678 ser_vdev_obj, WLAN_SER_CMD_NONSCAN); 679 680 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 681 682 if (wlan_serialization_peek_front( 683 &vdev_queue->active_list, &node) == QDF_STATUS_SUCCESS) { 684 cmd_list = qdf_container_of( 685 node, 686 struct wlan_serialization_command_list, 687 vdev_node); 688 689 cmd_type = cmd_list->cmd.cmd_type; 690 } 691 692 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 693 694 error: 695 return cmd_type; 696 } 697 698 bool wlan_ser_is_vdev_queue_enabled(struct wlan_objmgr_vdev *vdev) 699 { 700 struct wlan_ser_vdev_obj *ser_vdev_obj; 701 struct wlan_serialization_vdev_queue *vdev_queue; 702 703 ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev); 704 if (!ser_vdev_obj) { 705 ser_err("invalid ser_vdev_obj"); 706 return false; 707 } 708 709 vdev_queue = wlan_serialization_get_vdev_queue_obj( 710 ser_vdev_obj, WLAN_SER_CMD_NONSCAN); 711 if (vdev_queue->queue_disable) 712 return false; 713 else 714 return true; 715 } 716 717 QDF_STATUS 718 wlan_ser_get_cmd_activation_status(struct wlan_objmgr_vdev *vdev) 719 { 720 struct wlan_ser_pdev_obj *ser_pdev_obj; 721 struct wlan_ser_vdev_obj *ser_vdev_obj; 722 struct wlan_serialization_pdev_queue *pdev_queue; 723 struct wlan_serialization_vdev_queue *vdev_queue; 724 struct wlan_serialization_command_list *cmd_list = NULL; 725 qdf_list_node_t *node; 726 QDF_STATUS status = QDF_STATUS_E_FAILURE; 727 728 ser_pdev_obj = wlan_serialization_get_pdev_obj( 729 wlan_vdev_get_pdev(vdev)); 730 731 if (!ser_pdev_obj) { 732 ser_err("invalid ser_pdev_obj"); 733 return QDF_STATUS_E_FAILURE; 734 } 735 736 pdev_queue = wlan_serialization_get_pdev_queue_obj( 737 ser_pdev_obj, WLAN_SER_CMD_NONSCAN); 738 739 ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev); 740 if (!ser_vdev_obj) { 741 ser_err("invalid ser_vdev_obj"); 742 return QDF_STATUS_E_FAILURE; 743 } 744 vdev_queue = wlan_serialization_get_vdev_queue_obj( 745 ser_vdev_obj, WLAN_SER_CMD_NONSCAN); 746 747 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); 748 749 if (wlan_serialization_peek_front( 750 &vdev_queue->active_list, &node) == QDF_STATUS_SUCCESS) { 751 cmd_list = qdf_container_of( 752 node, 753 struct wlan_serialization_command_list, 754 vdev_node); 755 756 if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION, 757 &cmd_list->cmd_in_use)) 758 status = QDF_STATUS_SUCCESS; 759 } 760 761 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); 762 763 return status; 764 } 765 766 QDF_STATUS 767 wlan_ser_validate_umac_cmd(struct wlan_objmgr_vdev *vdev, 768 enum wlan_serialization_cmd_type cmd_type, 769 wlan_ser_umac_cmd_cb umac_cmd_cb) 770 { 771 struct wlan_objmgr_pdev *pdev; 772 struct wlan_ser_pdev_obj *ser_pdev_obj; 773 struct wlan_serialization_command_list *cmd_list = NULL; 774 void *umac_cmd = NULL; 775 qdf_list_node_t *node = NULL; 776 qdf_list_t *queue; 777 struct wlan_serialization_pdev_queue *pdev_q; 778 QDF_STATUS status = QDF_STATUS_E_INVAL; 779 780 if (!vdev) { 781 ser_err("invalid vdev"); 782 return QDF_STATUS_E_INVAL; 783 } 784 785 pdev = wlan_vdev_get_pdev(vdev); 786 if (!pdev) { 787 ser_err("invalid pdev"); 788 return QDF_STATUS_E_INVAL; 789 } 790 791 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 792 if (!ser_pdev_obj) { 793 ser_err("invalid ser_pdev_obj"); 794 return QDF_STATUS_E_INVAL; 795 } 796 797 pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type); 798 799 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 800 801 queue = &pdev_q->active_list; 802 node = wlan_serialization_find_cmd( 803 queue, WLAN_SER_MATCH_CMD_TYPE_VDEV, 804 NULL, cmd_type, NULL, vdev, WLAN_SER_PDEV_NODE); 805 if (node) { 806 cmd_list = qdf_container_of( 807 node, 808 struct wlan_serialization_command_list, 809 pdev_node); 810 811 umac_cmd = cmd_list->cmd.umac_cmd; 812 status = umac_cmd_cb(umac_cmd); 813 } 814 815 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 816 817 return status; 818 } 819 820 void wlan_serialization_purge_all_pdev_cmd(struct wlan_objmgr_pdev *pdev) 821 { 822 struct wlan_ser_pdev_obj *ser_pdev_obj; 823 824 if (!pdev) { 825 ser_err("NULL pdev"); 826 return; 827 } 828 829 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 830 if (!ser_pdev_obj) { 831 ser_err("invalid ser_pdev_obj"); 832 return; 833 } 834 835 wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, NULL, NULL, 836 WLAN_SER_CMD_SCAN, false); 837 wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, NULL, NULL, 838 WLAN_SER_CMD_SCAN, true); 839 wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL, 840 WLAN_SER_CMD_NONSCAN, false, 841 WLAN_SER_CMD_ATTR_NONE); 842 wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL, 843 WLAN_SER_CMD_NONSCAN, true, 844 WLAN_SER_CMD_ATTR_NONE); 845 } 846 847 static inline 848 void wlan_ser_purge_pdev_cmd_cb(struct wlan_objmgr_psoc *psoc, 849 void *object, void *arg) 850 { 851 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object; 852 853 wlan_serialization_purge_all_pdev_cmd(pdev); 854 } 855 856 static inline enum scm_scan_status 857 wlan_get_scan_status_from_serialization_status(enum 858 wlan_serialization_cmd_status 859 status) 860 { 861 enum scm_scan_status scan_status; 862 863 switch (status) { 864 case WLAN_SER_CMD_IN_PENDING_LIST: 865 scan_status = SCAN_IS_PENDING; 866 break; 867 case WLAN_SER_CMD_IN_ACTIVE_LIST: 868 scan_status = SCAN_IS_ACTIVE; 869 break; 870 case WLAN_SER_CMDS_IN_ALL_LISTS: 871 scan_status = SCAN_IS_ACTIVE_AND_PENDING; 872 break; 873 case WLAN_SER_CMD_NOT_FOUND: 874 scan_status = SCAN_NOT_IN_PROGRESS; 875 break; 876 default: 877 scm_warn("invalid serialization status %d", status); 878 QDF_ASSERT(0); 879 scan_status = SCAN_NOT_IN_PROGRESS; 880 break; 881 } 882 883 return scan_status; 884 } 885 886 void wlan_serialization_purge_all_cmd(struct wlan_objmgr_psoc *psoc) 887 { 888 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 889 wlan_ser_purge_pdev_cmd_cb, NULL, 1, 890 WLAN_SERIALIZATION_ID); 891 } 892 893 void wlan_serialization_purge_all_pending_cmd_by_vdev_id( 894 struct wlan_objmgr_pdev *pdev, 895 uint8_t vdev_id) 896 { 897 struct wlan_objmgr_vdev *vdev; 898 struct wlan_ser_pdev_obj *ser_pdev_obj; 899 900 if (!pdev) { 901 ser_err("Invalid pdev"); 902 return; 903 } 904 905 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 906 if (!ser_pdev_obj) { 907 ser_err("invalid ser_pdev_obj"); 908 return; 909 } 910 911 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 912 WLAN_SERIALIZATION_ID); 913 if (!vdev) { 914 ser_err("Invalid vdev"); 915 return; 916 } 917 918 wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, 919 WLAN_SER_CMD_SCAN, false); 920 wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, 921 WLAN_SER_CMD_NONSCAN, false, 922 WLAN_SER_CMD_ATTR_NONE); 923 924 wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); 925 } 926 927 void wlan_serialization_purge_all_cmd_by_vdev_id(struct wlan_objmgr_pdev *pdev, 928 uint8_t vdev_id) 929 { 930 struct wlan_objmgr_vdev *vdev; 931 struct wlan_ser_pdev_obj *ser_pdev_obj; 932 933 if (!pdev) { 934 ser_err("Invalid pdev"); 935 return; 936 } 937 938 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 939 if (!ser_pdev_obj) { 940 ser_err("invalid ser_pdev_obj"); 941 return; 942 } 943 944 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 945 WLAN_SERIALIZATION_ID); 946 if (!vdev) { 947 ser_err("Invalid vdev"); 948 return; 949 } 950 951 wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, 952 WLAN_SER_CMD_SCAN, false); 953 wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, 954 WLAN_SER_CMD_SCAN, true); 955 wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, 956 WLAN_SER_CMD_NONSCAN, false, 957 WLAN_SER_CMD_ATTR_NONE); 958 wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, 959 WLAN_SER_CMD_NONSCAN, true, 960 WLAN_SER_CMD_ATTR_NONE); 961 962 wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); 963 } 964 965 void wlan_serialization_purge_all_scan_cmd_by_vdev_id( 966 struct wlan_objmgr_pdev *pdev, 967 uint8_t vdev_id) 968 { 969 struct wlan_objmgr_vdev *vdev; 970 struct wlan_ser_pdev_obj *ser_pdev_obj; 971 972 if (!pdev) { 973 ser_err("Invalid pdev"); 974 return; 975 } 976 977 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 978 if (!ser_pdev_obj) { 979 ser_err("invalid ser_pdev_obj"); 980 return; 981 } 982 983 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 984 WLAN_SERIALIZATION_ID); 985 if (!vdev) { 986 ser_err("Invalid vdev"); 987 return; 988 } 989 990 wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, 991 WLAN_SER_CMD_SCAN, false); 992 wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, 993 WLAN_SER_CMD_SCAN, true); 994 995 wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); 996 } 997 998 QDF_STATUS wlan_ser_vdev_queue_disable(struct wlan_objmgr_vdev *vdev) 999 { 1000 struct wlan_objmgr_pdev *pdev; 1001 struct wlan_ser_vdev_obj *ser_vdev_obj; 1002 struct wlan_serialization_vdev_queue *vdev_queue; 1003 struct wlan_ser_pdev_obj *ser_pdev_obj; 1004 struct wlan_serialization_pdev_queue *pdev_q; 1005 1006 pdev = wlan_vdev_get_pdev(vdev); 1007 if (!pdev) { 1008 ser_err("invalid PDEV object"); 1009 return QDF_STATUS_E_INVAL; 1010 } 1011 1012 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); 1013 if (!ser_pdev_obj) { 1014 ser_err("invalid ser_pdev_obj"); 1015 return QDF_STATUS_E_INVAL; 1016 } 1017 1018 ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev); 1019 if (!ser_vdev_obj) { 1020 ser_err("invalid ser_vdev_obj"); 1021 return QDF_STATUS_E_INVAL; 1022 } 1023 1024 pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; 1025 1026 vdev_queue = wlan_serialization_get_vdev_queue_obj( 1027 ser_vdev_obj, WLAN_SER_CMD_NONSCAN); 1028 if (!vdev_queue) { 1029 ser_err("invalid vdev_queue object"); 1030 return QDF_STATUS_E_INVAL; 1031 } 1032 1033 wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); 1034 vdev_queue->queue_disable = true; 1035 wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); 1036 ser_debug("Disabling the serialization for vdev:%d", 1037 wlan_vdev_get_id(vdev)); 1038 1039 return QDF_STATUS_SUCCESS; 1040 } 1041 1042 enum scm_scan_status 1043 wlan_get_vdev_status(struct wlan_objmgr_vdev *vdev) 1044 { 1045 enum wlan_serialization_cmd_status status; 1046 1047 if (!vdev) { 1048 ser_err("null vdev"); 1049 return SCAN_NOT_IN_PROGRESS; 1050 } 1051 status = wlan_serialization_vdev_scan_status(vdev); 1052 1053 return wlan_get_scan_status_from_serialization_status(status); 1054 } 1055 1056 enum scm_scan_status 1057 wlan_get_pdev_status(struct wlan_objmgr_pdev *pdev) 1058 { 1059 enum wlan_serialization_cmd_status status; 1060 1061 if (!pdev) { 1062 ser_err("null pdev"); 1063 return SCAN_NOT_IN_PROGRESS; 1064 } 1065 status = wlan_serialization_pdev_scan_status(pdev); 1066 1067 return wlan_get_scan_status_from_serialization_status(status); 1068 } 1069