
Currently 160 and 80+80 MHz modes are handled together in Spectral module. Differentiate between 160 and 80+80 MHz to support new features like restricted 80+80 which are applicable only with 80+80 MHz. CRs-Fixed: 2630729 Change-Id: I3e9fdd0e2d22a0bca7d37445df7fb1f1bab023c8
962 خطوط
25 KiB
C
962 خطوط
25 KiB
C
/*
|
|
* Copyright (c) 2015,2017-2020 The Linux Foundation. All rights reserved.
|
|
*
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for
|
|
* any purpose with or without fee is hereby granted, provided that the
|
|
* above copyright notice and this permission notice appear in all
|
|
* copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
|
|
#include "target_if_spectral.h"
|
|
#include "target_if_spectral_sim.h"
|
|
#include "target_if_spectral_sim_int.h"
|
|
#include "_ieee80211.h"
|
|
#include "ieee80211_api.h"
|
|
#include "ieee80211_defines.h"
|
|
#include "qdf_types.h"
|
|
#include "ieee80211_var.h"
|
|
#include <wlan_mlme_dispatcher.h>
|
|
#include <qdf_module.h>
|
|
|
|
/* Helper functions */
|
|
|
|
static int target_if_populate_report_static_gen2(
|
|
struct spectralsim_report *report,
|
|
enum phy_ch_width width, bool is_80_80);
|
|
static int target_if_populate_report_static_gen3(
|
|
struct spectralsim_report *report,
|
|
enum phy_ch_width width, bool is_80_80);
|
|
static void target_if_depopulate_report(
|
|
struct spectralsim_report *report);
|
|
|
|
static int target_if_populate_reportset_static(
|
|
struct spectralsim_context *simctx,
|
|
struct spectralsim_reportset *reportset,
|
|
enum phy_ch_width width, bool is_80_80);
|
|
static void target_if_depopulate_reportset(
|
|
struct spectralsim_reportset *
|
|
reportset);
|
|
|
|
static int target_if_populate_simdata(struct spectralsim_context *simctx);
|
|
static void target_if_depopulate_simdata(struct spectralsim_context *simctx);
|
|
static OS_TIMER_FUNC(target_if_spectral_sim_phyerrdelivery_handler);
|
|
|
|
/*
|
|
* Static configuration.
|
|
* For now, we will be having a single configuration per BW, and a single
|
|
* report per configuration (since we need the data only for ensuring correct
|
|
* format handling).
|
|
*
|
|
* Extend this for more functionality if required in the future.
|
|
*/
|
|
|
|
/**
|
|
* target_if_populate_report_static_gen2() - Statically populate simulation
|
|
* data for one report for generation 2 chipsets
|
|
* @report: Pointer to spectral report data instance
|
|
* @width : Channel bandwidth enumeration
|
|
*
|
|
* Statically populate simulation data for one report for generation 2 chipsets
|
|
*
|
|
* Return: 0 on success, negative error code on failure
|
|
*/
|
|
static int
|
|
target_if_populate_report_static_gen2(
|
|
struct spectralsim_report *report,
|
|
enum phy_ch_width width)
|
|
{
|
|
qdf_assert_always(report);
|
|
|
|
switch (width) {
|
|
case CH_WIDTH_20MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_20_gen2));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_20_gen2);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_20_gen2, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_20, sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_20, sizeof(report->chan_info));
|
|
|
|
break;
|
|
case CH_WIDTH_40MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_40_gen2));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_40_gen2);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_40_gen2, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_40, sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_40, sizeof(report->chan_info));
|
|
|
|
break;
|
|
case CH_WIDTH_80MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_80_gen2));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_80_gen2);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_80_gen2, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_80, sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_80, sizeof(report->chan_info));
|
|
|
|
break;
|
|
case CH_WIDTH_80P80MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_80_80_gen2));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_80_80_gen2);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_80_80_gen2, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_80_80,
|
|
sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_80_80,
|
|
sizeof(report->chan_info));
|
|
break;
|
|
|
|
case CH_WIDTH_160MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_160_gen2));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_160_gen2);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_160_gen2, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_160,
|
|
sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_160, sizeof(report->chan_info));
|
|
break;
|
|
|
|
default:
|
|
spectral_err("Unhandled width. Please correct. Asserting");
|
|
qdf_assert_always(0);
|
|
}
|
|
|
|
return 0;
|
|
|
|
bad:
|
|
return -EPERM;
|
|
}
|
|
|
|
/**
|
|
* target_if_populate_report_static_gen3() - Statically populate simulation
|
|
* data for one report for generation 3 chipsets
|
|
* @report: Pointer to spectral report data instance
|
|
* @width : Channel bandwidth enumeration
|
|
*
|
|
* Statically populate simulation data for one report for generation 3 chipsets
|
|
*
|
|
* Return: 0 on success, negative error code on failure
|
|
*/
|
|
static int
|
|
target_if_populate_report_static_gen3(
|
|
struct spectralsim_report *report,
|
|
enum phy_ch_width width)
|
|
{
|
|
qdf_assert_always(report);
|
|
|
|
switch (width) {
|
|
case CH_WIDTH_20MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_20_gen3));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_20_gen3);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_20_gen3, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_20, sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_20, sizeof(report->chan_info));
|
|
|
|
break;
|
|
case CH_WIDTH_40MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_40_gen3));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_40_gen3);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_40_gen3, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_40, sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_40, sizeof(report->chan_info));
|
|
|
|
break;
|
|
case CH_WIDTH_80MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_80_gen3));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_80_gen3);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_80_gen3, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_80, sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_80, sizeof(report->chan_info));
|
|
|
|
break;
|
|
|
|
case CH_WIDTH_80P80MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_80_80_gen3));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_80_80_gen3);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_80_80_gen3, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_80_80,
|
|
sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_80_80,
|
|
sizeof(report->chan_info));
|
|
break;
|
|
|
|
case CH_WIDTH_160MHZ:
|
|
report->data = NULL;
|
|
report->data = (uint8_t *)
|
|
qdf_mem_malloc(sizeof(reportdata_160_gen3));
|
|
|
|
if (!report->data)
|
|
goto bad;
|
|
|
|
report->datasize = sizeof(reportdata_160_gen3);
|
|
qdf_mem_copy(report->data,
|
|
reportdata_160_gen3, report->datasize);
|
|
|
|
qdf_mem_copy(&report->rfqual_info,
|
|
&rfqual_info_160,
|
|
sizeof(report->rfqual_info));
|
|
|
|
qdf_mem_copy(&report->chan_info,
|
|
&chan_info_160, sizeof(report->chan_info));
|
|
break;
|
|
|
|
default:
|
|
spectral_err("Unhandled width. Please correct. Asserting");
|
|
qdf_assert_always(0);
|
|
}
|
|
|
|
return 0;
|
|
|
|
bad:
|
|
return -EPERM;
|
|
}
|
|
|
|
/**
|
|
* target_if_depopulate_report() - Free the given instances of
|
|
* struct spectralsim_report
|
|
* @report: instance of struct spectralsim_report
|
|
*
|
|
* Free the given instances of struct spectralsim_report
|
|
*
|
|
* Return: None
|
|
*/
|
|
static void
|
|
target_if_depopulate_report(
|
|
struct spectralsim_report *report)
|
|
{
|
|
if (!report)
|
|
return;
|
|
|
|
if (report->data) {
|
|
qdf_mem_free(report->data);
|
|
report->data = NULL;
|
|
report->datasize = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* target_if_populate_reportset_static() - Statically populate simulation data
|
|
* for a given configuration
|
|
* @simctx: Pointer to struct spectralsim_context
|
|
* @reportset: Set of spectral report data instances
|
|
* @width : Channel bandwidth enumeration
|
|
*
|
|
* Statically populate simulation data for a given configuration
|
|
*
|
|
* Return: 0 on success, negative error code on failure
|
|
*/
|
|
static int
|
|
target_if_populate_reportset_static(
|
|
struct spectralsim_context *simctx,
|
|
struct spectralsim_reportset *reportset,
|
|
enum phy_ch_width width)
|
|
{
|
|
int ret = 0;
|
|
struct spectralsim_report *report = NULL;
|
|
|
|
qdf_assert_always(reportset);
|
|
|
|
reportset->headreport = NULL;
|
|
reportset->curr_report = NULL;
|
|
|
|
/* For now, we populate only one report */
|
|
report = (struct spectralsim_report *)
|
|
qdf_mem_malloc(sizeof(struct spectralsim_report));
|
|
|
|
if (!report)
|
|
goto bad;
|
|
|
|
qdf_mem_zero(report, sizeof(*report));
|
|
|
|
switch (width) {
|
|
case CH_WIDTH_20MHZ:
|
|
qdf_mem_copy(&reportset->config,
|
|
&config_20_1, sizeof(reportset->config));
|
|
|
|
ret = simctx->populate_report_static(report, CH_WIDTH_20MHZ);
|
|
if (ret != 0)
|
|
goto bad;
|
|
|
|
report->next = NULL;
|
|
reportset->headreport = report;
|
|
break;
|
|
case CH_WIDTH_40MHZ:
|
|
qdf_mem_copy(&reportset->config,
|
|
&config_40_1, sizeof(reportset->config));
|
|
|
|
ret = simctx->populate_report_static(report, CH_WIDTH_40MHZ);
|
|
if (ret != 0)
|
|
goto bad;
|
|
|
|
report->next = NULL;
|
|
reportset->headreport = report;
|
|
break;
|
|
case CH_WIDTH_80MHZ:
|
|
qdf_mem_copy(&reportset->config,
|
|
&config_80_1, sizeof(reportset->config));
|
|
|
|
ret = simctx->populate_report_static(report, CH_WIDTH_80MHZ);
|
|
if (ret != 0)
|
|
goto bad;
|
|
|
|
report->next = NULL;
|
|
reportset->headreport = report;
|
|
break;
|
|
|
|
case CH_WIDTH_80P80MHZ:
|
|
qdf_mem_copy(&reportset->config,
|
|
&config_80_80_1,
|
|
sizeof(reportset->config));
|
|
|
|
ret = simctx->populate_report_static(report,
|
|
CH_WIDTH_80P80MHZ);
|
|
if (ret != 0)
|
|
goto bad;
|
|
|
|
report->next = NULL;
|
|
reportset->headreport = report;
|
|
break;
|
|
|
|
case CH_WIDTH_160MHZ:
|
|
qdf_mem_copy(&reportset->config,
|
|
&config_160_1, sizeof(reportset->config));
|
|
|
|
ret = simctx->populate_report_static(report,
|
|
CH_WIDTH_160MHZ);
|
|
if (ret != 0)
|
|
goto bad;
|
|
|
|
report->next = NULL;
|
|
reportset->headreport = report;
|
|
break;
|
|
|
|
default:
|
|
spectral_err("Unhandled width. Please rectify.");
|
|
qdf_assert_always(0);
|
|
};
|
|
|
|
reportset->curr_report = reportset->headreport;
|
|
|
|
return 0;
|
|
|
|
bad:
|
|
target_if_depopulate_reportset(reportset);
|
|
return -EPERM;
|
|
}
|
|
|
|
/**
|
|
* target_if_depopulate_reportset() - Free all the instances of
|
|
* struct spectralsim_reportset
|
|
* @report: head pointer to struct spectralsim_reportset linked list
|
|
*
|
|
* Free all the instances of struct spectralsim_reportset
|
|
*
|
|
* Return: None
|
|
*/
|
|
static void
|
|
target_if_depopulate_reportset(
|
|
struct spectralsim_reportset *reportset)
|
|
{
|
|
struct spectralsim_report *curr_report = NULL;
|
|
struct spectralsim_report *next_report = NULL;
|
|
|
|
if (!reportset)
|
|
return;
|
|
|
|
curr_report = reportset->headreport;
|
|
|
|
while (curr_report) {
|
|
next_report = curr_report->next;
|
|
target_if_depopulate_report(curr_report);
|
|
qdf_mem_free(curr_report);
|
|
curr_report = next_report;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* target_if_populate_simdata() - Populate simulation data
|
|
* @simctx: Pointer to struct spectralsim_context
|
|
*
|
|
* Populate simulation data
|
|
*
|
|
* Return: 0 on success, negative error code on failure
|
|
*/
|
|
static int
|
|
target_if_populate_simdata(
|
|
struct spectralsim_context *simctx)
|
|
{
|
|
/*
|
|
* For now, we use static population. Switch to loading from a file if
|
|
* needed in the future.
|
|
*/
|
|
|
|
simctx->bw20_headreportset = NULL;
|
|
SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
|
|
simctx->bw20_headreportset,
|
|
CH_WIDTH_20MHZ);
|
|
|
|
simctx->bw40_headreportset = NULL;
|
|
SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
|
|
simctx->bw40_headreportset,
|
|
CH_WIDTH_40MHZ);
|
|
|
|
simctx->bw80_headreportset = NULL;
|
|
SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
|
|
simctx->bw80_headreportset,
|
|
CH_WIDTH_80MHZ);
|
|
|
|
simctx->bw160_headreportset = NULL;
|
|
SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
|
|
simctx->bw160_headreportset,
|
|
CH_WIDTH_160MHZ);
|
|
|
|
simctx->bw80_80_headreportset = NULL;
|
|
SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
|
|
simctx->bw80_80_headreportset,
|
|
CH_WIDTH_80P80MHZ);
|
|
|
|
simctx->curr_reportset = NULL;
|
|
|
|
simctx->is_enabled = false;
|
|
simctx->is_active = false;
|
|
|
|
simctx->ssim_starting_tsf64 = 0;
|
|
simctx->ssim_count = 0;
|
|
simctx->ssim_period_ms = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* target_if_depopulate_simdata() - De-populate simulation data
|
|
* @simctx: Pointer to struct spectralsim_context
|
|
*
|
|
* De-populate simulation data
|
|
*
|
|
* Return: none
|
|
*/
|
|
static void
|
|
target_if_depopulate_simdata(
|
|
struct spectralsim_context *simctx)
|
|
{
|
|
if (!simctx)
|
|
return;
|
|
|
|
SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw20_headreportset);
|
|
SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw40_headreportset);
|
|
SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_headreportset);
|
|
SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw160_headreportset);
|
|
SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_80_headreportset);
|
|
}
|
|
|
|
/**
|
|
* target_if_spectral_sim_phyerrdelivery_handler() - Phyerr delivery handler
|
|
*
|
|
* Return: none
|
|
*/
|
|
static
|
|
OS_TIMER_FUNC(target_if_spectral_sim_phyerrdelivery_handler)
|
|
{
|
|
struct target_if_spectral *spectral = NULL;
|
|
struct spectralsim_context *simctx = NULL;
|
|
struct spectralsim_reportset *curr_reportset = NULL;
|
|
struct spectralsim_report *curr_report = NULL;
|
|
struct target_if_spectral_acs_stats acs_stats;
|
|
uint64_t curr_tsf64 = 0;
|
|
struct target_if_spectral_ops *p_sops;
|
|
|
|
OS_GET_TIMER_ARG(spectral, struct target_if_spectral *);
|
|
qdf_assert_always(spectral);
|
|
|
|
p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)spectral->simctx;
|
|
qdf_assert_always(simctx);
|
|
|
|
if (!simctx->is_active)
|
|
return;
|
|
|
|
curr_reportset = simctx->curr_reportset;
|
|
qdf_assert_always(curr_reportset);
|
|
|
|
curr_report = curr_reportset->curr_report;
|
|
qdf_assert_always(curr_report);
|
|
|
|
qdf_assert_always(curr_reportset->headreport);
|
|
|
|
/*
|
|
* We use a simulation TSF since in offload architectures we can't
|
|
* expect to
|
|
* get an accurate current TSF from HW.
|
|
* In case of TSF wrap over, we'll use it as-is for now since the
|
|
* simulation
|
|
* is intended only for format verification.
|
|
*/
|
|
curr_tsf64 = simctx->ssim_starting_tsf64 +
|
|
((simctx->ssim_period_ms * simctx->ssim_count) * 1000);
|
|
|
|
p_sops->spectral_process_phyerr(spectral,
|
|
curr_report->data,
|
|
curr_report->datasize,
|
|
&curr_report->rfqual_info,
|
|
&curr_report->chan_info,
|
|
curr_tsf64, &acs_stats);
|
|
|
|
simctx->ssim_count++;
|
|
|
|
if (curr_report->next)
|
|
curr_reportset->curr_report = curr_report->next;
|
|
else
|
|
curr_reportset->curr_report = curr_reportset->headreport;
|
|
|
|
if (curr_reportset->config.ss_count != 0 &&
|
|
simctx->ssim_count == curr_reportset->config.ss_count) {
|
|
target_if_spectral_sops_sim_stop_scan(spectral);
|
|
} else {
|
|
qdf_timer_start(&simctx->ssim_pherrdelivery_timer,
|
|
simctx->ssim_period_ms);
|
|
}
|
|
}
|
|
|
|
/* Module services */
|
|
|
|
int
|
|
target_if_spectral_sim_attach(struct target_if_spectral *spectral)
|
|
{
|
|
struct spectralsim_context *simctx = NULL;
|
|
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)
|
|
qdf_mem_malloc(sizeof(struct spectralsim_context));
|
|
|
|
if (!simctx)
|
|
return -EPERM;
|
|
|
|
qdf_mem_zero(simctx, sizeof(*simctx));
|
|
|
|
spectral->simctx = simctx;
|
|
|
|
if (spectral->spectral_gen == SPECTRAL_GEN2)
|
|
simctx->populate_report_static =
|
|
target_if_populate_report_static_gen2;
|
|
else if (spectral->spectral_gen == SPECTRAL_GEN3)
|
|
simctx->populate_report_static =
|
|
target_if_populate_report_static_gen3;
|
|
|
|
if (target_if_populate_simdata(simctx) != 0) {
|
|
qdf_mem_free(simctx);
|
|
spectral->simctx = NULL;
|
|
spectral_err("Spectral simulation attach failed");
|
|
return -EPERM;
|
|
}
|
|
|
|
qdf_timer_init(NULL,
|
|
&simctx->ssim_pherrdelivery_timer,
|
|
target_if_spectral_sim_phyerrdelivery_handler,
|
|
(void *)(spectral), QDF_TIMER_TYPE_WAKE_APPS);
|
|
|
|
spectral_info("Spectral simulation attached");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
target_if_spectral_sim_detach(struct target_if_spectral *spectral)
|
|
{
|
|
struct spectralsim_context *simctx = NULL;
|
|
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)spectral->simctx;
|
|
qdf_assert_always(simctx);
|
|
|
|
qdf_timer_free(&simctx->ssim_pherrdelivery_timer);
|
|
|
|
target_if_depopulate_simdata(simctx);
|
|
qdf_mem_free(simctx);
|
|
spectral->simctx = NULL;
|
|
|
|
spectral_info("Spectral simulation detached");
|
|
}
|
|
|
|
uint32_t
|
|
target_if_spectral_sops_sim_is_active(void *arg)
|
|
{
|
|
struct target_if_spectral *spectral = NULL;
|
|
struct spectralsim_context *simctx = NULL;
|
|
|
|
spectral = (struct target_if_spectral *)arg;
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)spectral->simctx;
|
|
qdf_assert_always(simctx);
|
|
|
|
return simctx->is_active;
|
|
}
|
|
qdf_export_symbol(target_if_spectral_sops_sim_is_active);
|
|
|
|
uint32_t
|
|
target_if_spectral_sops_sim_is_enabled(void *arg)
|
|
{
|
|
struct target_if_spectral *spectral = NULL;
|
|
struct spectralsim_context *simctx = NULL;
|
|
|
|
spectral = (struct target_if_spectral *)arg;
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)spectral->simctx;
|
|
qdf_assert_always(simctx);
|
|
|
|
return simctx->is_enabled;
|
|
}
|
|
qdf_export_symbol(target_if_spectral_sops_sim_is_enabled);
|
|
|
|
uint32_t
|
|
target_if_spectral_sops_sim_start_scan(void *arg)
|
|
{
|
|
struct target_if_spectral *spectral = NULL;
|
|
struct spectralsim_context *simctx = NULL;
|
|
|
|
spectral = (struct target_if_spectral *)arg;
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)spectral->simctx;
|
|
qdf_assert_always(simctx);
|
|
|
|
if (!simctx->curr_reportset) {
|
|
spectral_err("Spectral simulation: No current report set configured - unable to start simulated Spectral scan");
|
|
return 0;
|
|
}
|
|
|
|
if (!simctx->curr_reportset->curr_report) {
|
|
spectral_err("Spectral simulation: No report data instances populated - unable to start simulated Spectral scan");
|
|
return 0;
|
|
}
|
|
|
|
if (!simctx->is_enabled)
|
|
simctx->is_enabled = true;
|
|
|
|
simctx->is_active = true;
|
|
|
|
/* Hardcoding current time as zero since it is simulation */
|
|
simctx->ssim_starting_tsf64 = 0;
|
|
simctx->ssim_count = 0;
|
|
|
|
/*
|
|
* TODO: Support high resolution timer in microseconds if required, so
|
|
* that
|
|
* we can support default periods such as ~200 us. For now, we use 1
|
|
* millisecond since the current use case for the simulation is to
|
|
* validate
|
|
* formats rather than have a time dependent classification.
|
|
*/
|
|
simctx->ssim_period_ms = 1;
|
|
|
|
qdf_timer_start(&simctx->ssim_pherrdelivery_timer,
|
|
simctx->ssim_period_ms);
|
|
|
|
return 1;
|
|
}
|
|
qdf_export_symbol(target_if_spectral_sops_sim_start_scan);
|
|
|
|
uint32_t
|
|
target_if_spectral_sops_sim_stop_scan(void *arg)
|
|
{
|
|
struct target_if_spectral *spectral = NULL;
|
|
struct spectralsim_context *simctx = NULL;
|
|
|
|
spectral = (struct target_if_spectral *)arg;
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)spectral->simctx;
|
|
qdf_assert_always(simctx);
|
|
|
|
qdf_timer_stop(&simctx->ssim_pherrdelivery_timer);
|
|
|
|
simctx->is_active = false;
|
|
simctx->is_enabled = false;
|
|
|
|
simctx->ssim_starting_tsf64 = 0;
|
|
simctx->ssim_count = 0;
|
|
simctx->ssim_period_ms = 0;
|
|
|
|
return 1;
|
|
}
|
|
qdf_export_symbol(target_if_spectral_sops_sim_stop_scan);
|
|
|
|
#ifdef SPECTRAL_SIM_DUMP_PARAM_DATA
|
|
static void
|
|
target_if_log_sim_spectral_params(struct spectral_config *params)
|
|
{
|
|
int i = 0;
|
|
|
|
spectral_debug("\n");
|
|
|
|
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",
|
|
params->ss_fft_period,
|
|
params->ss_period,
|
|
params->ss_count,
|
|
params->ss_short_report,
|
|
params->radar_bin_thresh_sel,
|
|
params->ss_spectral_pri,
|
|
params->ss_fft_size,
|
|
params->ss_gc_ena,
|
|
params->ss_restart_ena,
|
|
params->ss_noise_floor_ref,
|
|
params->ss_init_delay,
|
|
params->ss_nb_tone_thr,
|
|
params->ss_str_bin_thr,
|
|
params->ss_wb_rpt_mode,
|
|
params->ss_rssi_rpt_mode,
|
|
params->ss_rssi_thr,
|
|
params->ss_pwr_format,
|
|
params->ss_rpt_mode,
|
|
params->ss_bin_scale,
|
|
params->ss_dbm_adj,
|
|
params->ss_chn_mask, params->ss_nf_temp_data);
|
|
|
|
for (i = 0; i < AH_MAX_CHAINS * 2; i++)
|
|
spectral_debug("ss_nf_cal[%d]=%hhd", i, params->ss_nf_cal[i]);
|
|
|
|
for (i = 0; i < AH_MAX_CHAINS * 2; i++)
|
|
spectral_debug("ss_nf_pwr[%d]=%hhd", i, params->ss_nf_pwr[i]);
|
|
|
|
spectral_info("\n");
|
|
}
|
|
#else
|
|
|
|
static void
|
|
target_if_log_sim_spectral_params(struct spectral_config *params)
|
|
{
|
|
}
|
|
#endif /* SPECTRAL_SIM_DUMP_PARAM_DATA */
|
|
|
|
uint32_t
|
|
target_if_spectral_sops_sim_configure_params(
|
|
void *arg,
|
|
struct spectral_config *params)
|
|
{
|
|
struct target_if_spectral *spectral = NULL;
|
|
struct spectralsim_context *simctx = NULL;
|
|
enum wlan_phymode phymode;
|
|
uint8_t bw;
|
|
struct spectralsim_reportset *des_headreportset = NULL;
|
|
struct spectralsim_reportset *temp_reportset = NULL;
|
|
bool is_invalid_width = false;
|
|
struct wlan_objmgr_vdev *vdev = NULL;
|
|
|
|
qdf_assert_always(params);
|
|
target_if_log_sim_spectral_params(params);
|
|
spectral = (struct target_if_spectral *)arg;
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)spectral->simctx;
|
|
qdf_assert_always(simctx);
|
|
|
|
vdev = target_if_spectral_get_vdev(spectral);
|
|
if (!vdev) {
|
|
spectral_warn("Spectral simulation: No VAPs found - not proceeding with param config.");
|
|
return 0;
|
|
}
|
|
|
|
bw = target_if_vdev_get_ch_width(vdev);
|
|
|
|
switch (bw) {
|
|
case CH_WIDTH_20MHZ:
|
|
des_headreportset = simctx->bw20_headreportset;
|
|
break;
|
|
case CH_WIDTH_40MHZ:
|
|
des_headreportset = simctx->bw40_headreportset;
|
|
break;
|
|
case CH_WIDTH_80MHZ:
|
|
des_headreportset = simctx->bw80_headreportset;
|
|
break;
|
|
case CH_WIDTH_160MHZ:
|
|
des_headreportset = simctx->bw160_headreportset;
|
|
break;
|
|
case CH_WIDTH_80P80MHZ:
|
|
des_headreportset = simctx->bw80_80_headreportset;
|
|
break;
|
|
case CH_WIDTH_INVALID:
|
|
spectral_err("Spectral simulation: Invalid width configured - not proceeding with param config.");
|
|
is_invalid_width = true;
|
|
default:
|
|
spectral_err("Spectral simulation: Unknown width %u...asserting",
|
|
bw);
|
|
qdf_assert_always(0);
|
|
break;
|
|
}
|
|
|
|
wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
|
|
|
|
if (is_invalid_width)
|
|
return 0;
|
|
|
|
if (!des_headreportset) {
|
|
spectral_warn("Spectral simulation: No simulation data present for configured bandwidth/PHY mode - unable to proceed with param config.");
|
|
return 0;
|
|
}
|
|
|
|
simctx->curr_reportset = NULL;
|
|
temp_reportset = des_headreportset;
|
|
|
|
while (temp_reportset) {
|
|
if (qdf_mem_cmp(&temp_reportset->config,
|
|
params, sizeof(struct spectral_config)) == 0) {
|
|
/* Found a matching config. We are done. */
|
|
simctx->curr_reportset = temp_reportset;
|
|
break;
|
|
}
|
|
|
|
temp_reportset = temp_reportset->next;
|
|
}
|
|
|
|
if (!simctx->curr_reportset) {
|
|
spectral_warn("Spectral simulation: No simulation data present for desired Spectral configuration - unable to proceed with param config.");
|
|
return 0;
|
|
}
|
|
|
|
if (!simctx->curr_reportset->curr_report) {
|
|
spectral_warn("Spectral simulation: No report data instances populated for desired Spectral configuration - unable to proceed with param config");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
qdf_export_symbol(target_if_spectral_sops_sim_configure_params);
|
|
|
|
uint32_t
|
|
target_if_spectral_sops_sim_get_params(
|
|
void *arg, struct spectral_config *params)
|
|
{
|
|
struct target_if_spectral *spectral = NULL;
|
|
struct spectralsim_context *simctx = NULL;
|
|
|
|
qdf_assert_always(params);
|
|
|
|
spectral = (struct target_if_spectral *)arg;
|
|
qdf_assert_always(spectral);
|
|
|
|
simctx = (struct spectralsim_context *)spectral->simctx;
|
|
qdf_assert_always(simctx);
|
|
|
|
if (!simctx->curr_reportset) {
|
|
spectral_warn("Spectral simulation: No configured reportset found.");
|
|
return 0;
|
|
}
|
|
|
|
qdf_mem_copy(params, &simctx->curr_reportset->config, sizeof(*params));
|
|
|
|
return 1;
|
|
}
|
|
qdf_export_symbol(target_if_spectral_sops_sim_get_params);
|
|
|
|
#endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */
|