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