From f3cc90e23655adf4273f90d58e7725f7d8da6f28 Mon Sep 17 00:00:00 2001 From: Edayilliam Jayadev Date: Wed, 13 Nov 2019 12:05:21 +0530 Subject: [PATCH] qcacmn: Check aSpectral capability for current chainmask Reject Agile Spectral scan request if the current chainmask doesn't have Agile capability. CRs-Fixed: 2565027 Change-Id: I0ac79f9846ef015ec16500ae29528c8e5d03da3e --- target_if/spectral/target_if_spectral.c | 146 ++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/target_if/spectral/target_if_spectral.c b/target_if/spectral/target_if_spectral.c index 63cd5443bcaf..2c7d3f012642 100644 --- a/target_if/spectral/target_if_spectral.c +++ b/target_if/spectral/target_if_spectral.c @@ -3318,6 +3318,134 @@ target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc, *is_agile_scan_inprog_5g_pdev = true; } +/** + * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported + * for current vdev rx chainmask. + * + * @spectral: Pointer to Spectral object + * @is_supported: Pointer to is_supported + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure + */ +static QDF_STATUS +target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral, + bool *is_supported) +{ + struct wlan_objmgr_vdev *vdev; + uint8_t vdev_rxchainmask; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + struct target_psoc_info *tgt_psoc_info; + struct wlan_psoc_host_service_ext_param *ext_svc_param; + struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; + struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; + struct wlan_psoc_host_chainmask_table *table; + int j; + uint32_t table_id; + enum phy_ch_width ch_width; + uint8_t pdev_id; + + if (!spectral) { + spectral_err("spectral target if object is null"); + return QDF_STATUS_E_FAILURE; + } + + if (!is_supported) { + spectral_err("is supported argument is null"); + return QDF_STATUS_E_FAILURE; + } + + if (spectral->spectral_gen <= SPECTRAL_GEN2) { + spectral_err("HW Agile mode is not supported up to gen 2"); + return QDF_STATUS_E_FAILURE; + } + + pdev = spectral->pdev_obj; + if (!pdev) { + spectral_err("pdev is null"); + return QDF_STATUS_E_FAILURE; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + spectral_err("psoc is null"); + return QDF_STATUS_E_FAILURE; + } + + vdev = target_if_spectral_get_vdev(spectral); + if (!vdev) { + spectral_err("First vdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + + vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); + if (!vdev_rxchainmask) { + spectral_err("vdev rx chainmask is zero"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + return QDF_STATUS_E_FAILURE; + } + + ch_width = target_if_vdev_get_ch_width(vdev); + if (ch_width == CH_WIDTH_INVALID) { + spectral_err("Invalid channel width"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + return QDF_STATUS_E_FAILURE; + } + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + + tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_psoc_info) { + spectral_err("target_psoc_info is null"); + return QDF_STATUS_E_FAILURE; + } + + ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); + if (!ext_svc_param) { + spectral_err("Extended service ready param null"); + return QDF_STATUS_E_FAILURE; + } + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); + if (!mac_phy_cap_arr) { + spectral_err("mac phy cap array is null"); + return QDF_STATUS_E_FAILURE; + } + + mac_phy_cap = &mac_phy_cap_arr[pdev_id]; + if (!mac_phy_cap) { + spectral_err("mac phy cap is null"); + return QDF_STATUS_E_FAILURE; + } + + table_id = mac_phy_cap->chainmask_table_id; + table = &ext_svc_param->chainmask_table[table_id]; + if (!table) { + spectral_err("chainmask table not found"); + return QDF_STATUS_E_FAILURE; + } + + for (j = 0; j < table->num_valid_chainmasks; j++) { + if (table->cap_list[j].chainmask == vdev_rxchainmask) { + if (ch_width <= CH_WIDTH_80MHZ) + *is_supported = + table->cap_list[j].supports_aSpectral; + else + *is_supported = + table->cap_list[j].supports_aSpectral_160; + break; + } + } + + if (j == table->num_valid_chainmasks) { + spectral_err("vdev rx chainmask %u not found in table id = %u", + vdev_rxchainmask, table_id); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, const enum spectral_scan_mode smode, @@ -3358,6 +3486,24 @@ target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (smode == SPECTRAL_SCAN_MODE_AGILE) { + QDF_STATUS status; + bool is_supported = false; + + status = target_if_is_agile_supported_cur_chmask(spectral, + &is_supported); + if (QDF_IS_STATUS_ERROR(status)) { + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + + if (!is_supported) { + spectral_err("aSpectral unsupported for cur chainmask"); + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + } + band = target_if_get_curr_band(spectral->pdev_obj); if (band == BAND_UNKNOWN) { spectral_err("Failed to get current band");