1 /* 2 * Copyright (c) 2015,2017-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2023 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 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 21 #include "target_if_spectral.h" 22 #include "target_if_spectral_sim.h" 23 #include "target_if_spectral_sim_int.h" 24 #include "_ieee80211.h" 25 #include "ieee80211_api.h" 26 #include "ieee80211_defines.h" 27 #include "qdf_types.h" 28 #include "ieee80211_var.h" 29 #include <wlan_mlme_dispatcher.h> 30 #include <qdf_module.h> 31 32 /* Helper functions */ 33 34 static int target_if_populate_report_static_gen2( 35 struct spectralsim_report *report, 36 enum phy_ch_width width, bool is_80_80); 37 static int target_if_populate_report_static_gen3( 38 struct spectralsim_report *report, 39 enum phy_ch_width width, bool is_80_80); 40 static void target_if_depopulate_report( 41 struct spectralsim_report *report); 42 43 static int target_if_populate_reportset_static( 44 struct spectralsim_context *simctx, 45 struct spectralsim_reportset *reportset, 46 enum phy_ch_width width, bool is_80_80); 47 static void target_if_depopulate_reportset( 48 struct spectralsim_reportset * 49 reportset); 50 51 static int target_if_populate_simdata(struct spectralsim_context *simctx); 52 static void target_if_depopulate_simdata(struct spectralsim_context *simctx); 53 static OS_TIMER_FUNC(target_if_spectral_sim_phyerrdelivery_handler); 54 55 /* 56 * Static configuration. 57 * For now, we will be having a single configuration per BW, and a single 58 * report per configuration (since we need the data only for ensuring correct 59 * format handling). 60 * 61 * Extend this for more functionality if required in the future. 62 */ 63 64 /** 65 * target_if_populate_report_static_gen2() - Statically populate simulation 66 * data for one report for generation 2 chipsets 67 * @report: Pointer to spectral report data instance 68 * @width : Channel bandwidth enumeration 69 * 70 * Statically populate simulation data for one report for generation 2 chipsets 71 * 72 * Return: 0 on success, negative error code on failure 73 */ 74 static int 75 target_if_populate_report_static_gen2( 76 struct spectralsim_report *report, 77 enum phy_ch_width width) 78 { 79 if (!report) { 80 spectral_err("report pointer is null."); 81 goto bad; 82 } 83 84 switch (width) { 85 case CH_WIDTH_20MHZ: 86 report->data = NULL; 87 report->data = (uint8_t *) 88 qdf_mem_malloc(sizeof(reportdata_20_gen2)); 89 90 if (!report->data) 91 goto bad; 92 93 report->datasize = sizeof(reportdata_20_gen2); 94 qdf_mem_copy(report->data, 95 reportdata_20_gen2, report->datasize); 96 97 qdf_mem_copy(&report->rfqual_info, 98 &rfqual_info_20, sizeof(report->rfqual_info)); 99 100 qdf_mem_copy(&report->chan_info, 101 &chan_info_20, sizeof(report->chan_info)); 102 103 break; 104 case CH_WIDTH_40MHZ: 105 report->data = NULL; 106 report->data = (uint8_t *) 107 qdf_mem_malloc(sizeof(reportdata_40_gen2)); 108 109 if (!report->data) 110 goto bad; 111 112 report->datasize = sizeof(reportdata_40_gen2); 113 qdf_mem_copy(report->data, 114 reportdata_40_gen2, report->datasize); 115 116 qdf_mem_copy(&report->rfqual_info, 117 &rfqual_info_40, sizeof(report->rfqual_info)); 118 119 qdf_mem_copy(&report->chan_info, 120 &chan_info_40, sizeof(report->chan_info)); 121 122 break; 123 case CH_WIDTH_80MHZ: 124 report->data = NULL; 125 report->data = (uint8_t *) 126 qdf_mem_malloc(sizeof(reportdata_80_gen2)); 127 128 if (!report->data) 129 goto bad; 130 131 report->datasize = sizeof(reportdata_80_gen2); 132 qdf_mem_copy(report->data, 133 reportdata_80_gen2, report->datasize); 134 135 qdf_mem_copy(&report->rfqual_info, 136 &rfqual_info_80, sizeof(report->rfqual_info)); 137 138 qdf_mem_copy(&report->chan_info, 139 &chan_info_80, sizeof(report->chan_info)); 140 141 break; 142 case CH_WIDTH_80P80MHZ: 143 report->data = NULL; 144 report->data = (uint8_t *) 145 qdf_mem_malloc(sizeof(reportdata_80_80_gen2)); 146 147 if (!report->data) 148 goto bad; 149 150 report->datasize = sizeof(reportdata_80_80_gen2); 151 qdf_mem_copy(report->data, 152 reportdata_80_80_gen2, report->datasize); 153 154 qdf_mem_copy(&report->rfqual_info, 155 &rfqual_info_80_80, 156 sizeof(report->rfqual_info)); 157 158 qdf_mem_copy(&report->chan_info, 159 &chan_info_80_80, 160 sizeof(report->chan_info)); 161 break; 162 163 case CH_WIDTH_160MHZ: 164 report->data = NULL; 165 report->data = (uint8_t *) 166 qdf_mem_malloc(sizeof(reportdata_160_gen2)); 167 168 if (!report->data) 169 goto bad; 170 171 report->datasize = sizeof(reportdata_160_gen2); 172 qdf_mem_copy(report->data, 173 reportdata_160_gen2, report->datasize); 174 175 qdf_mem_copy(&report->rfqual_info, 176 &rfqual_info_160, 177 sizeof(report->rfqual_info)); 178 179 qdf_mem_copy(&report->chan_info, 180 &chan_info_160, sizeof(report->chan_info)); 181 break; 182 183 default: 184 spectral_err("Unhandled width enum: %d. Please correct.", 185 width); 186 goto bad; 187 } 188 189 return 0; 190 191 bad: 192 return -EPERM; 193 } 194 195 /** 196 * target_if_populate_report_static_gen3() - Statically populate simulation 197 * data for one report for generation 3 chipsets 198 * @report: Pointer to spectral report data instance 199 * @width : Channel bandwidth enumeration 200 * 201 * Statically populate simulation data for one report for generation 3 chipsets 202 * 203 * Return: 0 on success, negative error code on failure 204 */ 205 static int 206 target_if_populate_report_static_gen3( 207 struct spectralsim_report *report, 208 enum phy_ch_width width) 209 { 210 if (!report) { 211 spectral_err("report pointer is null"); 212 goto bad; 213 } 214 switch (width) { 215 case CH_WIDTH_20MHZ: 216 report->data = NULL; 217 report->data = (uint8_t *) 218 qdf_mem_malloc(sizeof(reportdata_20_gen3)); 219 220 if (!report->data) 221 goto bad; 222 223 report->datasize = sizeof(reportdata_20_gen3); 224 qdf_mem_copy(report->data, 225 reportdata_20_gen3, report->datasize); 226 227 qdf_mem_copy(&report->rfqual_info, 228 &rfqual_info_20, sizeof(report->rfqual_info)); 229 230 qdf_mem_copy(&report->chan_info, 231 &chan_info_20, sizeof(report->chan_info)); 232 233 break; 234 case CH_WIDTH_40MHZ: 235 report->data = NULL; 236 report->data = (uint8_t *) 237 qdf_mem_malloc(sizeof(reportdata_40_gen3)); 238 239 if (!report->data) 240 goto bad; 241 242 report->datasize = sizeof(reportdata_40_gen3); 243 qdf_mem_copy(report->data, 244 reportdata_40_gen3, report->datasize); 245 246 qdf_mem_copy(&report->rfqual_info, 247 &rfqual_info_40, sizeof(report->rfqual_info)); 248 249 qdf_mem_copy(&report->chan_info, 250 &chan_info_40, sizeof(report->chan_info)); 251 252 break; 253 case CH_WIDTH_80MHZ: 254 report->data = NULL; 255 report->data = (uint8_t *) 256 qdf_mem_malloc(sizeof(reportdata_80_gen3)); 257 258 if (!report->data) 259 goto bad; 260 261 report->datasize = sizeof(reportdata_80_gen3); 262 qdf_mem_copy(report->data, 263 reportdata_80_gen3, report->datasize); 264 265 qdf_mem_copy(&report->rfqual_info, 266 &rfqual_info_80, sizeof(report->rfqual_info)); 267 268 qdf_mem_copy(&report->chan_info, 269 &chan_info_80, sizeof(report->chan_info)); 270 271 break; 272 273 case CH_WIDTH_80P80MHZ: 274 report->data = NULL; 275 report->data = (uint8_t *) 276 qdf_mem_malloc(sizeof(reportdata_80_80_gen3)); 277 278 if (!report->data) 279 goto bad; 280 281 report->datasize = sizeof(reportdata_80_80_gen3); 282 qdf_mem_copy(report->data, 283 reportdata_80_80_gen3, report->datasize); 284 285 qdf_mem_copy(&report->rfqual_info, 286 &rfqual_info_80_80, 287 sizeof(report->rfqual_info)); 288 289 qdf_mem_copy(&report->chan_info, 290 &chan_info_80_80, 291 sizeof(report->chan_info)); 292 break; 293 294 case CH_WIDTH_160MHZ: 295 report->data = NULL; 296 report->data = (uint8_t *) 297 qdf_mem_malloc(sizeof(reportdata_160_gen3)); 298 299 if (!report->data) 300 goto bad; 301 302 report->datasize = sizeof(reportdata_160_gen3); 303 qdf_mem_copy(report->data, 304 reportdata_160_gen3, report->datasize); 305 306 qdf_mem_copy(&report->rfqual_info, 307 &rfqual_info_160, 308 sizeof(report->rfqual_info)); 309 310 qdf_mem_copy(&report->chan_info, 311 &chan_info_160, sizeof(report->chan_info)); 312 break; 313 314 default: 315 spectral_err("Unhandled width enum: %d. Please correct.", 316 width); 317 goto bad; 318 } 319 320 return 0; 321 322 bad: 323 return -EPERM; 324 } 325 326 /** 327 * target_if_depopulate_report() - Free the given instances of 328 * struct spectralsim_report 329 * @report: instance of struct spectralsim_report 330 * 331 * Free the given instances of struct spectralsim_report 332 * 333 * Return: None 334 */ 335 static void 336 target_if_depopulate_report( 337 struct spectralsim_report *report) 338 { 339 if (!report) 340 return; 341 342 if (report->data) { 343 qdf_mem_free(report->data); 344 report->data = NULL; 345 report->datasize = 0; 346 } 347 } 348 349 /** 350 * target_if_populate_reportset_static() - Statically populate simulation data 351 * for a given configuration 352 * @simctx: Pointer to struct spectralsim_context 353 * @reportset: Set of spectral report data instances 354 * @width : Channel bandwidth enumeration 355 * 356 * Statically populate simulation data for a given configuration 357 * 358 * Return: 0 on success, negative error code on failure 359 */ 360 static int 361 target_if_populate_reportset_static( 362 struct spectralsim_context *simctx, 363 struct spectralsim_reportset *reportset, 364 enum phy_ch_width width) 365 { 366 int ret = 0; 367 struct spectralsim_report *report = NULL; 368 369 if (!reportset) { 370 spectral_err("reportset pointer is null."); 371 goto bad; 372 } 373 374 reportset->headreport = NULL; 375 reportset->curr_report = NULL; 376 377 /* For now, we populate only one report */ 378 report = (struct spectralsim_report *) 379 qdf_mem_malloc(sizeof(struct spectralsim_report)); 380 381 if (!report) 382 goto bad; 383 384 qdf_mem_zero(report, sizeof(*report)); 385 386 switch (width) { 387 case CH_WIDTH_20MHZ: 388 qdf_mem_copy(&reportset->config, 389 &config_20_1, sizeof(reportset->config)); 390 391 ret = simctx->populate_report_static(report, CH_WIDTH_20MHZ); 392 if (ret != 0) 393 goto bad; 394 395 report->next = NULL; 396 reportset->headreport = report; 397 break; 398 case CH_WIDTH_40MHZ: 399 qdf_mem_copy(&reportset->config, 400 &config_40_1, sizeof(reportset->config)); 401 402 ret = simctx->populate_report_static(report, CH_WIDTH_40MHZ); 403 if (ret != 0) 404 goto bad; 405 406 report->next = NULL; 407 reportset->headreport = report; 408 break; 409 case CH_WIDTH_80MHZ: 410 qdf_mem_copy(&reportset->config, 411 &config_80_1, sizeof(reportset->config)); 412 413 ret = simctx->populate_report_static(report, CH_WIDTH_80MHZ); 414 if (ret != 0) 415 goto bad; 416 417 report->next = NULL; 418 reportset->headreport = report; 419 break; 420 421 case CH_WIDTH_80P80MHZ: 422 qdf_mem_copy(&reportset->config, 423 &config_80_80_1, 424 sizeof(reportset->config)); 425 426 ret = simctx->populate_report_static(report, 427 CH_WIDTH_80P80MHZ); 428 if (ret != 0) 429 goto bad; 430 431 report->next = NULL; 432 reportset->headreport = report; 433 break; 434 435 case CH_WIDTH_160MHZ: 436 qdf_mem_copy(&reportset->config, 437 &config_160_1, sizeof(reportset->config)); 438 439 ret = simctx->populate_report_static(report, 440 CH_WIDTH_160MHZ); 441 if (ret != 0) 442 goto bad; 443 444 report->next = NULL; 445 reportset->headreport = report; 446 break; 447 448 default: 449 spectral_err("Unhandled width enum: %d. Please correct.", 450 width); 451 goto bad; 452 }; 453 454 reportset->curr_report = reportset->headreport; 455 456 return 0; 457 458 bad: 459 target_if_depopulate_reportset(reportset); 460 return -EPERM; 461 } 462 463 /** 464 * target_if_depopulate_reportset() - Free all the instances of 465 * struct spectralsim_reportset 466 * @reportset: head pointer to struct spectralsim_reportset linked list 467 * 468 * Free all the instances of struct spectralsim_reportset 469 * 470 * Return: None 471 */ 472 static void 473 target_if_depopulate_reportset( 474 struct spectralsim_reportset *reportset) 475 { 476 struct spectralsim_report *curr_report = NULL; 477 struct spectralsim_report *next_report = NULL; 478 479 if (!reportset) 480 return; 481 482 curr_report = reportset->headreport; 483 484 while (curr_report) { 485 next_report = curr_report->next; 486 target_if_depopulate_report(curr_report); 487 qdf_mem_free(curr_report); 488 curr_report = next_report; 489 } 490 } 491 492 /** 493 * target_if_populate_simdata() - Populate simulation data 494 * @simctx: Pointer to struct spectralsim_context 495 * 496 * Populate simulation data 497 * 498 * Return: 0 on success, negative error code on failure 499 */ 500 static int 501 target_if_populate_simdata( 502 struct spectralsim_context *simctx) 503 { 504 /* 505 * For now, we use static population. Switch to loading from a file if 506 * needed in the future. 507 */ 508 509 simctx->bw20_headreportset = NULL; 510 SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx, 511 simctx->bw20_headreportset, 512 CH_WIDTH_20MHZ); 513 514 simctx->bw40_headreportset = NULL; 515 SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx, 516 simctx->bw40_headreportset, 517 CH_WIDTH_40MHZ); 518 519 simctx->bw80_headreportset = NULL; 520 SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx, 521 simctx->bw80_headreportset, 522 CH_WIDTH_80MHZ); 523 524 simctx->bw160_headreportset = NULL; 525 SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx, 526 simctx->bw160_headreportset, 527 CH_WIDTH_160MHZ); 528 529 simctx->bw80_80_headreportset = NULL; 530 SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx, 531 simctx->bw80_80_headreportset, 532 CH_WIDTH_80P80MHZ); 533 534 simctx->curr_reportset = NULL; 535 536 simctx->is_enabled = false; 537 simctx->is_active = false; 538 539 simctx->ssim_starting_tsf64 = 0; 540 simctx->ssim_count = 0; 541 simctx->ssim_period_ms = 0; 542 543 return 0; 544 } 545 546 /** 547 * target_if_depopulate_simdata() - De-populate simulation data 548 * @simctx: Pointer to struct spectralsim_context 549 * 550 * De-populate simulation data 551 * 552 * Return: none 553 */ 554 static void 555 target_if_depopulate_simdata( 556 struct spectralsim_context *simctx) 557 { 558 if (!simctx) 559 return; 560 561 SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw20_headreportset); 562 SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw40_headreportset); 563 SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_headreportset); 564 SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw160_headreportset); 565 SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_80_headreportset); 566 } 567 568 /* 569 * target_if_spectral_sim_phyerrdelivery_handler() - Phyerr delivery handler 570 * 571 * Return: none 572 * 573 * NB: kernel-doc script doesn't parse OS_TIMER_FUNC 574 */ 575 static 576 OS_TIMER_FUNC(target_if_spectral_sim_phyerrdelivery_handler) 577 { 578 struct target_if_spectral *spectral = NULL; 579 struct spectralsim_context *simctx = NULL; 580 struct spectralsim_reportset *curr_reportset = NULL; 581 struct spectralsim_report *curr_report = NULL; 582 struct target_if_spectral_acs_stats acs_stats; 583 uint64_t curr_tsf64 = 0; 584 struct target_if_spectral_ops *p_sops; 585 586 OS_GET_TIMER_ARG(spectral, struct target_if_spectral *); 587 if (!spectral) { 588 spectral_err("spectral pointer is null."); 589 return; 590 } 591 592 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 593 if (!p_sops) { 594 spectral_err("p_sops pointer is null."); 595 return; 596 } 597 598 simctx = (struct spectralsim_context *)spectral->simctx; 599 if (!simctx) { 600 spectral_err("simctx pointer is null."); 601 return; 602 } 603 604 if (!simctx->is_active) 605 return; 606 607 curr_reportset = simctx->curr_reportset; 608 if (!curr_reportset) { 609 spectral_err("curr_reportset pointer is null."); 610 return; 611 } 612 613 curr_report = curr_reportset->curr_report; 614 if (!curr_report) { 615 spectral_err("curr_report pointer is null."); 616 return; 617 } 618 619 if (!curr_reportset->headreport) { 620 spectral_err("curr_reportset->headreport pointer is null."); 621 return; 622 } 623 624 /* 625 * We use a simulation TSF since in offload architectures we can't 626 * expect to 627 * get an accurate current TSF from HW. 628 * In case of TSF wrap over, we'll use it as-is for now since the 629 * simulation 630 * is intended only for format verification. 631 */ 632 curr_tsf64 = simctx->ssim_starting_tsf64 + 633 ((simctx->ssim_period_ms * simctx->ssim_count) * 1000); 634 635 p_sops->spectral_process_phyerr(spectral, 636 curr_report->data, 637 curr_report->datasize, 638 &curr_report->rfqual_info, 639 &curr_report->chan_info, 640 curr_tsf64, &acs_stats); 641 642 simctx->ssim_count++; 643 644 if (curr_report->next) 645 curr_reportset->curr_report = curr_report->next; 646 else 647 curr_reportset->curr_report = curr_reportset->headreport; 648 649 if (curr_reportset->config.ss_count != 0 && 650 simctx->ssim_count == curr_reportset->config.ss_count) { 651 target_if_spectral_sops_sim_stop_scan(spectral); 652 } else { 653 qdf_timer_start(&simctx->ssim_pherrdelivery_timer, 654 simctx->ssim_period_ms); 655 } 656 } 657 658 /* Module services */ 659 660 int 661 target_if_spectral_sim_attach(struct target_if_spectral *spectral) 662 { 663 struct spectralsim_context *simctx = NULL; 664 665 if (!spectral) { 666 spectral_err("Spectral simulation: spectral pointer is null.") 667 return -EPERM; 668 } 669 670 simctx = (struct spectralsim_context *) 671 qdf_mem_malloc(sizeof(struct spectralsim_context)); 672 673 if (!simctx) 674 return -EPERM; 675 676 qdf_mem_zero(simctx, sizeof(*simctx)); 677 678 spectral->simctx = simctx; 679 680 if (spectral->spectral_gen == SPECTRAL_GEN2) 681 simctx->populate_report_static = 682 target_if_populate_report_static_gen2; 683 else if (spectral->spectral_gen == SPECTRAL_GEN3) 684 simctx->populate_report_static = 685 target_if_populate_report_static_gen3; 686 687 if (target_if_populate_simdata(simctx) != 0) { 688 qdf_mem_free(simctx); 689 spectral->simctx = NULL; 690 spectral_err("Spectral simulation attach failed"); 691 return -EPERM; 692 } 693 694 qdf_timer_init(NULL, 695 &simctx->ssim_pherrdelivery_timer, 696 target_if_spectral_sim_phyerrdelivery_handler, 697 (void *)(spectral), QDF_TIMER_TYPE_WAKE_APPS); 698 699 spectral_info("Spectral simulation attached"); 700 701 return 0; 702 } 703 704 void 705 target_if_spectral_sim_detach(struct target_if_spectral *spectral) 706 { 707 struct spectralsim_context *simctx = NULL; 708 709 if (!spectral) { 710 spectral_err("spectral pointer is null."); 711 return; 712 } 713 714 simctx = (struct spectralsim_context *)spectral->simctx; 715 if (!simctx) { 716 spectral_err("simctx pointer is null."); 717 return; 718 } 719 720 qdf_timer_free(&simctx->ssim_pherrdelivery_timer); 721 722 target_if_depopulate_simdata(simctx); 723 qdf_mem_free(simctx); 724 spectral->simctx = NULL; 725 726 spectral_info("Spectral simulation detached"); 727 } 728 729 uint32_t 730 target_if_spectral_sops_sim_is_active(void *arg) 731 { 732 struct target_if_spectral *spectral = NULL; 733 struct spectralsim_context *simctx = NULL; 734 735 spectral = (struct target_if_spectral *)arg; 736 if (!spectral) { 737 spectral_err("Spectral simulation: spectral pointer is null"); 738 return 0; 739 } 740 simctx = (struct spectralsim_context *)spectral->simctx; 741 if (!simctx) { 742 spectral_err("Spectral simulation: simctx pointer is null"); 743 return 0; 744 } 745 746 return simctx->is_active; 747 } 748 qdf_export_symbol(target_if_spectral_sops_sim_is_active); 749 750 uint32_t 751 target_if_spectral_sops_sim_is_enabled(void *arg) 752 { 753 struct target_if_spectral *spectral = NULL; 754 struct spectralsim_context *simctx = NULL; 755 756 spectral = (struct target_if_spectral *)arg; 757 if (!spectral) { 758 spectral_err("Spectral simulation: spectral pointer is null"); 759 return 0; 760 } 761 simctx = (struct spectralsim_context *)spectral->simctx; 762 if (!simctx) { 763 spectral_err("Spectral simulation: simctx pointer is null"); 764 return 0; 765 } 766 767 return simctx->is_enabled; 768 } 769 qdf_export_symbol(target_if_spectral_sops_sim_is_enabled); 770 771 uint32_t 772 target_if_spectral_sops_sim_start_scan(void *arg) 773 { 774 struct target_if_spectral *spectral = NULL; 775 struct spectralsim_context *simctx = NULL; 776 777 spectral = (struct target_if_spectral *)arg; 778 if (!spectral) { 779 spectral_err("Spectral simulation: spectral pointer is null"); 780 return 0; 781 } 782 simctx = (struct spectralsim_context *)spectral->simctx; 783 if (!simctx) { 784 spectral_err("Spectral simulation: simctx pointer is null"); 785 return 0; 786 } 787 788 if (!simctx->curr_reportset) { 789 spectral_err("Spectral simulation: No current report set configured - unable to start simulated Spectral scan"); 790 return 0; 791 } 792 793 if (!simctx->curr_reportset->curr_report) { 794 spectral_err("Spectral simulation: No report data instances populated - unable to start simulated Spectral scan"); 795 return 0; 796 } 797 798 if (!simctx->is_enabled) 799 simctx->is_enabled = true; 800 801 simctx->is_active = true; 802 803 /* Hardcoding current time as zero since it is simulation */ 804 simctx->ssim_starting_tsf64 = 0; 805 simctx->ssim_count = 0; 806 807 /* 808 * TODO: Support high resolution timer in microseconds if required, so 809 * that 810 * we can support default periods such as ~200 us. For now, we use 1 811 * millisecond since the current use case for the simulation is to 812 * validate 813 * formats rather than have a time dependent classification. 814 */ 815 simctx->ssim_period_ms = 1; 816 817 qdf_timer_start(&simctx->ssim_pherrdelivery_timer, 818 simctx->ssim_period_ms); 819 820 return 1; 821 } 822 qdf_export_symbol(target_if_spectral_sops_sim_start_scan); 823 824 uint32_t 825 target_if_spectral_sops_sim_stop_scan(void *arg) 826 { 827 struct target_if_spectral *spectral = NULL; 828 struct spectralsim_context *simctx = NULL; 829 830 spectral = (struct target_if_spectral *)arg; 831 if (!spectral) { 832 spectral_err("Spectral simulation: spectral pointer is null"); 833 return 0; 834 } 835 simctx = (struct spectralsim_context *)spectral->simctx; 836 if (!simctx) { 837 spectral_err("Spectral simulation: simctx pointer is null"); 838 return 0; 839 } 840 841 qdf_timer_stop(&simctx->ssim_pherrdelivery_timer); 842 843 simctx->is_active = false; 844 simctx->is_enabled = false; 845 846 simctx->ssim_starting_tsf64 = 0; 847 simctx->ssim_count = 0; 848 simctx->ssim_period_ms = 0; 849 850 return 1; 851 } 852 qdf_export_symbol(target_if_spectral_sops_sim_stop_scan); 853 854 #ifdef SPECTRAL_SIM_DUMP_PARAM_DATA 855 static void 856 target_if_log_sim_spectral_params(struct spectral_config *params) 857 { 858 int i = 0; 859 860 spectral_debug("\n"); 861 862 spectral_debug("Spectral simulation: Param data dump:\nss_fft_period=%hu\nss_period=%hu\nss_count=%hu\nss_short_report=%hu\nradar_bin_thresh_sel=%hhu\nss_spectral_pri=%hu\nss_fft_size=%hu\nss_gc_ena=%hu\nss_restart_ena=%hu\nss_noise_floor_ref=%hu\nss_init_delay=%hu\nss_nb_tone_thr=%hu\nss_str_bin_thr=%hu\nss_wb_rpt_mode=%hu\nss_rssi_rpt_mode=%hu\nss_rssi_thr=%hu\nss_pwr_format=%hu\nss_rpt_mode=%hu\nss_bin_scale=%hu\nss_dbm_adj=%hu\nss_chn_mask=%hu\nss_nf_temp_data=%d", 863 params->ss_fft_period, 864 params->ss_period, 865 params->ss_count, 866 params->ss_short_report, 867 params->radar_bin_thresh_sel, 868 params->ss_spectral_pri, 869 params->ss_fft_size, 870 params->ss_gc_ena, 871 params->ss_restart_ena, 872 params->ss_noise_floor_ref, 873 params->ss_init_delay, 874 params->ss_nb_tone_thr, 875 params->ss_str_bin_thr, 876 params->ss_wb_rpt_mode, 877 params->ss_rssi_rpt_mode, 878 params->ss_rssi_thr, 879 params->ss_pwr_format, 880 params->ss_rpt_mode, 881 params->ss_bin_scale, 882 params->ss_dbm_adj, 883 params->ss_chn_mask, params->ss_nf_temp_data); 884 885 for (i = 0; i < AH_MAX_CHAINS * 2; i++) 886 spectral_debug("ss_nf_cal[%d]=%hhd", i, params->ss_nf_cal[i]); 887 888 for (i = 0; i < AH_MAX_CHAINS * 2; i++) 889 spectral_debug("ss_nf_pwr[%d]=%hhd", i, params->ss_nf_pwr[i]); 890 891 spectral_info("\n"); 892 } 893 #else 894 895 static void 896 target_if_log_sim_spectral_params(struct spectral_config *params) 897 { 898 } 899 #endif /* SPECTRAL_SIM_DUMP_PARAM_DATA */ 900 901 uint32_t 902 target_if_spectral_sops_sim_configure_params( 903 void *arg, 904 struct spectral_config *params, 905 enum spectral_scan_mode smode) 906 { 907 struct target_if_spectral *spectral = NULL; 908 struct spectralsim_context *simctx = NULL; 909 enum wlan_phymode phymode; 910 uint8_t bw; 911 struct spectralsim_reportset *des_headreportset = NULL; 912 struct spectralsim_reportset *temp_reportset = NULL; 913 struct wlan_objmgr_vdev *vdev = NULL; 914 915 if (!params) { 916 spectral_err("Spectral simulation: params pointer is null.") 917 return 0; 918 } 919 target_if_log_sim_spectral_params(params); 920 921 spectral = (struct target_if_spectral *)arg; 922 if (!spectral) { 923 spectral_err("Spectral simulation: spectral pointer is null"); 924 return 0; 925 } 926 simctx = (struct spectralsim_context *)spectral->simctx; 927 if (!simctx) { 928 spectral_err("Spectral simulation: simctx pointer is null"); 929 return 0; 930 } 931 932 vdev = target_if_spectral_get_vdev(spectral, smode); 933 if (!vdev) { 934 spectral_warn("Spectral simulation: No VAPs found - not proceeding with param config."); 935 return 0; 936 } 937 938 bw = target_if_vdev_get_ch_width(vdev); 939 940 switch (bw) { 941 case CH_WIDTH_20MHZ: 942 des_headreportset = simctx->bw20_headreportset; 943 break; 944 case CH_WIDTH_40MHZ: 945 des_headreportset = simctx->bw40_headreportset; 946 break; 947 case CH_WIDTH_80MHZ: 948 des_headreportset = simctx->bw80_headreportset; 949 break; 950 case CH_WIDTH_160MHZ: 951 des_headreportset = simctx->bw160_headreportset; 952 break; 953 case CH_WIDTH_80P80MHZ: 954 des_headreportset = simctx->bw80_80_headreportset; 955 break; 956 case CH_WIDTH_INVALID: 957 default: 958 spectral_err("Spectral simulation: Invalid width: %d configured - not proceeding with param config.", 959 bw); 960 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 961 return 0; 962 } 963 964 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 965 966 if (!des_headreportset) { 967 spectral_warn("Spectral simulation: No simulation data present for configured bandwidth/PHY mode - unable to proceed with param config."); 968 return 0; 969 } 970 971 simctx->curr_reportset = NULL; 972 temp_reportset = des_headreportset; 973 974 while (temp_reportset) { 975 if (qdf_mem_cmp(&temp_reportset->config, 976 params, sizeof(struct spectral_config)) == 0) { 977 /* Found a matching config. We are done. */ 978 simctx->curr_reportset = temp_reportset; 979 break; 980 } 981 982 temp_reportset = temp_reportset->next; 983 } 984 985 if (!simctx->curr_reportset) { 986 spectral_warn("Spectral simulation: No simulation data present for desired Spectral configuration - unable to proceed with param config."); 987 return 0; 988 } 989 990 if (!simctx->curr_reportset->curr_report) { 991 spectral_warn("Spectral simulation: No report data instances populated for desired Spectral configuration - unable to proceed with param config"); 992 return 0; 993 } 994 995 return 1; 996 } 997 qdf_export_symbol(target_if_spectral_sops_sim_configure_params); 998 999 uint32_t 1000 target_if_spectral_sops_sim_get_params( 1001 void *arg, struct spectral_config *params) 1002 { 1003 struct target_if_spectral *spectral = NULL; 1004 struct spectralsim_context *simctx = NULL; 1005 spectral = (struct target_if_spectral *)arg; 1006 1007 if (!param || !spectral) { 1008 spectral_err("Spectral simulation: null params, param %pK, spectral %pK.", 1009 param, spectral); 1010 return 0; 1011 } 1012 1013 simctx = (struct spectralsim_context *)spectral->simctx; 1014 if (!simctx) { 1015 spectral_err("Spectral simulation: simctx pointer is null."); 1016 return 0; 1017 } 1018 1019 if (!simctx->curr_reportset) { 1020 spectral_warn("Spectral simulation: No configured reportset found."); 1021 return 0; 1022 } 1023 1024 qdf_mem_copy(params, &simctx->curr_reportset->config, sizeof(*params)); 1025 1026 return 1; 1027 } 1028 qdf_export_symbol(target_if_spectral_sops_sim_get_params); 1029 1030 #endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */ 1031