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) {