diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index c2b086a6fc..1c6158dbdd 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -257,6 +257,42 @@ static void mlme_init_chainmask_cfg(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_ENABLE_BT_CHAIN_SEPARATION); } +static void mlme_init_ratemask_cfg(struct wlan_objmgr_psoc *psoc, + struct wlan_mlme_ratemask *ratemask_cfg) +{ + uint32_t masks[CFG_MLME_RATE_MASK_LEN] = { 0 }; + qdf_size_t len = 0; + QDF_STATUS status; + + ratemask_cfg->type = cfg_get(psoc, CFG_RATEMASK_TYPE); + if ((ratemask_cfg->type <= WLAN_MLME_RATEMASK_TYPE_NO_MASK) || + (ratemask_cfg->type >= WLAN_MLME_RATEMASK_TYPE_MAX)) { + mlme_legacy_debug("Ratemask disabled"); + return; + } + + status = qdf_uint32_array_parse(cfg_get(psoc, CFG_RATEMASK_SET), + masks, + CFG_MLME_RATE_MASK_LEN, + &len); + + if (status != QDF_STATUS_SUCCESS || len != CFG_MLME_RATE_MASK_LEN) { + /* Do not enable ratemaks if config is invalid */ + ratemask_cfg->type = WLAN_MLME_RATEMASK_TYPE_NO_MASK; + mlme_legacy_err("Failed to parse ratemask"); + return; + } + + ratemask_cfg->lower32 = masks[0]; + ratemask_cfg->higher32 = masks[1]; + ratemask_cfg->lower32_2 = masks[2]; + ratemask_cfg->higher32_2 = masks[3]; + mlme_legacy_debug("Ratemask type: %d, masks:0x%x, 0x%x, 0x%x, 0x%x", + ratemask_cfg->type, ratemask_cfg->lower32, + ratemask_cfg->higher32, ratemask_cfg->lower32_2, + ratemask_cfg->higher32_2); +} + #ifdef WLAN_FEATURE_11W static void mlme_init_pmf_cfg(struct wlan_objmgr_psoc *psoc, struct wlan_mlme_generic *gen) @@ -2290,6 +2326,7 @@ QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc) mlme_init_reg_cfg(psoc, &mlme_cfg->reg); mlme_init_btm_cfg(psoc, &mlme_cfg->btm); mlme_init_roam_score_config(psoc, mlme_cfg); + mlme_init_ratemask_cfg(psoc, &mlme_cfg->ratemask_cfg); return status; } diff --git a/components/mlme/dispatcher/inc/cfg_mlme_rates.h b/components/mlme/dispatcher/inc/cfg_mlme_rates.h index eb886a368d..665fb5c8f7 100644 --- a/components/mlme/dispatcher/inc/cfg_mlme_rates.h +++ b/components/mlme/dispatcher/inc/cfg_mlme_rates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -30,6 +30,7 @@ #define CFG_SUPPORTED_MCS_SET_LEN 16 #define CFG_BASIC_MCS_SET_LEN 16 #define CFG_CURRENT_MCS_SET_LEN 16 +#define CFG_MLME_RATE_MASK_LEN 4 /* * @@ -221,6 +222,78 @@ CFG_CURRENT_MCS_SET_DATA, \ "current MCS set") +/* + * + * ratemask_type - PHY type for the ratemask. + * @Min: 0 No rate mask set defined - disabled the configuration + * @Max: 4 + * @Default: 0 + * + * This ini is used to set the PHY type for ratemask in rate selection. + * + * 0 = Disables the configuration + * 1 = The rate mask specified is for CCK/OFDM configuration + * 2 = The rate mask specified is for HT configuration + * 3 = The rate mask specified is for VHT configuration + * 4 = The rate mask specified is for HE/11ax configuration + * + * Related: CFG_RATEMASK_SET + * + * Usage: External + */ +#define CFG_RATEMASK_TYPE CFG_INI_UINT( \ + "ratemask_type", \ + 0, \ + 4, \ + 0, \ + CFG_VALUE_OR_DEFAULT, \ + "Ratemask type") + +/* + * + * ratemask_set - ratemasks for a PHY type used in rate selection + * @Min: default data length of ratemask in string format + * @Max: default data length of ratemask in string format + * @Default: 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, 0xFFFFFFFF + * + * This is used to set the rate mask value to be used in rate selection. + * Each of the four words must be configured. + * A bit value of 1 represents rate is enabled + * A bit value of 0 represents rate is disabled + * + * [b31-b0],[b63-b32],[b95-b64],[b127-b96] + * For HE targets, 12 bits correpond to one NSS setting. Ex: + * b0-13 => NSS1, MCS 0-13 + * b14-27 => NSS2, MCS 0-13 and so on for other NSS. + * Note that the bit representation is continuous. + * + * For VHT targets, 10 bits correspond to one NSS setting. + * b0-9 => NSS1, MCS 0-9 + * b10-19 => NSS2, MCS 0-9 and so on for other NSS. + * + * For HT targets, 8 bits correspond to one NSS setting. + * b0-7 => NSS1, MCS 0-7 + * b8-15 => NSS2, MCS 0-7 and so on for other NSS. + * + * For OFDM/CCK targets, 8 bits correspond to one NSS setting. + * Bit position |-b3-|-b2-|-b1-|-b0-| + * Rates in Mbps |-1 -|-2 -|-5.5|-11-| CCK Rates + * + * Bit position |-b11-|-b10-|-b09-|-b08-|-b07-|-b06-|-b05-|-b04-| + * Rates in Mbps |- 9 -|- 18-|-36 -|-54 -|- 6 -|-12 -| -24-|-48- | OFDM Rates + * + * Related: CFG_RATEMASK_TYPE + * + * Usage: External + */ +#define CFG_RATEMASK_DATA "0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF" +#define CFG_RATEMASK_SET CFG_INI_STRING( \ + "ratemask_set", \ + 0, \ + sizeof(CFG_RATEMASK_DATA) - 1, \ + CFG_RATEMASK_DATA, \ + "Ratemasks for rate selection") + #define CFG_RATES_ALL \ CFG(CFG_MAX_HT_MCS_FOR_TX_DATA) \ CFG(CFG_DISABLE_ABG_RATE_FOR_TX_DATA) \ @@ -232,6 +305,8 @@ CFG(CFG_SUPPORTED_RATES_11A) \ CFG(CFG_SUPPORTED_MCS_SET) \ CFG(CFG_BASIC_MCS_SET) \ - CFG(CFG_CURRENT_MCS_SET) + CFG(CFG_CURRENT_MCS_SET) \ + CFG(CFG_RATEMASK_TYPE) \ + CFG(CFG_RATEMASK_SET) #endif /* __CFG_MLME_RATES_H */ diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 0da44c9660..833174cc0d 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1131,6 +1131,42 @@ struct wlan_mlme_chainmask { bool enable_bt_chain_separation; }; +/** + * enum wlan_mlme_ratemask_type: Type of PHY for ratemask + * @WLAN_MLME_RATEMASK_TYPE_NO_MASK: no ratemask set + * @WLAN_MLME_RATEMASK_TYPE_CCK: CCK/OFDM rate + * @WLAN_MLEM_RATEMASK_TYPE_HT: HT rate + * @WLAN_MLME_RATEMASK_TYPE_VHT: VHT rate + * @WLAN_MLME_RATEMASK_TYPE_HE: HE rate + * + * This is used for 'type' values in wlan_mlme_ratemask + */ +enum wlan_mlme_ratemask_type { + WLAN_MLME_RATEMASK_TYPE_NO_MASK = 0, + WLAN_MLME_RATEMASK_TYPE_CCK = 1, + WLAN_MLME_RATEMASK_TYPE_HT = 2, + WLAN_MLME_RATEMASK_TYPE_VHT = 3, + WLAN_MLME_RATEMASK_TYPE_HE = 4, + /* keep this last */ + WLAN_MLME_RATEMASK_TYPE_MAX, +}; + +/** + * struct wlan_mlme_ratemask - ratemask config parameters + * @type: Type of PHY the mask to be applied + * @lower32: Lower 32 bits in the 1st 64-bit value + * @higher32: Higher 32 bits in the 1st 64-bit value + * @lower32_2: Lower 32 bits in the 2nd 64-bit value + * @higher32_2: Higher 32 bits in the 2nd 64-bit value + */ +struct wlan_mlme_ratemask { + enum wlan_mlme_ratemask_type type; + uint32_t lower32; + uint32_t higher32; + uint32_t lower32_2; + uint32_t higher32_2; +}; + /* struct wlan_mlme_generic - Generic CFG config items * * @band_capability: HW Band Capability - Both or 2.4G only or 5G only @@ -2333,6 +2369,7 @@ struct wlan_mlme_cfg { struct wlan_mlme_reg reg; struct roam_trigger_score_delta trig_score_delta[NUM_OF_ROAM_TRIGGERS]; struct roam_trigger_min_rssi trig_min_rssi[NUM_OF_ROAM_TRIGGERS]; + struct wlan_mlme_ratemask ratemask_cfg; }; enum pkt_origin { diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 63bd64963b..1d21ec5f50 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -87,6 +87,7 @@ #include "wlan_utility.h" #include "wlan_coex_ucfg_api.h" #include +#include "wmi_unified_vdev_api.h" #ifdef DCS_INTERFERENCE_DETECTION #include @@ -1119,6 +1120,36 @@ static void wma_dcs_clear_vdev_starting(struct mac_context *mac_ctx, } #endif +/* + * wma_get_ratemask_type() - convert user input ratemask type to FW type + * @type: User input ratemask type maintained in HDD + * @fwtype: Value return arg for fw ratemask type value + * + * Return: FW configurable ratemask type + */ +static QDF_STATUS wma_get_ratemask_type(enum wlan_mlme_ratemask_type type, + uint8_t *fwtype) +{ + switch (type) { + case WLAN_MLME_RATEMASK_TYPE_CCK: + *fwtype = WMI_RATEMASK_TYPE_CCK; + break; + case WLAN_MLME_RATEMASK_TYPE_HT: + *fwtype = WMI_RATEMASK_TYPE_HT; + break; + case WLAN_MLME_RATEMASK_TYPE_VHT: + *fwtype = WMI_RATEMASK_TYPE_VHT; + break; + case WLAN_MLME_RATEMASK_TYPE_HE: + *fwtype = WMI_RATEMASK_TYPE_HE; + break; + default: + return QDF_STATUS_E_INVAL; + } + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS wma_vdev_start_resp_handler(struct vdev_mlme_obj *vdev_mlme, struct vdev_start_response *rsp) { @@ -1130,6 +1161,9 @@ QDF_STATUS wma_vdev_start_resp_handler(struct vdev_mlme_obj *vdev_mlme, QDF_STATUS status; enum vdev_assoc_type assoc_type = VDEV_ASSOC; struct vdev_mlme_obj *mlme_obj; + struct wlan_mlme_psoc_ext_obj *mlme_psoc_obj; + const struct wlan_mlme_ratemask *ratemask_cfg; + struct config_ratemask_params rparams = {0}; wma = cds_get_context(QDF_MODULE_ID_WMA); if (!wma) { @@ -1142,6 +1176,9 @@ QDF_STATUS wma_vdev_start_resp_handler(struct vdev_mlme_obj *vdev_mlme, return QDF_STATUS_E_FAILURE; } + mlme_psoc_obj = mlme_get_psoc_ext_obj(psoc); + ratemask_cfg = &mlme_psoc_obj->cfg.ratemask_cfg; + if (!mac_ctx) { wma_err("Failed to get mac_ctx"); return QDF_STATUS_E_FAILURE; @@ -1254,6 +1291,38 @@ QDF_STATUS wma_vdev_start_resp_handler(struct vdev_mlme_obj *vdev_mlme, if (iface->type == WMI_VDEV_TYPE_AP && wma_is_vdev_up(rsp->vdev_id)) wma_set_sap_keepalive(wma, rsp->vdev_id); + /* Send ratemask to firmware */ + if ((ratemask_cfg->type > WLAN_MLME_RATEMASK_TYPE_NO_MASK) && + (ratemask_cfg->type < WLAN_MLME_RATEMASK_TYPE_MAX)) { + struct wmi_unified *wmi_handle = wma->wmi_handle; + + if (!wmi_handle) { + wma_err(FL("wmi_handle is null")); + return QDF_STATUS_E_INVAL; + } + + rparams.vdev_id = rsp->vdev_id; + status = wma_get_ratemask_type(ratemask_cfg->type, + &rparams.type); + + if (QDF_IS_STATUS_ERROR(status)) { + wma_err(FL("unable to map ratemask")); + /* don't fail, default rates will still work */ + return QDF_STATUS_SUCCESS; + } + + rparams.lower32 = ratemask_cfg->lower32; + rparams.higher32 = ratemask_cfg->higher32; + rparams.lower32_2 = ratemask_cfg->lower32_2; + rparams.higher32_2 = ratemask_cfg->higher32_2; + + status = wmi_unified_vdev_config_ratemask_cmd_send(wmi_handle, + &rparams); + /* Only log failure. Do not abort */ + if (QDF_IS_STATUS_ERROR(status)) + wma_err(FL("failed to send ratemask")); + } + return QDF_STATUS_SUCCESS; }