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