diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 73cd1b5f26d1..c81938bc72ba 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -834,6 +834,20 @@ struct wlan_mlme_he_caps { }; #endif +/** + * struct wlan_mlme_chain_cfg - Chain info related structure + * @max_tx_chains_2g: max tx chains supported in 2.4ghz band + * @max_rx_chains_2g: max rx chains supported in 2.4ghz band + * @max_tx_chains_5g: max tx chains supported in 5ghz band + * @max_rx_chains_5g: max rx chains supported in 5ghz band + */ +struct wlan_mlme_chain_cfg { + uint8_t max_tx_chains_2g; + uint8_t max_rx_chains_2g; + uint8_t max_tx_chains_5g; + uint8_t max_rx_chains_5g; +}; + /** * struct wlan_mlme_rates - RATES related config items * @cfpPeriod: cfp period info diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index b13f5d746ad5..150d3feec551 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1848,7 +1848,6 @@ struct hdd_context { enum sar_version sar_version; struct hdd_dynamic_mac dynamic_mac_list[QDF_MAX_CONCURRENCY_PERSONA]; bool dynamic_nss_chains_support; - struct qdf_mac_addr hw_macaddr; struct qdf_mac_addr provisioned_mac_addr[QDF_MAX_CONCURRENCY_PERSONA]; struct qdf_mac_addr derived_mac_addr[QDF_MAX_CONCURRENCY_PERSONA]; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index e6304569e8fa..9cd4653e2552 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -1511,6 +1511,7 @@ hdd_set_nss_params(struct hdd_adapter *adapter, return QDF_STATUS_SUCCESS; } + /** * hdd_update_nss() - Update the number of spatial streams supported. * Ensure that nss is either 1 or 2 before calling this. @@ -1585,8 +1586,8 @@ QDF_STATUS hdd_update_nss(struct hdd_adapter *adapter, uint8_t nss) for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++) { /* This API will change the global ini in mlme cfg */ - sme_update_vdev_nss(mac_handle, rx_nss, tx_nss, - adapter->device_mode, band); + sme_update_nss_in_mlme_cfg(mac_handle, rx_nss, tx_nss, + adapter->device_mode, band); /* * This API will change the vdev nss params in mac * context diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6d54dcc77b1d..a666140c3926 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1801,6 +1801,7 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg) bool bval = false; uint8_t value = 0; uint32_t fine_time_meas_cap = 0; + enum nss_chains_band_info band; if (!hdd_ctx) { hdd_err("HDD context is NULL"); @@ -1944,6 +1945,22 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg) } hdd_update_tgt_twt_cap(hdd_ctx, cfg); + for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++) { + sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle, + QDF_STA_MODE, band); + sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle, + QDF_SAP_MODE, band); + sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle, + QDF_TDLS_MODE, band); + sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle, + QDF_P2P_DEVICE_MODE, + band); + sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle, + QDF_OCB_MODE, band); + sme_modify_nss_chains_tgt_cfg(hdd_ctx->mac_handle, + QDF_TDLS_MODE, band); + } + hdd_update_vdev_nss(hdd_ctx); hdd_ctx->dynamic_nss_chains_support = diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 5de7cac5d0b0..0e1f719fa7b6 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -755,7 +755,7 @@ struct mgmt_beacon_probe_filter { */ struct mac_context { enum qdf_driver_type gDriverType; - + struct wlan_mlme_chain_cfg fw_chain_cfg; tAniSirCfg cfg; struct wlan_mlme_cfg *mlme_cfg; tAniSirLim lim; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 69f5e96aaa76..a0295c69fa35 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -360,7 +360,25 @@ sme_store_nss_chains_cfg_in_vdev(struct wlan_objmgr_vdev *vdev, struct wlan_mlme_nss_chains *vdev_ini_cfg); /** - * sme_update_vdev_nss() - Change the nss in ini(rx_nss_(band)) for + * sme_modify_nss_chains_tgt_cfg() - Change the nss in ini for + * particular opmode, and band, according to the chain config supported by FW. + * @mac_handle: The handle returned by mac_open. + * @vdev_op_mode: vdev operation mode. + * @band:- band for which user wants to change nss. + * + * This API will change the nss in ini (for eg. rx_nss_2g) in the mlme cfg i.e + * the global config structure kept in mac context, according to the max + * supported chains per band which is got as part of ext service ready event. + * + * Return: none + */ +void +sme_modify_nss_chains_tgt_cfg(mac_handle_t mac_handle, + enum QDF_OPMODE vdev_op_mode, + enum nss_chains_band_info band); + +/** + * sme_update_nss_in_mlme_cfg() - Change the nss in ini(rx_nss_(band)) for * particular opmode, and band. * @mac_handle: The handle returned by mac_open. * @rx_nss: new value of rx nss that user wants to change. @@ -374,10 +392,10 @@ sme_store_nss_chains_cfg_in_vdev(struct wlan_objmgr_vdev *vdev, * Return: none */ void -sme_update_vdev_nss(mac_handle_t mac_handle, - uint8_t rx_nss, uint8_t tx_nss, - enum QDF_OPMODE vdev_op_mode, - enum nss_chains_band_info band); +sme_update_nss_in_mlme_cfg(mac_handle_t mac_handle, + uint8_t rx_nss, uint8_t tx_nss, + enum QDF_OPMODE vdev_op_mode, + enum nss_chains_band_info band); /** * sme_nss_chains_update() - validate and send the user params to fw diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 137ab08574df..a8a3ee29c4ba 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -4321,11 +4321,36 @@ sme_validate_nss_chains_config(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } -static void -sme_change_vdev_nss_ini(mac_handle_t mac_handle, - uint8_t rx_nss, uint8_t tx_nss, - enum QDF_OPMODE vdev_op_mode, - enum nss_chains_band_info band) +static bool +sme_is_nss_update_allowed(struct wlan_mlme_chain_cfg chain_cfg, + uint8_t rx_nss, uint8_t tx_nss, + enum nss_chains_band_info band) +{ + switch (band) { + case NSS_CHAINS_BAND_2GHZ: + if (rx_nss > chain_cfg.max_rx_chains_2g) + return false; + if (tx_nss > chain_cfg.max_tx_chains_2g) + return false; + break; + case NSS_CHAINS_BAND_5GHZ: + if (rx_nss > chain_cfg.max_rx_chains_5g) + return false; + if (tx_nss > chain_cfg.max_tx_chains_5g) + return false; + break; + default: + sme_err("Unknown Band nss change not allowed"); + return false; + } + return true; +} + +static void sme_modify_chains_in_mlme_cfg(mac_handle_t mac_handle, + uint8_t rx_chains, + uint8_t tx_chains, + enum QDF_OPMODE vdev_op_mode, + enum nss_chains_band_info band) { uint8_t nss_shift; uint32_t nss_mask = 0x7; @@ -4333,6 +4358,37 @@ sme_change_vdev_nss_ini(mac_handle_t mac_handle, nss_shift = sme_get_nss_chain_shift(vdev_op_mode); + mac_ctx->mlme_cfg->nss_chains_ini_cfg.num_rx_chains[band] &= + ~(nss_mask << nss_shift); + mac_ctx->mlme_cfg->nss_chains_ini_cfg.num_rx_chains[band] |= + (rx_chains << nss_shift); + mac_ctx->mlme_cfg->nss_chains_ini_cfg.num_tx_chains[band] &= + ~(nss_mask << nss_shift); + mac_ctx->mlme_cfg->nss_chains_ini_cfg.num_tx_chains[band] |= + (tx_chains << nss_shift); + sme_debug("rx chains %d tx chains %d changed for vdev mode %d for band %d", + rx_chains, tx_chains, vdev_op_mode, band); +} + +static void +sme_modify_nss_in_mlme_cfg(mac_handle_t mac_handle, + uint8_t rx_nss, uint8_t tx_nss, + enum QDF_OPMODE vdev_op_mode, + enum nss_chains_band_info band) +{ + uint8_t nss_shift; + uint32_t nss_mask = 0x7; + struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle); + + if (!sme_is_nss_update_allowed(mac_ctx->fw_chain_cfg, rx_nss, tx_nss, + band)) { + sme_debug("Nss modification failed, fw doesn't support this nss %d", + rx_nss); + return; + } + + nss_shift = sme_get_nss_chain_shift(vdev_op_mode); + mac_ctx->mlme_cfg->nss_chains_ini_cfg.rx_nss[band] &= ~(nss_mask << nss_shift); mac_ctx->mlme_cfg->nss_chains_ini_cfg.rx_nss[band] |= @@ -4346,10 +4402,73 @@ sme_change_vdev_nss_ini(mac_handle_t mac_handle, } void -sme_update_vdev_nss(mac_handle_t mac_handle, - uint8_t rx_nss, uint8_t tx_nss, - enum QDF_OPMODE vdev_op_mode, - enum nss_chains_band_info band) +sme_modify_nss_chains_tgt_cfg(mac_handle_t mac_handle, + enum QDF_OPMODE vdev_op_mode, + enum nss_chains_band_info band) +{ + uint8_t ini_rx_nss; + uint8_t ini_tx_nss; + uint8_t max_supported_rx_nss = MAX_VDEV_NSS; + uint8_t max_supported_tx_nss = MAX_VDEV_NSS; + uint8_t ini_rx_chains; + uint8_t ini_tx_chains; + uint8_t max_supported_rx_chains = MAX_VDEV_CHAINS; + uint8_t max_supported_tx_chains = MAX_VDEV_CHAINS; + + struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle); + struct wlan_mlme_nss_chains *nss_chains_ini_cfg = + &mac_ctx->mlme_cfg->nss_chains_ini_cfg; + uint8_t nss_shift = sme_get_nss_chain_shift(vdev_op_mode); + struct wlan_mlme_chain_cfg chain_cfg = mac_ctx->fw_chain_cfg; + + ini_rx_nss = GET_VDEV_NSS_CHAIN(nss_chains_ini_cfg->rx_nss[band], + nss_shift); + ini_tx_nss = GET_VDEV_NSS_CHAIN(nss_chains_ini_cfg->tx_nss[band], + nss_shift); + + if (band == NSS_CHAINS_BAND_2GHZ) { + max_supported_rx_nss = chain_cfg.max_rx_chains_2g; + max_supported_tx_nss = chain_cfg.max_tx_chains_2g; + } else if (band == NSS_CHAINS_BAND_5GHZ) { + max_supported_rx_nss = chain_cfg.max_rx_chains_5g; + max_supported_tx_nss = chain_cfg.max_tx_chains_5g; + } + + max_supported_rx_nss = QDF_MIN(ini_rx_nss, max_supported_rx_nss); + max_supported_tx_nss = QDF_MIN(ini_tx_nss, max_supported_tx_nss); + + ini_rx_chains = GET_VDEV_NSS_CHAIN(nss_chains_ini_cfg-> + num_rx_chains[band], + nss_shift); + ini_tx_chains = GET_VDEV_NSS_CHAIN(nss_chains_ini_cfg-> + num_tx_chains[band], + nss_shift); + + if (band == NSS_CHAINS_BAND_2GHZ) { + max_supported_rx_chains = chain_cfg.max_rx_chains_2g; + max_supported_tx_chains = chain_cfg.max_tx_chains_2g; + } else if (band == NSS_CHAINS_BAND_5GHZ) { + max_supported_rx_chains = chain_cfg.max_rx_chains_5g; + max_supported_tx_chains = chain_cfg.max_tx_chains_5g; + } + + max_supported_rx_chains = QDF_MIN(ini_rx_chains, + max_supported_rx_chains); + max_supported_tx_chains = QDF_MIN(ini_tx_chains, + max_supported_tx_chains); + + sme_modify_chains_in_mlme_cfg(mac_handle, max_supported_rx_chains, + max_supported_tx_chains, vdev_op_mode, + band); + sme_modify_nss_in_mlme_cfg(mac_handle, max_supported_rx_nss, + max_supported_tx_nss, vdev_op_mode, band); +} + +void +sme_update_nss_in_mlme_cfg(mac_handle_t mac_handle, + uint8_t rx_nss, uint8_t tx_nss, + enum QDF_OPMODE vdev_op_mode, + enum nss_chains_band_info band) { /* * If device mode is P2P-DEVICE, then we want P2P to come in that @@ -4361,15 +4480,15 @@ sme_update_vdev_nss(mac_handle_t mac_handle, if (vdev_op_mode == QDF_P2P_DEVICE_MODE || vdev_op_mode == QDF_P2P_CLIENT_MODE || vdev_op_mode == QDF_P2P_GO_MODE) { - sme_change_vdev_nss_ini(mac_handle, rx_nss, tx_nss, - QDF_P2P_CLIENT_MODE, band); - sme_change_vdev_nss_ini(mac_handle, rx_nss, tx_nss, - QDF_P2P_GO_MODE, band); - sme_change_vdev_nss_ini(mac_handle, rx_nss, tx_nss, - QDF_P2P_DEVICE_MODE, band); + sme_modify_nss_in_mlme_cfg(mac_handle, rx_nss, tx_nss, + QDF_P2P_CLIENT_MODE, band); + sme_modify_nss_in_mlme_cfg(mac_handle, rx_nss, tx_nss, + QDF_P2P_GO_MODE, band); + sme_modify_nss_in_mlme_cfg(mac_handle, rx_nss, tx_nss, + QDF_P2P_DEVICE_MODE, band); } else - sme_change_vdev_nss_ini(mac_handle, rx_nss, tx_nss, - vdev_op_mode, band); + sme_modify_nss_in_mlme_cfg(mac_handle, rx_nss, tx_nss, + vdev_op_mode, band); } QDF_STATUS diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 20e0bd125d93..6b5e9a9fbf6f 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -5555,6 +5555,59 @@ static void wma_update_nan_target_caps(tp_wma_handle wma_handle, } #endif +static uint8_t +wma_convert_chainmask_to_chain(uint8_t chainmask) +{ + uint8_t num_chains = 0; + + while (chainmask) { + chainmask &= (chainmask - 1); + num_chains++; + } + + return num_chains; +} + +static void +wma_fill_chain_cfg(struct target_psoc_info *tgt_hdl, + uint8_t phy) +{ + struct mac_context *mac_ctx; + uint8_t num_chain; + struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = + tgt_hdl->info.mac_phy_cap; + + mac_ctx = cds_get_context(QDF_MODULE_ID_PE); + if (!mac_ctx) { + WMA_LOGE("fill chain cfg failed as mac_ctx is NULL"); + return; + } + + num_chain = wma_convert_chainmask_to_chain(mac_phy_cap[phy]. + tx_chain_mask_2G); + + if (num_chain > mac_ctx->fw_chain_cfg.max_tx_chains_2g) + mac_ctx->fw_chain_cfg.max_tx_chains_2g = num_chain; + + num_chain = wma_convert_chainmask_to_chain(mac_phy_cap[phy]. + tx_chain_mask_5G); + + if (num_chain > mac_ctx->fw_chain_cfg.max_tx_chains_5g) + mac_ctx->fw_chain_cfg.max_tx_chains_5g = num_chain; + + num_chain = wma_convert_chainmask_to_chain(mac_phy_cap[phy]. + rx_chain_mask_2G); + + if (num_chain > mac_ctx->fw_chain_cfg.max_rx_chains_2g) + mac_ctx->fw_chain_cfg.max_rx_chains_2g = num_chain; + + num_chain = wma_convert_chainmask_to_chain(mac_phy_cap[phy]. + rx_chain_mask_5G); + + if (num_chain > mac_ctx->fw_chain_cfg.max_rx_chains_5g) + mac_ctx->fw_chain_cfg.max_rx_chains_5g = num_chain; +} + /** * wma_update_hdd_cfg() - update HDD config * @wma_handle: wma handle @@ -5569,6 +5622,7 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) struct wlan_psoc_host_service_ext_param *service_ext_param; struct target_psoc_info *tgt_hdl; struct wmi_unified *wmi_handle; + uint8_t i; WMA_LOGD("%s: Enter", __func__); @@ -5648,6 +5702,11 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) wma_update_obss_color_collision_support(wma_handle, &tgt_cfg); wma_update_hdd_cfg_ndp(wma_handle, &tgt_cfg); wma_update_nan_target_caps(wma_handle, &tgt_cfg); + + /* Take the max of chains supported by FW, which will limit nss */ + for (i = 0; i < tgt_hdl->info.total_mac_phy_cnt; i++) + wma_fill_chain_cfg(tgt_hdl, i); + wma_handle->tgt_cfg_update_cb(hdd_ctx, &tgt_cfg); target_if_store_pdev_target_if_ctx(wma_get_pdev_from_scn_handle); target_pdev_set_wmi_handle(wma_handle->pdev->tgt_if_handle,