diff --git a/target_if/spectral/target_if_spectral.c b/target_if/spectral/target_if_spectral.c index f209288bfddd..3e1b364a5074 100644 --- a/target_if/spectral/target_if_spectral.c +++ b/target_if/spectral/target_if_spectral.c @@ -3612,6 +3612,115 @@ target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } +/** + * target_if_spectral_get_num_detectors() - Get number of Spectral detectors + * @spectral: Pointer to target if Spectral object + * @ch_width: channel width + * @num_detectors: Pointer to the variable to store number of Spectral detectors + * + * API to get number of Spectral detectors used for scan in the given channel + * width. + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure + */ +static QDF_STATUS +target_if_spectral_get_num_detectors(struct target_if_spectral *spectral, + enum phy_ch_width ch_width, + uint32_t *num_detectors) +{ + if (!spectral) { + spectral_err("target if spectral object is null"); + return QDF_STATUS_E_INVAL; + } + + if (ch_width >= CH_WIDTH_INVALID) { + spectral_err("Invalid channel width %d", ch_width); + return QDF_STATUS_E_INVAL; + } + + if (!num_detectors) { + spectral_err("Invalid argument, number of detectors"); + return QDF_STATUS_E_INVAL; + } + + switch (ch_width) { + case CH_WIDTH_20MHZ: + *num_detectors = spectral->capability.num_detectors_20mhz; + break; + + case CH_WIDTH_40MHZ: + *num_detectors = spectral->capability.num_detectors_40mhz; + break; + + case CH_WIDTH_80MHZ: + *num_detectors = spectral->capability.num_detectors_80mhz; + break; + + case CH_WIDTH_160MHZ: + *num_detectors = spectral->capability.num_detectors_160mhz; + break; + + case CH_WIDTH_80P80MHZ: + *num_detectors = spectral->capability.num_detectors_80p80mhz; + break; + + default: + spectral_err("Unsupported channel width %d", ch_width); + return QDF_STATUS_E_INVAL; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_spectral_finite_scan_init() - Initializations required for finite + * Spectral scan + * @spectral: Pointer to target of Spctral object + * @smode: Spectral scan mode + * + * This routine initializes the finite Spectral scan. Finite Spectral scan is + * triggered by configuring a non zero scan count. + * + * Return: QDF_STATUS_SUCCESS on success + */ +static QDF_STATUS +target_if_spectral_finite_scan_init(struct target_if_spectral *spectral, + enum spectral_scan_mode smode) +{ + struct target_if_finite_spectral_scan_params *finite_scan; + enum phy_ch_width ch_width; + uint32_t num_detectors; + QDF_STATUS status; + uint16_t sscan_count; + + if (!spectral) { + spectral_err("target if spectral object is null"); + return QDF_STATUS_E_INVAL; + } + + if (smode >= SPECTRAL_SCAN_MODE_MAX) { + spectral_err("Invalid Spectral mode"); + return QDF_STATUS_E_INVAL; + } + + ch_width = spectral->ch_width[smode]; + status = target_if_spectral_get_num_detectors(spectral, ch_width, + &num_detectors); + + if (QDF_IS_STATUS_ERROR(status)) { + spectral_err("Failed to get number of detectors"); + return QDF_STATUS_E_FAILURE; + } + + finite_scan = &spectral->finite_scan[smode]; + sscan_count = spectral->params[smode].ss_count; + + finite_scan->finite_spectral_scan = true; + finite_scan->num_reports_expected = num_detectors * sscan_count; + + return QDF_STATUS_SUCCESS; +} + /** * target_if_spectral_scan_enable_params() - Enable use of desired Spectral * parameters @@ -3922,6 +4031,15 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, if (!p_sops->is_spectral_active(spectral, smode)) { p_sops->configure_spectral(spectral, spectral_params, smode); spectral->rparams.marker[smode].is_valid = false; + + if (spectral->params[smode].ss_count) { + status = target_if_spectral_finite_scan_init(spectral, + smode); + if (QDF_IS_STATUS_ERROR(status)) { + spectral_err("Failed to init finite scan"); + return 1; + } + } p_sops->start_spectral_scan(spectral, smode, err); spectral->timestamp_war.timestamp_war_offset[smode] = 0; spectral->timestamp_war.last_fft_timestamp[smode] = 0; @@ -5633,3 +5751,72 @@ target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, } } qdf_export_symbol(target_if_spectral_send_intf_found_msg); + +QDF_STATUS +target_if_spectral_is_finite_scan(struct target_if_spectral *spectral, + enum spectral_scan_mode smode, + bool *finite_spectral_scan) +{ + struct target_if_finite_spectral_scan_params *finite_scan; + + if (!spectral) { + spectral_err_rl("target if spectral object is null"); + return QDF_STATUS_E_INVAL; + } + + if (smode >= SPECTRAL_SCAN_MODE_MAX) { + spectral_err_rl("invalid spectral mode %d", smode); + return QDF_STATUS_E_INVAL; + } + + if (!finite_spectral_scan) { + spectral_err_rl("Invalid pointer"); + return QDF_STATUS_E_INVAL; + } + + finite_scan = &spectral->finite_scan[smode]; + *finite_spectral_scan = finite_scan->finite_spectral_scan; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +target_if_spectral_finite_scan_update(struct target_if_spectral *spectral, + enum spectral_scan_mode smode) +{ + struct target_if_finite_spectral_scan_params *finite_scan; + + if (!spectral) { + spectral_err_rl("target if spectral object is null"); + return QDF_STATUS_E_INVAL; + } + + if (smode >= SPECTRAL_SCAN_MODE_MAX) { + spectral_err_rl("Invalid Spectral mode"); + return QDF_STATUS_E_INVAL; + } + + finite_scan = &spectral->finite_scan[smode]; + + if (!finite_scan->num_reports_expected) { + spectral_err_rl("Error, No reports expected"); + return QDF_STATUS_E_FAILURE; + } + + finite_scan->num_reports_expected--; + if (!finite_scan->num_reports_expected) { + QDF_STATUS status; + enum spectral_cp_error_code err; + + /* received expected number of reports from target, stop scan */ + status = target_if_stop_spectral_scan(spectral->pdev_obj, smode, + &err); + if (QDF_IS_STATUS_ERROR(status)) { + spectral_err_rl("Failed to stop finite Spectral scan"); + return QDF_STATUS_E_FAILURE; + } + finite_scan->finite_spectral_scan = false; + } + + return QDF_STATUS_SUCCESS; +} diff --git a/target_if/spectral/target_if_spectral.h b/target_if/spectral/target_if_spectral.h index 10b06a566a03..bcd8a6b1b0dd 100644 --- a/target_if/spectral/target_if_spectral.h +++ b/target_if/spectral/target_if_spectral.h @@ -881,6 +881,18 @@ struct spectral_param_properties { bool common_all_modes; }; +/** + * struct target_if_finite_spectral_scan_params - Parameters related to finite + * Spectral scan + * @finite_spectral_scan: Indicates the Spectrl scan is finite/infinite + * @num_reports_expected: Number of Spectral reports expected from target for a + * finite Spectral scan + */ +struct target_if_finite_spectral_scan_params { + bool finite_spectral_scan; + uint32_t num_reports_expected; +}; + /** * struct target_if_spectral - main spectral structure * @pdev: Pointer to pdev @@ -975,6 +987,7 @@ struct spectral_param_properties { * compared with the current tstamp to check descrepancy * @rparams: Parameters related to Spectral report structure * @param_min_max: Spectral parameter's minimum and maximum values + * @finite_scan: Parameters for finite Spectral scan */ struct target_if_spectral { struct wlan_objmgr_pdev *pdev_obj; @@ -1090,6 +1103,8 @@ struct target_if_spectral { uint32_t prev_tstamp; struct spectral_report_params rparams; struct spectral_param_min_max param_min_max; + struct target_if_finite_spectral_scan_params + finite_scan[SPECTRAL_SCAN_MODE_MAX]; }; /** @@ -2275,6 +2290,38 @@ target_if_consume_spectral_report_gen3( */ QDF_STATUS target_if_spectral_fw_hang(struct target_if_spectral *spectral); +/** + * target_if_spectral_finite_scan_update() - Update scan count for finite scan + * and stop Spectral scan when required + * @spectral: Pointer to Spectral target_if internal private data + * @smode: Spectral scan mode + * + * This API decrements the number of Spectral reports expected from target for + * a finite Spectral scan. When expected number of reports are received from + * target Spectral scan is stopped. + * + * Return: QDF_STATUS on success + */ +QDF_STATUS +target_if_spectral_finite_scan_update(struct target_if_spectral *spectral, + enum spectral_scan_mode smode); + +/** + * target_if_spectral_is_finite_scan() - Check Spectral scan is finite/infinite + * @spectral: Pointer to Spectral target_if internal private data + * @smode: Spectral scan mode + * + * API to check whether Spectral scan is finite/infinite for the give mode. + * A non zero scan count indicates that scan is finite. Scan count of 0 + * indicates an infinite Spectral scan. + * + * Return: QDF_STATUS on success + */ +QDF_STATUS +target_if_spectral_is_finite_scan(struct target_if_spectral *spectral, + enum spectral_scan_mode smode, + bool *finite_spectral_scan); + #ifdef WIN32 #pragma pack(pop, target_if_spectral) #endif diff --git a/target_if/spectral/target_if_spectral_phyerr.c b/target_if/spectral/target_if_spectral_phyerr.c index a7416d77a860..96332a574b59 100644 --- a/target_if/spectral/target_if_spectral_phyerr.c +++ b/target_if/spectral/target_if_spectral_phyerr.c @@ -1858,6 +1858,7 @@ target_if_consume_spectral_report_gen3( QDF_STATUS ret; enum spectral_scan_mode spectral_mode = SPECTRAL_SCAN_MODE_INVALID; uint8_t *temp; + bool finite_scan = false; /* Process Spectral scan summary report */ if (target_if_verify_sig_and_tag_gen3( @@ -1883,6 +1884,26 @@ target_if_consume_spectral_report_gen3( goto fail; } + /* Drop the sample if Spectral is not active for the current mode */ + if (!p_sops->is_spectral_active(spectral, spectral_mode)) + return -EINVAL; + + ret = target_if_spectral_is_finite_scan(spectral, spectral_mode, + &finite_scan); + if (QDF_IS_STATUS_ERROR(ret)) { + spectral_err_rl("Failed to check scan is finite"); + goto fail; + } + + if (finite_scan) { + ret = target_if_spectral_finite_scan_update(spectral, + spectral_mode); + if (QDF_IS_STATUS_ERROR(ret)) { + spectral_err_rl("Failed to update scan count"); + goto fail; + } + } + target_if_consume_sscan_summary_report_gen3(data, &sscan_report_fields, &spectral->rparams); /* Advance buf pointer to the search fft report */