From fde76d4e9ccb8141a6308a4158f66a0e582abd28 Mon Sep 17 00:00:00 2001 From: Min Liu Date: Tue, 26 May 2020 17:35:24 +0800 Subject: [PATCH] qcacld-3.0: Set Wi-Fi configurations - bandwidth configurations Add attributes in SET(GET)_WIFI_CONFIGURATION to dynamically configure capabilities - CHANNEL_WIDTH and DYNAMIC_BW. Change-Id: I4d577f057e5d1b385ab7a6fadcb344dc30b85c4c CRs-Fixed: 2694656 --- core/hdd/inc/wlan_hdd_cfg.h | 13 +++ core/hdd/src/wlan_hdd_cfg.c | 35 ++++++ core/hdd/src/wlan_hdd_cfg80211.c | 193 +++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_wext.c | 33 +----- 4 files changed, 245 insertions(+), 29 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index dc02361effed..019be8cfa763 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "osapi_linux.h" #include #include "wlan_pmo_hw_filter_public_struct.h" @@ -383,4 +384,16 @@ int hdd_get_rx_stbc(struct hdd_adapter *adapter, int *value); * Return: 0 on success, negative errno on failure */ int hdd_set_rx_stbc(struct hdd_adapter *adapter, int value); + +/** + * hdd_update_channel_width() - Update adapter channel width settings + * @adapter: adapter being modified + * @chwidth: new channel width of enum eSirMacHTChannelWidth + * @bonding_mode: channel bonding mode of the new channel width + * + * Return: 0 on success, negative errno on failure + */ +int hdd_update_channel_width(struct hdd_adapter *adapter, + enum eSirMacHTChannelWidth chwidth, + uint32_t bonding_mode); #endif /* end #if !defined(HDD_CONFIG_H__) */ diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index de271dbc4e6a..91e240057be9 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -47,6 +47,7 @@ #include "wlan_fwol_ucfg_api.h" #include "cfg_ucfg_api.h" #include "hdd_dp_cfg.h" +#include /** * get_next_line() - find and locate the new line pointer @@ -1403,3 +1404,37 @@ int hdd_set_rx_stbc(struct hdd_adapter *adapter, int value) return ret; } + +int hdd_update_channel_width(struct hdd_adapter *adapter, + enum eSirMacHTChannelWidth chwidth, + uint32_t bonding_mode) +{ + struct hdd_context *hdd_ctx; + struct sme_config_params *sme_config; + int ret; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) { + hdd_err("hdd_ctx failure"); + return -EINVAL; + } + + sme_config = qdf_mem_malloc(sizeof(*sme_config)); + if (!sme_config) + return -ENOMEM; + + ret = wma_cli_set_command(adapter->vdev_id, WMI_VDEV_PARAM_CHWIDTH, + chwidth, VDEV_CMD); + if (ret) + goto free_config; + + sme_get_config_param(hdd_ctx->mac_handle, sme_config); + sme_config->csr_config.channelBondingMode5GHz = bonding_mode; + sme_config->csr_config.channelBondingMode24GHz = bonding_mode; + sme_update_config(hdd_ctx->mac_handle, sme_config); + +free_config: + qdf_mem_free(sme_config); + return ret; + +} diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 3867b10142e2..24e1b43a4d1b 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -6714,6 +6714,8 @@ const struct nla_policy wlan_hdd_wifi_config_policy[ [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC] = {.type = NLA_U8 }, [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 }, }; @@ -8233,6 +8235,125 @@ static int hdd_set_elna_bypass(struct hdd_adapter *adapter, } #endif +static enum eSirMacHTChannelWidth +hdd_nl80211_chwidth_to_chwidth(uint8_t nl80211_chwidth) +{ + int chwidth; + + switch (nl80211_chwidth) { + case NL80211_CHAN_WIDTH_20: + chwidth = eHT_CHANNEL_WIDTH_20MHZ; + break; + case NL80211_CHAN_WIDTH_40: + chwidth = eHT_CHANNEL_WIDTH_40MHZ; + break; + case NL80211_CHAN_WIDTH_80: + chwidth = eHT_CHANNEL_WIDTH_80MHZ; + break; + case NL80211_CHAN_WIDTH_80P80: + chwidth = eHT_CHANNEL_WIDTH_80P80MHZ; + break; + case NL80211_CHAN_WIDTH_160: + chwidth = eHT_CHANNEL_WIDTH_160MHZ; + break; + default: + hdd_err("Unsupported channel width %d", nl80211_chwidth); + chwidth = -EINVAL; + } + + return chwidth; +} + +static uint8_t +hdd_chwidth_to_nl80211_chwidth(enum eSirMacHTChannelWidth chwidth) +{ + uint8_t nl80211_chwidth; + + switch (chwidth) { + case eHT_CHANNEL_WIDTH_20MHZ: + nl80211_chwidth = NL80211_CHAN_WIDTH_20; + break; + case eHT_CHANNEL_WIDTH_40MHZ: + nl80211_chwidth = NL80211_CHAN_WIDTH_40; + break; + case eHT_CHANNEL_WIDTH_80MHZ: + nl80211_chwidth = NL80211_CHAN_WIDTH_80; + break; + case eHT_CHANNEL_WIDTH_80P80MHZ: + nl80211_chwidth = NL80211_CHAN_WIDTH_80P80; + break; + case eHT_CHANNEL_WIDTH_160MHZ: + nl80211_chwidth = NL80211_CHAN_WIDTH_160; + break; + default: + hdd_err("Unsupported channel width %d", chwidth); + nl80211_chwidth = 0xFF; + } + + return nl80211_chwidth; +} + +static uint32_t hdd_nl80211_chwidth_to_bonding_mode(uint8_t nl80211_chwidth) +{ + uint32_t bonding_mode; + + switch (nl80211_chwidth) { + case NL80211_CHAN_WIDTH_20: + bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + break; + default: + bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + } + + return bonding_mode; +} + +/** + * hdd_set_channel_width() - set channel width + * + * @adapter: hdd adapter + * @attr: nla attr sent by supplicant + * + * Return: 0 on success, negative errno on failure + */ +static int hdd_set_channel_width(struct hdd_adapter *adapter, + const struct nlattr *attr) +{ + uint8_t nl80211_chwidth; + enum eSirMacHTChannelWidth chwidth; + uint32_t bonding_mode; + + nl80211_chwidth = nla_get_u8(attr); + chwidth = hdd_nl80211_chwidth_to_chwidth(nl80211_chwidth); + if (chwidth < 0) { + hdd_err("Invalid channel width"); + return -EINVAL; + } + + bonding_mode = hdd_nl80211_chwidth_to_bonding_mode(nl80211_chwidth); + + return hdd_update_channel_width(adapter, chwidth, bonding_mode); +} + +/** + * hdd_set_dynamic_bw() - enable / disable dynamic bandwidth + * + * @adapter: hdd adapter + * @attr: nla attr sent by supplicant + * + * Return: 0 on success, negative errno on failure + */ +static int hdd_set_dynamic_bw(struct hdd_adapter *adapter, + const struct nlattr *attr) +{ + uint8_t enable; + + enable = nla_get_u8(attr); + + return wma_cli_set_command(adapter->vdev_id, WMI_PDEV_PARAM_DYNAMIC_BW, + enable, PDEV_CMD); +} + /** * typedef independent_setter_fn - independent attribute handler * @adapter: The adapter being configured @@ -8333,6 +8454,10 @@ static const struct independent_setters independent_setters[] = { hdd_config_rx_stbc}, {QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE, hdd_config_phy_mode}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH, + hdd_set_channel_width}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW, + hdd_set_dynamic_bw}, }; #ifdef WLAN_FEATURE_ELNA @@ -8596,6 +8721,68 @@ static int hdd_get_rx_amsdu(struct hdd_adapter *adapter, return 0; } +/** + * hdd_get_channel_width() - Get channel width + * @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_channel_width(struct hdd_adapter *adapter, + struct sk_buff *skb, + const struct nlattr *attr) +{ + enum eSirMacHTChannelWidth chwidth; + uint8_t nl80211_chwidth; + + chwidth = wma_cli_get_command(adapter->vdev_id, WMI_VDEV_PARAM_CHWIDTH, + VDEV_CMD); + if (chwidth < 0) { + hdd_err("Failed to get chwidth"); + return -EINVAL; + } + + nl80211_chwidth = hdd_chwidth_to_nl80211_chwidth(chwidth); + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH, + nl80211_chwidth)) { + hdd_err("nla_put failure"); + return -EINVAL; + } + + return 0; +} + +/** + * hdd_get_dynamic_bw() - Get dynamic bandwidth disabled / enabled + * @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_dynamic_bw(struct hdd_adapter *adapter, + struct sk_buff *skb, + const struct nlattr *attr) +{ + int enable; + + enable = wma_cli_get_command(adapter->vdev_id, + WMI_PDEV_PARAM_DYNAMIC_BW, PDEV_CMD); + if (enable < 0) { + hdd_err("Failed to get dynamic_bw"); + return -EINVAL; + } + + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW, + (uint8_t)enable)) { + hdd_err("nla_put failure"); + return -EINVAL; + } + + return 0; +} + /** * typedef config_getter_fn - get configuration handler * @adapter: The adapter being configured @@ -8652,6 +8839,12 @@ static const struct config_getters config_getters[] = { {QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC, sizeof(uint8_t), hdd_vendor_attr_rx_stbc_get}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH, + sizeof(uint8_t), + hdd_get_channel_width}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW, + sizeof(uint8_t), + hdd_get_dynamic_bw}, }; /** diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index f4ca0daaa184..804f0c713620 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -3574,15 +3574,7 @@ static int hdd_handle_pdev_reset(struct hdd_adapter *adapter, int value) static int hdd_we_set_ch_width(struct hdd_adapter *adapter, int ch_width) { - int errno; - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); uint32_t bonding_mode; - struct sme_config_params *sme_config; - mac_handle_t mac_handle; - - mac_handle = hdd_ctx->mac_handle; - if (!mac_handle) - return -EINVAL; /* updating channel bonding only on 5Ghz */ hdd_debug("WMI_VDEV_PARAM_CHWIDTH val %d", ch_width); @@ -3594,7 +3586,9 @@ static int hdd_we_set_ch_width(struct hdd_adapter *adapter, int ch_width) case eHT_CHANNEL_WIDTH_40MHZ: case eHT_CHANNEL_WIDTH_80MHZ: - bonding_mode = 1; + case eHT_CHANNEL_WIDTH_80P80MHZ: + case eHT_CHANNEL_WIDTH_160MHZ: + bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; break; default: @@ -3602,26 +3596,7 @@ static int hdd_we_set_ch_width(struct hdd_adapter *adapter, int ch_width) return -EINVAL; } - sme_config = qdf_mem_malloc(sizeof(*sme_config)); - if (!sme_config) { - hdd_err("failed to allocate memory for sme_config"); - return -ENOMEM; - } - - errno = wma_cli_set_command(adapter->vdev_id, WMI_VDEV_PARAM_CHWIDTH, - ch_width, VDEV_CMD); - if (errno) - goto free_config; - - sme_get_config_param(mac_handle, sme_config); - sme_config->csr_config.channelBondingMode5GHz = bonding_mode; - sme_config->csr_config.channelBondingMode24GHz = bonding_mode; - sme_update_config(mac_handle, sme_config); - -free_config: - qdf_mem_free(sme_config); - - return errno; + return hdd_update_channel_width(adapter, ch_width, bonding_mode); } static int hdd_we_set_11d_state(struct hdd_adapter *adapter, int state_11d)