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