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