From 101d014faaca5c3230fe6804d84d383c92351af9 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 17 Aug 2020 02:15:38 +0530 Subject: [PATCH] qcacld-3.0: Add support to config num of chains over vendor cmd Currently there is only SETANTENNAMODE ioctl command to configure number of chains to firmware. Add support to configure the number of chains over the nl vendor command QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS and QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS. This new interface will configure the number of chains per vdev dynamically. Change-Id: Iff22d886529f6d8fb205d668eba8928039620a20 CRs-Fixed: 2756647 --- core/hdd/src/wlan_hdd_cfg80211.c | 114 +++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg80211.h | 14 ++++ core/hdd/src/wlan_hdd_ioctl.c | 83 ---------------------- 3 files changed, 128 insertions(+), 83 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index df71f9bcff6c..2e56d10128f6 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -6851,6 +6851,8 @@ const struct nla_policy wlan_hdd_wifi_config_policy[ [QCA_WLAN_VENDOR_ATTR_CONFIG_NSS] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS] = {.type = NLA_U8 }, }; @@ -7440,6 +7442,117 @@ static int hdd_config_msdu_aggregation(struct hdd_adapter *adapter, return qdf_status_to_os_return(status); } +static QDF_STATUS +hdd_populate_vdev_chains(struct wlan_mlme_nss_chains *nss_chains_cfg, + uint8_t tx_chains, + uint8_t rx_chains, + enum nss_chains_band_info band, + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_mlme_nss_chains *dynamic_cfg; + + nss_chains_cfg->num_rx_chains[band] = rx_chains; + nss_chains_cfg->num_tx_chains[band] = tx_chains; + + dynamic_cfg = ucfg_mlme_get_dynamic_vdev_config(vdev); + if (!dynamic_cfg) { + hdd_err("nss chain dynamic config NULL"); + return QDF_STATUS_E_FAILURE; + } + /* + * If user gives any nss value, then chains will be adjusted based on + * nss (in SME func sme_validate_user_nss_chain_params). + * If Chains are not suitable as per current NSS then, we need to + * return, and the below logic is added for the same. + */ + + if ((dynamic_cfg->rx_nss[band] > rx_chains) || + (dynamic_cfg->tx_nss[band] > tx_chains)) { + hdd_err("Chains less than nss, configure correct nss first."); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +int +hdd_set_dynamic_antenna_mode(struct hdd_adapter *adapter, + uint8_t num_rx_chains, + uint8_t num_tx_chains) +{ + enum nss_chains_band_info band; + struct wlan_mlme_nss_chains user_cfg; + QDF_STATUS status; + mac_handle_t mac_handle; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct wlan_objmgr_vdev *vdev; + int ret; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + mac_handle = hdd_ctx->mac_handle; + if (!mac_handle) { + hdd_err("NULL MAC handle"); + return -EINVAL; + } + + if (!hdd_is_vdev_in_conn_state(adapter)) { + hdd_debug("Vdev (id %d) not in connected/started state, cannot accept command", + adapter->vdev_id); + return -EINVAL; + } + + vdev = hdd_objmgr_get_vdev(adapter); + if (!vdev) { + hdd_err("vdev is NULL"); + return -EINVAL; + } + + qdf_mem_zero(&user_cfg, sizeof(user_cfg)); + for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++) { + status = hdd_populate_vdev_chains(&user_cfg, + num_rx_chains, + num_tx_chains, band, vdev); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_objmgr_put_vdev(vdev); + return -EINVAL; + } + } + hdd_objmgr_put_vdev(vdev); + + status = sme_nss_chains_update(mac_handle, + &user_cfg, + adapter->vdev_id); + if (QDF_IS_STATUS_ERROR(status)) + return -EINVAL; + + return 0; +} + +static int hdd_config_vdev_chains(struct hdd_adapter *adapter, + struct nlattr *tb[]) +{ + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + uint8_t tx_chains, rx_chains; + struct nlattr *tx_attr = + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS]; + struct nlattr *rx_attr = + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS]; + + if (!tx_attr && !rx_attr) + return 0; + + tx_chains = nla_get_u8(tx_attr); + rx_chains = nla_get_u8(rx_attr); + + if (hdd_ctx->dynamic_nss_chains_support) + return hdd_set_dynamic_antenna_mode(adapter, rx_chains, + tx_chains); + return 0; +} + static int hdd_config_ant_div_period(struct hdd_adapter *adapter, struct nlattr *tb[]) { @@ -9090,6 +9203,7 @@ static const interdependent_setter_fn interdependent_setters[] = { wlan_hdd_cfg80211_wifi_set_reorder_timeout, wlan_hdd_cfg80211_wifi_set_rx_blocksize, hdd_config_msdu_aggregation, + hdd_config_vdev_chains, }; /** diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 3b2cf7f333c9..8f9234cf0699 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -817,6 +817,20 @@ void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level) } #endif +/** + * hdd_set_dynamic_antenna_mode() - set dynamic antenna mode + * @adapter: Pointer to network adapter + * @num_rx_chains: number of chains to be used for receiving data + * @num_tx_chains: number of chains to be used for transmitting data + * + * This function will set dynamic antenna mode + * + * Return: 0 for success + */ +int hdd_set_dynamic_antenna_mode(struct hdd_adapter *adapter, + uint8_t num_rx_chains, + uint8_t num_tx_chains); + /** * hdd_convert_cfgdot11mode_to_80211mode() - Function to convert cfg dot11 mode * to 80211 mode diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index e17950ca5277..0522bc488bac 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -5850,89 +5850,6 @@ wlan_hdd_soc_set_antenna_mode_cb(enum set_antenna_mode_status status, osif_request_put(request); } -static QDF_STATUS -hdd_populate_vdev_chains(struct wlan_mlme_nss_chains *nss_chains_cfg, - uint8_t tx_chains, - uint8_t rx_chains, - enum nss_chains_band_info band, - struct wlan_objmgr_vdev *vdev) -{ - struct wlan_mlme_nss_chains *dynamic_cfg; - - nss_chains_cfg->num_rx_chains[band] = rx_chains; - nss_chains_cfg->num_tx_chains[band] = tx_chains; - - dynamic_cfg = ucfg_mlme_get_dynamic_vdev_config(vdev); - if (!dynamic_cfg) { - hdd_err("nss chain dynamic config NULL"); - return QDF_STATUS_E_FAILURE; - } - /* - * If user gives any nss value, then chains will be adjusted based on - * nss (in SME func sme_validate_user_nss_chain_params). - * If Chains are not suitable as per current NSS then, we need to - * return, and the below logic is added for the same. - */ - - if ((dynamic_cfg->rx_nss[band] > rx_chains) || - (dynamic_cfg->tx_nss[band] > tx_chains)) { - hdd_err("Chains less than nss, configure correct nss first."); - return QDF_STATUS_E_FAILURE; - } - - return QDF_STATUS_SUCCESS; -} - -static int -hdd_set_dynamic_antenna_mode(struct hdd_adapter *adapter, - uint8_t num_rx_chains, - uint8_t num_tx_chains) -{ - enum nss_chains_band_info band; - struct wlan_mlme_nss_chains user_cfg; - QDF_STATUS status; - mac_handle_t mac_handle; - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - struct wlan_objmgr_vdev *vdev; - - mac_handle = hdd_ctx->mac_handle; - if (!mac_handle) { - hdd_err("NULL MAC handle"); - return -EINVAL; - } - - if (!hdd_is_vdev_in_conn_state(adapter)) { - hdd_debug("Vdev (id %d) not in connected/started state, cannot accept command", - adapter->vdev_id); - return -EINVAL; - } - - vdev = hdd_objmgr_get_vdev(adapter); - if (!vdev) { - hdd_err("vdev is NULL"); - return -EINVAL; - } - - qdf_mem_zero(&user_cfg, sizeof(user_cfg)); - for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++) { - status = hdd_populate_vdev_chains(&user_cfg, - num_rx_chains, - num_tx_chains, band, vdev); - if (QDF_IS_STATUS_ERROR(status)) { - hdd_objmgr_put_vdev(vdev); - return -EINVAL; - } - } - hdd_objmgr_put_vdev(vdev); - - status = sme_nss_chains_update(mac_handle, - &user_cfg, - adapter->vdev_id); - if (QDF_IS_STATUS_ERROR(status)) - return -EINVAL; - - return 0; -} int hdd_set_antenna_mode(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx, int mode) {