diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 019be8cfa763..7c5df85db78b 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -300,8 +300,33 @@ QDF_STATUS hdd_hex_string_to_u16_array(char *str, uint16_t *int_array, void hdd_cfg_print_global_config(struct hdd_context *hdd_ctx); +/** + * hdd_update_nss() - Update the number of spatial streams supported. + * + * @adapter: the pointer to adapter + * @nss: the number of spatial streams to be updated + * + * This function is used to modify the number of spatial streams + * supported when not in connected state. + * + * Return: QDF_STATUS_SUCCESS if nss is correctly updated, + * otherwise QDF_STATUS_E_FAILURE would be returned + */ QDF_STATUS hdd_update_nss(struct hdd_adapter *adapter, uint8_t nss); +/** + * hdd_get_nss() - Get the number of spatial streams supported by the adapter + * + * @adapter: the pointer to adapter + * @nss: the number of spatial streams supported by the adapter + * + * This function is used to get the number of spatial streams supported by + * the adapter. + * + * Return: QDF_STATUS + */ +QDF_STATUS hdd_get_nss(struct hdd_adapter *adapter, uint8_t *nss); + /** * hdd_dfs_indicate_radar() - Block tx as radar found on the channel * @hdd_ctxt: HDD context pointer diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 91e240057be9..df42822949c5 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -1022,19 +1022,6 @@ 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. - * - * @adapter: the pointer to adapter - * @nss: the number of spatial streams to be updated - * - * This function is used to modify the number of spatial streams - * supported when not in connected state. - * - * Return: QDF_STATUS_SUCCESS if nss is correctly updated, - * otherwise QDF_STATUS_E_FAILURE would be returned - */ QDF_STATUS hdd_update_nss(struct hdd_adapter *adapter, uint8_t nss) { struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -1225,6 +1212,26 @@ skip_ht_cap_update: return (status == false) ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS; } +QDF_STATUS hdd_get_nss(struct hdd_adapter *adapter, uint8_t *nss) +{ + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + bool bval; + QDF_STATUS status; + + status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("unable to get vht_enable2x2"); + return status; + } + + *nss = (bval) ? 2 : 1; + if (!policy_mgr_is_hw_dbs_2x2_capable(hdd_ctx->psoc) && + policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc)) + *nss = *nss - 1; + + return status; +} + int hdd_get_ldpc(struct hdd_adapter *adapter, int *value) { mac_handle_t mac_handle = adapter->hdd_ctx->mac_handle; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 24e1b43a4d1b..472cc18368e9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -6716,6 +6716,7 @@ const struct nla_policy wlan_hdd_wifi_config_policy[ [QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE] = {.type = NLA_U32 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_NSS] = {.type = NLA_U8 }, }; @@ -8354,6 +8355,33 @@ static int hdd_set_dynamic_bw(struct hdd_adapter *adapter, enable, PDEV_CMD); } +/** + * hdd_set_nss() - set the number of spatial streams supported by the adapter + * + * @adapter: hdd adapter + * @attr: pointer to nla attr + * + * Return: 0 on success, negative errno on failure + */ +static int hdd_set_nss(struct hdd_adapter *adapter, + const struct nlattr *attr) +{ + uint8_t nss; + int ret; + QDF_STATUS status; + + nss = nla_get_u8(attr); + + status = hdd_update_nss(adapter, nss); + ret = qdf_status_to_os_return(status); + + if (ret == 0 && adapter->device_mode == QDF_SAP_MODE) + ret = wma_cli_set_command(adapter->vdev_id, WMI_VDEV_PARAM_NSS, + nss, VDEV_CMD); + + return ret; +} + /** * typedef independent_setter_fn - independent attribute handler * @adapter: The adapter being configured @@ -8458,6 +8486,8 @@ static const struct independent_setters independent_setters[] = { hdd_set_channel_width}, {QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW, hdd_set_dynamic_bw}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_NSS, + hdd_set_nss}, }; #ifdef WLAN_FEATURE_ELNA @@ -8783,6 +8813,49 @@ static int hdd_get_dynamic_bw(struct hdd_adapter *adapter, return 0; } +/** + * hdd_get_nss_config() - Get the number of spatial streams supported by + * the adapter + * @adapter: Pointer to HDD adapter + * @skb: sk buffer to hold nl80211 attributes + * @attr: Pointer to struct nlattr + * + * Return: 0 on success; error number otherwise + */ +static int hdd_get_nss_config(struct hdd_adapter *adapter, + struct sk_buff *skb, + const struct nlattr *attr) +{ + uint8_t nss; + + if (adapter->device_mode == QDF_SAP_MODE) { + int value; + + value = wma_cli_get_command(adapter->vdev_id, + WMI_VDEV_PARAM_NSS, VDEV_CMD); + if (value < 0) { + hdd_err("Failed to get nss"); + return -EINVAL; + } + nss = (uint8_t)value; + } else { + QDF_STATUS status; + + status = hdd_get_nss(adapter, &nss); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Failed to get nss"); + return -EINVAL; + } + } + + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_NSS, nss)) { + hdd_err("nla_put failure"); + return -EINVAL; + } + + return 0; +} + /** * typedef config_getter_fn - get configuration handler * @adapter: The adapter being configured @@ -8845,6 +8918,9 @@ static const struct config_getters config_getters[] = { {QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW, sizeof(uint8_t), hdd_get_dynamic_bw}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_NSS, + sizeof(uint8_t), + hdd_get_nss_config}, }; /** diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 804f0c713620..b314ffdef1ff 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -5386,14 +5386,15 @@ static int __iw_setnone_getint(struct net_device *dev, case WE_GET_NSS: { - sme_get_config_param(mac_handle, sme_config); - status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval); - if (!QDF_IS_STATUS_SUCCESS(status)) + uint8_t nss; + + status = hdd_get_nss(adapter, &nss); + if (!QDF_IS_STATUS_SUCCESS(status)) { hdd_err("unable to get vht_enable2x2"); - *value = (bval == 0) ? 1 : 2; - if (!policy_mgr_is_hw_dbs_2x2_capable(hdd_ctx->psoc) && - policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc)) - *value = *value - 1; + ret = -EIO; + break; + } + *value = nss; hdd_debug("GET_NSS: Current NSS:%d", *value); break;