diff --git a/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h b/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h index 9e87327e0ce7..49a6c24aee2a 100644 --- a/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h +++ b/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h @@ -46,6 +46,8 @@ enum vdev_assoc_type { * @vdev_start_failed: flag to indicate that vdev start failed. * @connection_fail: flag to indicate connection failed * @assoc_type: vdev associate/reassociate type + * @dynamic_cfg: current configuration of nss, chains for vdev. + * @ini_cfg: Max configuration of nss, chains supported for vdev. */ struct mlme_legacy_priv { bool chan_switch_in_progress; @@ -53,6 +55,8 @@ struct mlme_legacy_priv { bool vdev_start_failed; bool connection_fail; enum vdev_assoc_type assoc_type; + struct wlan_mlme_nss_chains dynamic_cfg; + struct wlan_mlme_nss_chains ini_cfg; }; /** @@ -141,6 +145,24 @@ bool mlme_is_connection_fail(struct wlan_objmgr_vdev *vdev); QDF_STATUS mlme_set_connection_fail(struct wlan_objmgr_vdev *vdev, bool val); +/** + * mlme_get_dynamic_vdev_config() - get the vdev dynamic config params + * @vdev: vdev pointer + * + * Return: pointer to the dynamic vdev config structure + */ +struct wlan_mlme_nss_chains *mlme_get_dynamic_vdev_config( + struct wlan_objmgr_vdev *vdev); + +/** + * mlme_get_ini_vdev_config() - get the vdev ini config params + * @vdev: vdev pointer + * + * Return: pointer to the ini vdev config structure + */ +struct wlan_mlme_nss_chains *mlme_get_ini_vdev_config( + struct wlan_objmgr_vdev *vdev); + /** * mlme_get_vdev_start_failed() - get mlme priv vdev restart fail flag * @vdev: vdev pointer diff --git a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c index 8a3f869be054..9d4e7b834eb5 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -595,6 +595,40 @@ mlme_set_vdev_start_failed(struct wlan_objmgr_vdev *vdev, bool val) return QDF_STATUS_SUCCESS; } +struct wlan_mlme_nss_chains *mlme_get_dynamic_vdev_config( + struct wlan_objmgr_vdev *vdev) +{ + struct vdev_mlme_obj *vdev_mlme; + struct mlme_legacy_priv *mlme_priv; + + vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); + if (!vdev_mlme) { + mlme_err("vdev component object is NULL"); + return NULL; + } + + mlme_priv = vdev_mlme->legacy_vdev_ptr; + + return &mlme_priv->dynamic_cfg; +} + +struct wlan_mlme_nss_chains *mlme_get_ini_vdev_config( + struct wlan_objmgr_vdev *vdev) +{ + struct vdev_mlme_obj *vdev_mlme; + struct mlme_legacy_priv *mlme_priv; + + vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); + if (!vdev_mlme) { + mlme_err("vdev component object is NULL"); + return NULL; + } + + mlme_priv = vdev_mlme->legacy_vdev_ptr; + + return &mlme_priv->ini_cfg; +} + bool mlme_get_vdev_start_failed(struct wlan_objmgr_vdev *vdev) { struct vdev_mlme_obj *vdev_mlme; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index a69c873a707d..1431964288d5 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4043,6 +4043,21 @@ static int hdd_set_sme_session_param(struct hdd_adapter *adapter, return 0; } +static void +hdd_store_nss_chains_cfg_in_vdev(struct hdd_adapter *adapter) +{ + struct wlan_mlme_nss_chains vdev_ini_cfg; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + /* store the ini config in vdev component in mlme priv structure */ + sme_populate_nss_chain_params(hdd_ctx->mac_handle, &vdev_ini_cfg, + adapter->device_mode, + hdd_ctx->num_rf_chains); + qdf_mem_copy(mlme_get_dynamic_vdev_config(adapter->vdev), + &vdev_ini_cfg, sizeof(struct wlan_mlme_nss_chains)); + qdf_mem_copy(mlme_get_ini_vdev_config(adapter->vdev), + &vdev_ini_cfg, sizeof(struct wlan_mlme_nss_chains)); +} int hdd_vdev_create(struct hdd_adapter *adapter, csr_roam_complete_cb callback, void *ctx) { @@ -4075,7 +4090,6 @@ int hdd_vdev_create(struct hdd_adapter *adapter, hdd_err("failed to populating SME params"); goto objmgr_vdev_destroy_procedure; } - status = sme_open_session(hdd_ctx->mac_handle, &sme_session_params); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("failed to open sme session: %d", status); @@ -4146,6 +4160,8 @@ int hdd_vdev_create(struct hdd_adapter *adapter, hdd_objmgr_put_vdev(adapter); } + hdd_store_nss_chains_cfg_in_vdev(adapter); + hdd_info("vdev %d created successfully", adapter->session_id); return 0; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 506dd6b4a958..d76d87f139ff 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -37,7 +37,7 @@ #include "wma_tgt_cfg.h" #include "wma_fips_public_structs.h" #include "wma_sar_public_structs.h" - +#include "wlan_mlme_public_struct.h" #include "sme_rrm_internal.h" #include "sir_types.h" #include "scheduler_api.h" @@ -323,13 +323,30 @@ QDF_STATUS sme_start(mac_handle_t mac_handle); */ QDF_STATUS sme_stop(mac_handle_t mac_handle); -/* +/** + * sme_populate_nss_chain_params() - fill vdev nss chain params from ini + * @mac_handle: The handle returned by mac_open. + * @vdev_ini_cfg: pointer to the structure to be filled + * @device_mode: device mode (eg STA, SAP etc.) + * @rf_chains_supported: number of chains supported by fw(updated during + * service ready event) + * + * This API will fill the nss chain params for the particlar vdev from ini + * configuration for the respective vdev. + * + * Return: none + */ +void sme_populate_nss_chain_params(mac_handle_t mac_handle, + struct wlan_mlme_nss_chains *vdev_ini_cfg, + enum QDF_OPMODE device_mode, + uint8_t rf_chains_supported); + +/** * sme_open_session() - Open a session for given persona * * This is a synchronous API. For any protocol stack related activity * requires session to be opened. This API needs to be called to open * the session in SME module. - * * hal: The handle returned by mac_open. * params: to initialize the session open params * @@ -339,7 +356,7 @@ QDF_STATUS sme_stop(mac_handle_t mac_handle); */ QDF_STATUS sme_open_session(mac_handle_t hal, struct sme_session_params *params); -/* +/** * sme_close_session() - Close a session for given persona * * This is a synchronous API. This API needs to be called to close the session diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index c5f0b98051b9..30560f07281c 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -35,6 +35,7 @@ #include "qdf_trace.h" #include "sme_trace.h" #include "qdf_types.h" +#include "qdf_util.h" #include "qdf_trace.h" #include "cds_utils.h" #include "sap_api.h" @@ -4768,6 +4769,117 @@ QDF_STATUS sme_oem_data_req(mac_handle_t hal, struct oem_data_req *hdd_oem_req) } #endif /*FEATURE_OEM_DATA_SUPPORT */ +#define STA_NSS_CHAINS_SHIFT 0 +#define SAP_NSS_CHAINS_SHIFT 3 +#define P2P_GO_NSS_CHAINS_SHIFT 6 +#define P2P_CLI_CHAINS_SHIFT 9 +#define TDLS_CHAINS_SHIFT 12 +#define IBSS_NSS_CHAINS_SHIFT 15 +#define P2P_DEV_NSS_CHAINS_SHIFT 18 +#define OCB_NSS_CHAINS_SHIFT 21 +#define NAN_NSS_CHAIN_SHIFT 24 +#define NSS_CHAIN_MASK 0x7 +#define GET_VDEV_NSS_CHAIN(x, y) (((x) >> (y)) & NSS_CHAIN_MASK) + +static uint8_t sme_get_nss_chain_shift(enum QDF_OPMODE device_mode) +{ + switch (device_mode) { + case QDF_STA_MODE: + return STA_NSS_CHAINS_SHIFT; + case QDF_SAP_MODE: + return SAP_NSS_CHAINS_SHIFT; + case QDF_P2P_GO_MODE: + return P2P_GO_NSS_CHAINS_SHIFT; + case QDF_P2P_CLIENT_MODE: + return P2P_CLI_CHAINS_SHIFT; + case QDF_IBSS_MODE: + return IBSS_NSS_CHAINS_SHIFT; + case QDF_P2P_DEVICE_MODE: + return P2P_DEV_NSS_CHAINS_SHIFT; + case QDF_OCB_MODE: + return OCB_NSS_CHAINS_SHIFT; + + default: + sme_err("Device mode %d invalid", device_mode); + return STA_NSS_CHAINS_SHIFT; + } +} + +static void +sme_fill_nss_chain_params(struct sAniSirGlobal *mac_ctx, + struct wlan_mlme_nss_chains *vdev_ini_cfg, + enum QDF_OPMODE device_mode, + enum nss_chains_band_info band, + uint8_t rf_chains_supported) +{ + uint8_t nss_chain_shift; + uint8_t max_supported_nss; + struct wlan_mlme_nss_chains *nss_chains_ini_cfg = + &mac_ctx->mlme_cfg->nss_chains_ini_cfg; + + nss_chain_shift = sme_get_nss_chain_shift(device_mode); + max_supported_nss = mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2 ? + MAX_VDEV_NSS : 1; + + /* If the fw doesn't support two chains, num rf chains can max be 1 */ + vdev_ini_cfg->num_rx_chains[band] = + QDF_MIN(GET_VDEV_NSS_CHAIN( + nss_chains_ini_cfg->num_rx_chains[band], + nss_chain_shift), rf_chains_supported); + + vdev_ini_cfg->num_tx_chains[band] = + QDF_MIN(GET_VDEV_NSS_CHAIN( + nss_chains_ini_cfg->num_tx_chains[band], + nss_chain_shift), rf_chains_supported); + + /* If 2x2 mode is disabled, then max rx, tx nss can be 1 */ + vdev_ini_cfg->rx_nss[band] = + QDF_MIN(GET_VDEV_NSS_CHAIN( + nss_chains_ini_cfg->rx_nss[band], + nss_chain_shift), max_supported_nss); + + vdev_ini_cfg->tx_nss[band] = + QDF_MIN(GET_VDEV_NSS_CHAIN( + nss_chains_ini_cfg->tx_nss[band], + nss_chain_shift), max_supported_nss); + + vdev_ini_cfg->num_tx_chains_11a = + QDF_MIN(GET_VDEV_NSS_CHAIN( + nss_chains_ini_cfg->num_tx_chains_11a, + nss_chain_shift), rf_chains_supported); + + /* If the fw doesn't support two chains, num rf chains can max be 1 */ + vdev_ini_cfg->num_tx_chains_11b = + QDF_MIN(GET_VDEV_NSS_CHAIN( + nss_chains_ini_cfg->num_tx_chains_11b, + nss_chain_shift), rf_chains_supported); + + vdev_ini_cfg->num_tx_chains_11g = + QDF_MIN(GET_VDEV_NSS_CHAIN( + nss_chains_ini_cfg->num_tx_chains_11g, + nss_chain_shift), rf_chains_supported); + + vdev_ini_cfg->disable_rx_mrc[band] = + nss_chains_ini_cfg->disable_rx_mrc[band]; + + vdev_ini_cfg->disable_tx_mrc[band] = + nss_chains_ini_cfg->disable_tx_mrc[band]; +} + +void sme_populate_nss_chain_params(mac_handle_t mac_handle, + struct wlan_mlme_nss_chains *vdev_ini_cfg, + enum QDF_OPMODE device_mode, + uint8_t rf_chains_supported) +{ + struct sAniSirGlobal *mac_ctx = MAC_CONTEXT(mac_handle); + enum nss_chains_band_info band; + + for (band = BAND_2GHZ; band < BAND_MAX; band++) + sme_fill_nss_chain_params(mac_ctx, vdev_ini_cfg, + device_mode, band, + rf_chains_supported); +} + QDF_STATUS sme_open_session(mac_handle_t hal, struct sme_session_params *params) { QDF_STATUS status = QDF_STATUS_E_INVAL;