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