wpa_supplicant_8_lib: Add support to configure TX/RX chains and NSS
Add SET_TX_RX_CHAIN command to configure TX and RX chains and
add SET_TX_RX_NSS command to configure TX and RX NSS.
Change-Id: I3538bc070535e6d616ed83e82206cd9d81cf5110
CRs-Fixed: 3361632
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
index a647ccd..90fd3fd 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -5950,6 +5950,148 @@
return ret;
}
+static int wpa_driver_set_tx_rx_chains(struct i802_bss *bss, char *cmd,
+ char *buf, size_t buf_len)
+{
+ struct wpa_driver_nl80211_data *drv;
+ struct nl_msg *nlmsg;
+ struct nlattr *attr;
+ u8 tx_chains, rx_chains;
+ int ret;
+
+ if (!bss || !bss->drv || !cmd) {
+ wpa_printf(MSG_ERROR, "%s:Invalid arguments", __func__);
+ return -EINVAL;
+ }
+ drv = bss->drv;
+ cmd = skip_white_space(cmd);
+ if (*cmd == '\0') {
+ wpa_printf(MSG_ERROR, "tx rx chains values missing");
+ return -EINVAL;
+ }
+ tx_chains = get_u8_from_string(cmd, &ret);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "Invalid tx_chains value");
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ if (*cmd == '\0') {
+ wpa_printf(MSG_ERROR, "rx chains value missing");
+ return -EINVAL;
+ }
+ rx_chains = get_u8_from_string(cmd, &ret);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "Invalid rx_chains value");
+ return -EINVAL;
+ }
+
+ nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR, "Fail to allocate nlmsg for set_tx_rx_chains cmd");
+ return -ENOMEM;
+ }
+
+ attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+ if (!attr) {
+ ret = -ENOMEM;
+ wpa_printf(MSG_ERROR, "Fail to create nl attributes for set_tx_rx_chains cmd");
+ goto nlmsg_fail;
+ }
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS, tx_chains)) {
+ ret = -ENOMEM;
+ wpa_printf(MSG_ERROR, "Fail to put tx_chains value");
+ goto nlmsg_fail;
+ }
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS, rx_chains)) {
+ ret = -ENOMEM;
+ wpa_printf(MSG_ERROR, "Fail to put rx_chains value");
+ goto nlmsg_fail;
+ }
+ nla_nest_end(nlmsg, attr);
+
+ ret = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg, NULL, NULL);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "Fail to send set_tx_rx_chains nlmsg, error:%d", ret);
+ return ret;
+ }
+ return 0;
+nlmsg_fail:
+ nlmsg_free(nlmsg);
+ return ret;
+}
+
+static int wpa_driver_set_tx_rx_nss(struct i802_bss *bss, char *cmd,
+ char *buf, size_t buf_len)
+{
+ struct wpa_driver_nl80211_data *drv;
+ struct nl_msg *nlmsg;
+ struct nlattr *attr;
+ u8 tx_nss, rx_nss;
+ int ret;
+
+ if (!bss || !bss->drv || !cmd) {
+ wpa_printf(MSG_ERROR, "%s:Invalid arguments", __func__);
+ return -EINVAL;
+ }
+ drv = bss->drv;
+ cmd = skip_white_space(cmd);
+ if (*cmd == '\0') {
+ wpa_printf(MSG_ERROR, "tx_nss rx_nss values missing");
+ return -EINVAL;
+ }
+ tx_nss = get_u8_from_string(cmd, &ret);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "Invalid tx_nss value");
+ return -EINVAL;
+ }
+ cmd = move_to_next_str(cmd);
+ if (*cmd == '\0') {
+ wpa_printf(MSG_ERROR, "rx_nss value missing");
+ return -EINVAL;
+ }
+ rx_nss = get_u8_from_string(cmd, &ret);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "Invalid rx_nss value");
+ return -EINVAL;
+ }
+
+ nlmsg = prepare_vendor_nlmsg(drv, bss->ifname,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION);
+ if (!nlmsg) {
+ wpa_printf(MSG_ERROR, "Fail to allocate nlmsg for set_tx_rx_nss cmd");
+ return -ENOMEM;
+ }
+
+ attr = nla_nest_start(nlmsg, NL80211_ATTR_VENDOR_DATA);
+ if (!attr) {
+ ret = -ENOMEM;
+ wpa_printf(MSG_ERROR, "Fail to create nl attributes for set_tx_rx_nss cmd");
+ goto nlmsg_fail;
+ }
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS, tx_nss)) {
+ ret = -ENOMEM;
+ wpa_printf(MSG_ERROR, "Fail to put tx_nss value");
+ goto nlmsg_fail;
+ }
+ if (nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS, rx_nss)) {
+ ret = -ENOMEM;
+ wpa_printf(MSG_ERROR, "Fail to put rx_nss value");
+ goto nlmsg_fail;
+ }
+ nla_nest_end(nlmsg, attr);
+
+ ret = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg, NULL, NULL);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "Fail to send set_tx_rx_nss nlmsg, error:%d", ret);
+ return ret;
+ }
+ return 0;
+nlmsg_fail:
+ nlmsg_free(nlmsg);
+ return ret;
+}
+
int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
size_t buf_len )
{
@@ -6256,6 +6398,14 @@
/* Move cmd by string len and space */
cmd += 19;
return wpa_driver_cmd_send_peer_flush_queue_config(priv, cmd);
+ } else if (os_strncasecmp(cmd, "SET_TX_RX_CHAIN ", 16) == 0) {
+ /* DRIVER SET_TX_RX_CHAIN <TX_CHAINS> <RX_CHAINS> */
+ cmd += 16;
+ return wpa_driver_set_tx_rx_chains(priv, cmd, buf, buf_len);
+ } else if (os_strncasecmp(cmd, "SET_TX_RX_NSS ", 14) == 0) {
+ /* DRIVER SET_TX_RX_NSS <TX_NSS> <RX_NSS> */
+ cmd += 14;
+ return wpa_driver_set_tx_rx_nss(priv, cmd, buf, buf_len);
} else if (os_strncasecmp(cmd, "SPATIAL_REUSE ", 14) == 0) {
cmd += 14;
return wpa_driver_sr_cmd(priv, cmd, buf, buf_len);