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