Merge f18bebc3a8f42c1778c973fdba64d8813d5bbeac on remote branch

Change-Id: Id6bb1650a691eb7d88a8b31588a1e20aa5904315
diff --git a/qcwcn/wifi_hal/ifaceeventhandler.cpp b/qcwcn/wifi_hal/ifaceeventhandler.cpp
index 8bb22ac..5f98de4 100644
--- a/qcwcn/wifi_hal/ifaceeventhandler.cpp
+++ b/qcwcn/wifi_hal/ifaceeventhandler.cpp
@@ -27,7 +27,7 @@
  *
  * Changes from Qualcomm Innovation Center are provided under the following license:
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted (subject to the limitations in the
@@ -203,6 +203,7 @@
     mRequestId = id;
     mSubcmd = subcmd;
     registerHandler(mSubcmd);
+    memset(tb, 0, sizeof(struct nlattr *) * (NL80211_ATTR_MAX + 1));
     ALOGV("wifiEventHandler %p constructed", this);
 }
 
diff --git a/qcwcn/wifi_hal/llstats.cpp b/qcwcn/wifi_hal/llstats.cpp
index 3bed31c..2b3b325 100644
--- a/qcwcn/wifi_hal/llstats.cpp
+++ b/qcwcn/wifi_hal/llstats.cpp
@@ -15,7 +15,7 @@
 
  * Changes from Qualcomm Innovation Center are provided under the following license:
 
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -60,6 +60,7 @@
     mRadioStatsSize = 0;
     mNumRadios = 0;
     mNumRadiosAllocated = 0;
+    mRequestId = 0;
 }
 
 LLStatsCommand::~LLStatsCommand()
diff --git a/qcwcn/wifi_hal/nan.cpp b/qcwcn/wifi_hal/nan.cpp
index 1690a86..a73126b 100644
--- a/qcwcn/wifi_hal/nan.cpp
+++ b/qcwcn/wifi_hal/nan.cpp
@@ -977,8 +977,8 @@
     wifi_handle handle = getWifiHandle(iface);
     hal_info *info = getHalInfo(handle);
 
-    if (iface_name == NULL) {
-        ALOGE("%s: Invalid Nan Data Interface Name. \n", __FUNCTION__);
+    if (iface_name == NULL || if_nametoindex(iface_name) == 0) {
+        ALOGE("%s: Invalid/Unknown Nan Data Interface Name. \n", __FUNCTION__);
         return WIFI_ERROR_INVALID_ARGS;
     }
 
@@ -988,11 +988,33 @@
         return WIFI_ERROR_UNKNOWN;
     }
 
+    // NL80211_CMD_DEL_INTERFACE internally takes care of NDP cleanup.
+    if ((check_feature(QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI,
+                       &info->driver_supported_features)) &&
+        if_nametoindex(iface_name)) {
+        wifiConfigCommand = new WiFiConfigCommand(handle,
+                                                  get_requestid(), 0, 0);
+        if (wifiConfigCommand == NULL) {
+            ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+            return WIFI_ERROR_UNKNOWN;
+        }
+        wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
+        wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
+                                   if_nametoindex(iface_name));
+        /* Send the NL msg. */
+        wifiConfigCommand->waitForRsp(false);
+        if (wifiConfigCommand->requestEvent() != WIFI_SUCCESS) {
+            ALOGE("%s: Delete intf failed", __FUNCTION__);
+        }
+        delete wifiConfigCommand;
+        return WIFI_SUCCESS;
+    }
+
     ret = nan_initialize_vendor_cmd(iface,
                                     &nanCommand);
     if (ret != WIFI_SUCCESS) {
         ALOGE("%s: Initialization failed", __FUNCTION__);
-        goto delete_ndi;
+        return ret;
     }
 
     /* Add the vendor specific attributes for the NL command. */
@@ -1023,28 +1045,6 @@
 
 cleanup:
     delete nanCommand;
-
-delete_ndi:
-    if ((check_feature(QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI,
-                       &info->driver_supported_features)) &&
-        if_nametoindex(iface_name)) {
-        wifiConfigCommand = new WiFiConfigCommand(handle,
-                                                  get_requestid(), 0, 0);
-        if (wifiConfigCommand == NULL) {
-            ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
-            return WIFI_ERROR_UNKNOWN;
-        }
-        wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
-        wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX,
-                                   if_nametoindex(iface_name));
-        /* Send the NL msg. */
-        wifiConfigCommand->waitForRsp(false);
-        if (wifiConfigCommand->requestEvent() != WIFI_SUCCESS) {
-            ALOGE("%s: Delete intf failed", __FUNCTION__);
-        }
-        delete wifiConfigCommand;
-    }
-
     return ret;
 }
 
diff --git a/qcwcn/wifi_hal/radio_mode.cpp b/qcwcn/wifi_hal/radio_mode.cpp
index e652bb0..8cbbab2 100644
--- a/qcwcn/wifi_hal/radio_mode.cpp
+++ b/qcwcn/wifi_hal/radio_mode.cpp
@@ -27,7 +27,7 @@
 
  * Changes from Qualcomm Innovation Center are provided under the following license:
 
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -95,6 +95,7 @@
         : WifiVendorCommand(handle, id, vendor_id, subcmd)
 {
     memset(&mHandler, 0, sizeof(mHandler));
+    mwifi_iface_mac_info = NULL;
     if (registerVendorHandler(vendor_id, subcmd)) {
         /* Error case should not happen print log */
         ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
diff --git a/qcwcn/wifi_hal/tdls.cpp b/qcwcn/wifi_hal/tdls.cpp
index 2082fef..c794a56 100644
--- a/qcwcn/wifi_hal/tdls.cpp
+++ b/qcwcn/wifi_hal/tdls.cpp
@@ -27,7 +27,7 @@
 
  * Changes from Qualcomm Innovation Center are provided under the following license:
 
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -51,6 +51,7 @@
     memset(&mHandler, 0, sizeof(mHandler));
     memset(&mTDLSgetStatusRspParams, 0, sizeof(wifi_tdls_status));
     mRequestId = 0;
+    memset(&mTDLSgetCaps, 0, sizeof(wifiTdlsCapabilities));
 }
 
 TdlsCommand::~TdlsCommand()
diff --git a/qcwcn/wifi_hal/wifihal_vendor.cpp b/qcwcn/wifi_hal/wifihal_vendor.cpp
index 4837e63..e05e407 100644
--- a/qcwcn/wifi_hal/wifihal_vendor.cpp
+++ b/qcwcn/wifi_hal/wifihal_vendor.cpp
@@ -28,7 +28,7 @@
 
  * Changes from Qualcomm Innovation Center are provided under the following license:
 
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -74,6 +74,7 @@
     memset(&mStats, 0,sizeof(nud_stats));
     mpktInfo = NULL;
     mnumStats = 0;
+    memset(&mHandler, 0, sizeof(pkt_stats_result_handler));
 }
 
 NUDStatsCommand::~NUDStatsCommand()
diff --git a/qcwcn/wifi_hal/wifilogger.cpp b/qcwcn/wifi_hal/wifilogger.cpp
index 384633a..a7cb0ab 100644
--- a/qcwcn/wifi_hal/wifilogger.cpp
+++ b/qcwcn/wifi_hal/wifilogger.cpp
@@ -27,7 +27,7 @@
  *
  * Changes from Qualcomm Innovation Center are provided under the following license:
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted (subject to the limitations in the
@@ -840,6 +840,7 @@
     mWaitforRsp = false;
     mMoreData = false;
     mSupportedSet = NULL;
+    mGetWakeStats = NULL;
 }
 
 WifiLoggerCommand::~WifiLoggerCommand()
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
index a647ccd..279e020 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -4811,10 +4811,8 @@
 	ret = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
 			 features_info_handler, &info);
 
-	if (ret || !info.flags) {
-		nlmsg_free(nlmsg);
+	if (ret || !info.flags)
 		return 0;
-	}
 
 	if (check_feature(QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT, &info)) {
 		twt_async_support = 1;
@@ -4859,35 +4857,34 @@
 	twt_nl_msg = prepare_nlmsg(drv, ifname, NL80211_CMD_VENDOR,
 				   QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT, 0);
 	if (!twt_nl_msg) {
-		ret = -EINVAL;
-		goto err_msg;
+		wpa_printf(MSG_ERROR, "Fail to allocate nlmsg for TWT cmd");
+		return -ENOMEM;
 	}
 
 	ret = pack_nlmsg_twt_params(twt_nl_msg, param, twt_oper);
 	if (ret) {
+		ret = -EINVAL;
 		goto err_msg;
 	}
 
-	switch(twt_oper) {
+	switch (twt_oper) {
 	case QCA_WLAN_TWT_GET:
 	case QCA_WLAN_TWT_GET_CAPABILITIES:
 	case QCA_WLAN_TWT_GET_STATS:
 		*status = send_nlmsg((struct nl_sock *)drv->global->nl,
 				     twt_nl_msg, twt_response_handler,
 				     &reply_info);
-		if (*status != 0) {
+		if (*status) {
 			wpa_printf(MSG_ERROR, "Failed to send nlmsg - err %d", *status);
-			ret = -EINVAL;
-			goto err_msg;
+			return -EINVAL;
 		}
 		break;
 	case QCA_WLAN_TWT_CLEAR_STATS:
 		*status = send_nlmsg((struct nl_sock *)drv->global->nl,
 				      twt_nl_msg, NULL, NULL);
-		if (*status != 0) {
+		if (*status) {
 			wpa_printf(MSG_ERROR, "Failed to send nlmsg - err %d", *status);
-			ret = -EINVAL;
-			goto err_msg;
+			return -EINVAL;
 		}
 		break;
 	case QCA_WLAN_TWT_SET:
@@ -4896,17 +4893,16 @@
 	case QCA_WLAN_TWT_RESUME:
 	case QCA_WLAN_TWT_NUDGE:
 	case QCA_WLAN_TWT_SET_PARAM:
-		if(check_wifi_twt_async_feature(drv, ifname) == 0) {
+		if (check_wifi_twt_async_feature(drv, ifname) == 0) {
 			wpa_printf(MSG_ERROR, "Asynchronous TWT Feature is missing");
 			ret = -EINVAL;
 			goto err_msg;
 		} else {
 			*status = send_nlmsg((struct nl_sock *)drv->global->nl,
 					     twt_nl_msg, NULL, NULL);
-			if (*status != 0) {
+			if (*status) {
 				wpa_printf(MSG_ERROR, "Failed to send nlmsg - err %d", *status);
-				ret = -EINVAL;
-				goto err_msg;
+				return -EINVAL;
 			}
 		}
 		break;
@@ -4918,7 +4914,7 @@
 	return ret;
 
 err_msg:
-	wpa_printf(MSG_ERROR, "sent nlmsg - status %d", *status);
+	wpa_printf(MSG_ERROR, "sent nlmsg - status %d", ret);
 	nlmsg_free(twt_nl_msg);
 	return ret;
 }
@@ -5950,6 +5946,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 +6394,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);