qcacld-3.0: Add "unit_test" IOCTL

Add a unit test IOCTL for components to hook their unit tests into.

Change-Id: I676394771a35263454bc0f6d13174fbb7d957e67
CRs-Fixed: 2274538
diff --git a/Kbuild b/Kbuild
index a32efb8..0802c09 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1636,6 +1636,7 @@
 		-DHDD_TRACE_RECORD
 endif
 endif
+cppflags-$(CONFIG_UNIT_TEST) += -DWLAN_UNIT_TEST
 cppflags-$(CONFIG_WLAN_DEBUG_CRASH_INJECT) += -DCONFIG_WLAN_DEBUG_CRASH_INJECT
 cppflags-$(CONFIG_FEATURE_UNIT_TEST_SUSPEND) += -DWLAN_SUSPEND_RESUME_TEST
 
diff --git a/configs/default_defconfig b/configs/default_defconfig
index e1d7297..570a207 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -559,6 +559,7 @@
 ifeq ($(CONFIG_SLUB_DEBUG_ON), y)
 	CONFIG_FEATURE_UNIT_TEST_SUSPEND := y
 	CONFIG_LEAK_DETECTION := y
+	CONFIG_UNIT_TEST := y
 endif
 
 # enable unit-test suspend for napier builds
diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c
index d2e323d..9c9d31c 100644
--- a/core/hdd/src/wlan_hdd_wext.c
+++ b/core/hdd/src/wlan_hdd_wext.c
@@ -66,6 +66,7 @@
 #include "qc_sap_ioctl.h"
 #include "sme_api.h"
 #include "wma_types.h"
+#include "qdf_str.h"
 #include "qdf_trace.h"
 #include "wlan_hdd_assoc.h"
 #include "wlan_hdd_ioctl.h"
@@ -1809,6 +1810,19 @@
 #define WE_SET_AP_WPS_IE     4
 #define WE_SET_CONFIG        5
 
+/*
+ * <ioctl>
+ * unit_test - execute component-level unit tests
+ *
+ * @INPUT: string - the name of the component to test.
+ *	All tests are executed if unspecified
+ * @OUTPUT: None
+ *
+ * Usage: Internal only
+ * </ioctl>
+ */
+#define WE_UNIT_TEST         6
+
 /* Private ioctls and their sub-ioctls */
 #define WLAN_PRIV_SET_THREE_INT_GET_NONE   (SIOCIWFIRSTPRIV + 4)
 #define WE_SET_WLAN_DBG      1
@@ -5284,6 +5298,35 @@
 	return ret;
 }
 
+#ifdef WLAN_UNIT_TEST
+static int hdd_we_unit_test(struct hdd_context *hdd_ctx, const char *component)
+{
+	uint32_t errors = 0;
+	bool all = !component || !component[0];
+
+	if (all)
+		hdd_info("Starting unit tests for all components");
+	else
+		hdd_info("Starting unit tests for component '%s'", component);
+
+	/* add future tests here */
+
+	if (errors) {
+		hdd_err("Unit tests failed with %u errors", errors);
+		return -EPERM;
+	}
+
+	hdd_info("Unit tests passed successfully");
+
+	return 0;
+}
+#else
+static int hdd_we_unit_test(struct hdd_context *hdd_ctx, const char *component)
+{
+	return -EOPNOTSUPP;
+}
+#endif /* WLAN_UNIT_TEST */
+
 /**
  * iw_setchar_getnone() - Generic "set string" private ioctl handler
  * @dev: device upon which the ioctl was received
@@ -5297,10 +5340,10 @@
 				struct iw_request_info *info,
 				union iwreq_data *wrqu, char *extra)
 {
-	QDF_STATUS vstatus;
+	QDF_STATUS status;
 	int sub_cmd;
 	int ret;
-	char *pBuffer = NULL;
+	char *str_arg = NULL;
 	struct hdd_adapter *adapter = (netdev_priv(dev));
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	struct hdd_config *pConfig = hdd_ctx->config;
@@ -5332,24 +5375,24 @@
 	sub_cmd = s_priv_data.flags;
 
 	/* ODD number is used for set, copy data using copy_from_user */
-	pBuffer = mem_alloc_copy_from_user_helper(s_priv_data.pointer,
+	str_arg = mem_alloc_copy_from_user_helper(s_priv_data.pointer,
 						  s_priv_data.length);
-	if (NULL == pBuffer) {
+	if (!str_arg) {
 		hdd_err("mem_alloc_copy_from_user_helper fail");
 		return -ENOMEM;
 	}
 
 	hdd_debug("Received length: %d data: %s",
-			s_priv_data.length, pBuffer);
+			s_priv_data.length, str_arg);
 
 	switch (sub_cmd) {
 	case WE_WOWL_ADD_PTRN:
 		hdd_debug("ADD_PTRN");
-		hdd_add_wowl_ptrn(adapter, pBuffer);
+		hdd_add_wowl_ptrn(adapter, str_arg);
 		break;
 	case WE_WOWL_DEL_PTRN:
 		hdd_debug("DEL_PTRN");
-		hdd_del_wowl_ptrn(adapter, pBuffer);
+		hdd_del_wowl_ptrn(adapter, str_arg);
 		break;
 	case WE_NEIGHBOR_REPORT_REQUEST:
 	{
@@ -5367,7 +5410,7 @@
 					(s_priv_data.length - 1) >
 					32 ? 32 : (s_priv_data.length - 1);
 				qdf_mem_copy(neighborReq.ssid.ssId,
-					     pBuffer,
+					     str_arg,
 					     neighborReq.ssid.length);
 			}
 
@@ -5400,21 +5443,25 @@
 		hdd_debug("Received WE_SET_AP_WPS_IE, won't process");
 		break;
 	case WE_SET_CONFIG:
-		vstatus = hdd_execute_global_config_command(hdd_ctx, pBuffer);
-		if (QDF_STATUS_SUCCESS != vstatus)
+		status = hdd_execute_global_config_command(hdd_ctx, str_arg);
+		if (QDF_IS_STATUS_ERROR(status))
 			ret = -EINVAL;
 
 		break;
+	case WE_UNIT_TEST:
+		ret = hdd_we_unit_test(hdd_ctx, str_arg);
+		break;
 	default:
 	{
-		hdd_err("Invalid sub command %d",
-		       sub_cmd);
+		hdd_err("Invalid sub command %d", sub_cmd);
 		ret = -EINVAL;
 		break;
 	}
 	}
-	qdf_mem_free(pBuffer);
+
+	qdf_mem_free(str_arg);
 	hdd_exit();
+
 	return ret;
 }
 
@@ -9724,6 +9771,13 @@
 	 0,
 	 "setConfig"},
 
+#ifdef WLAN_UNIT_TEST
+	{WE_UNIT_TEST,
+	 IW_PRIV_TYPE_CHAR | 512,
+	 0,
+	 "unit_test"},
+#endif
+
 	/* handlers for main ioctl */
 	{WLAN_PRIV_SET_THREE_INT_GET_NONE,
 	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,