Browse Source

qcacmn: Add basic infra for connection manager UTF

Add basic infra for connection manager UTF

Change-Id: Id111a4bcda970e927b73441be55de4d33a694796
Himanshu Batra 5 năm trước cách đây
mục cha
commit
569cc296ed

+ 7 - 1
cfg/inc/cfg_converged.h

@@ -44,6 +44,11 @@
 #else
 #define CFG_CFR_ALL
 #endif
+#ifdef FEATURE_CM_UTF_ENABLE
+#include <wlan_cm_utf.h>
+#else
+#define CFG_WLAN_CM_UTF_PARAM
+#endif
 
 #define CFG_CONVERGED_ALL \
 		CFG_SCAN_ALL \
@@ -54,7 +59,8 @@
 		CFG_HIF \
 		CFG_DCS_ALL \
 		CFG_CFR_ALL \
-		CFG_MLME_SCORE_ALL
+		CFG_MLME_SCORE_ALL \
+		CFG_WLAN_CM_UTF_PARAM
 
 #endif /* __CFG_CONVERGED_H */
 

+ 1 - 0
spectral/Kbuild

@@ -37,6 +37,7 @@ INCS += -I$(obj)/$(DEPTH)/pld/inc
 INCS += -I$(obj)/$(DEPTH)/component_dev/dp/inc
 INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/mlme/connection_mgr/dispatcher/inc
 INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/thermal/dispatcher/inc
+INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/mlme/connection_mgr/utf/inc
 
 ifeq ($(WLAN_CONV_CRYPTO_SUPPORTED), 1)
 INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cmn_services/crypto/inc

+ 277 - 0
umac/mlme/connection_mgr/utf/inc/wlan_cm_utf.h

@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * DOC: Implements CM UTF
+ */
+
+#ifndef WLAN_CM_UTF_H
+#define WLAN_CM_UTF_H
+
+#include <qdf_debugfs.h>
+#include <qdf_mem.h>
+#include <qdf_trace.h>
+#include <qdf_module.h>
+#include <qdf_event.h>
+#include <qdf_defer.h>
+#include <wlan_cm_public_struct.h>
+#include <wlan_mgmt_txrx_utils_api.h>
+#include <wlan_reg_services_api.h>
+#include <wlan_scan_tgt_api.h>
+#include <wlan_cfg80211.h>
+
+#define NUM_UTF_DEBUGFS_INFOS 2
+
+/*
+ * <ini>
+ * wlan_cm_utf - WLAN CM UTF Configuration
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to config wlan cm utf
+ *
+ * Related: None
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+#define CFG_WLAN_CM_UTF CFG_INI_UINT( \
+	"wlan_cm_utf", \
+	0, \
+	1, \
+	0, \
+	CFG_VALUE_OR_DEFAULT, \
+	"WLAN CM UTF Configuration")
+
+#define CFG_WLAN_CM_UTF_PARAM CFG(CFG_WLAN_CM_UTF)
+/**
+ * enum wlan_cm_utf_test - CM UTF Test ID
+ * @CM_UTF_ID_CONNECT_SUCCESS: Connect Succes
+ * @CM_UTF_ID_DISCONNECT_SUCCESS: Disconnect Success
+ * @CM_UTF_ID_PEER_CREATE_FAILURE: Peer Create Failure
+ * @CM_UTF_ID_PEER_CREATE_TIMEOUT: No Peer Create Response
+ * @CM_UTF_ID_PEER_DELETE_TIMEOUT: No Peer Delete Response
+ * @CM_UTF_ID_AUTH_FAILURE: Auth Req Failure
+ * @CM_UTF_ID_AUTH_TIMEOUT: No Auth Response
+ * @CM_UTF_ID_ASSOC_FAILURE: Assoc Req Failure
+ * @CM_UTF_ID_ASSOC_TIMEOUT: No Assoc Response
+ * @CM_UTF_ID_CONNECT_SCAN_FAILURE: SSID Not Found
+ * @CM_UTF_ID_CONNECT_SER_TIMEOUT: Serialization Active Cmd Timeout for Connect
+ * @CM_UTF_ID_DISCONNECT_SER_TIMEOUT: Ser Active Cmd Timeout for Disconnect
+ * @CM_UTF_ID_CONNECT_SER_FAILED: Serialization Cmd Queue Failure for Connect
+ * @CM_UTF_ID_DISCONNECT_SER_FAILED: Ser Cmd Queue Failure for Disconnect
+ */
+enum wlan_cm_utf_test {
+	CM_UTF_ID_CONNECT_SUCCESS,
+	CM_UTF_ID_DISCONNECT_SUCCESS,
+	CM_UTF_ID_PEER_CREATE_FAILURE,
+	CM_UTF_ID_PEER_CREATE_TIMEOUT,
+	CM_UTF_ID_PEER_DELETE_TIMEOUT,
+	CM_UTF_ID_AUTH_FAILURE,
+	CM_UTF_ID_AUTH_TIMEOUT,
+	CM_UTF_ID_ASSOC_FAILURE,
+	CM_UTF_ID_ASSOC_TIMEOUT,
+	CM_UTF_ID_CONNECT_SCAN_FAILURE,
+	CM_UTF_ID_CONNECT_SER_TIMEOUT,
+	CM_UTF_ID_DISCONNECT_SER_TIMEOUT,
+	CM_UTF_ID_CONNECT_SER_FAILED,//Need ser utf
+	CM_UTF_ID_DISCONNECT_SER_FAILED,//Need ser utf
+	CM_UTF_ID_MAX,
+};
+
+/**
+ * enum wlan_cm_utf_evt - CM UTF Resp event
+ * @CM_UTF_BSS_PEER_CREATE_RESP: Peer Create Response
+ * @CM_UTF_BSS_PEER_DELETE_RESP: Peer Delete Response
+ * @CM_UTF_CONNECT_RESP: Connect Response
+ * @CM_UTF_DISCONNECT_RESP: Disconnect Response
+ * @CM_UTF_PEER_DELETE_IND: Peer Delete Indication
+ */
+enum wlan_cm_utf_evt {
+	CM_UTF_BSS_PEER_CREATE_RESP,
+	CM_UTF_BSS_PEER_DELETE_RESP,
+	CM_UTF_CONNECT_RESP,
+	CM_UTF_DISCONNECT_RESP,
+	CM_UTF_PEER_DELETE_IND,
+};
+
+/**
+ * struct wlan_cm_utf_node- CM UTF node to hold CM req info
+ * @wlan_cm_utf_evt: CM UTF Resp event
+ * @peer_mac: Peer Mac
+ * @conn_req: Connect Request
+ * @disconn_req: Disconnect Request
+ */
+struct wlan_cm_utf_node {
+	enum wlan_cm_utf_evt evt_id;
+	struct qdf_mac_addr *peer_mac;
+	struct wlan_cm_vdev_connect_req conn_req;
+	struct wlan_cm_vdev_discon_req disconn_req;
+};
+
+/**
+ * struct wlan_cm_utf- CM UTF handle
+ * @vdev: Vdev object
+ * @debugfs_de: debugfs entry
+ * @test_id: Test case Id
+ * @req: cfg80211 connect request params
+ * @cm_utf_timer: CM UTF timer
+ * @cm_utf_test_timer: CM UTF timer for each test
+ * @utf_node: CM UTF node to hold CM req info
+ * @cm_utf_work: CM UTF work queue for processing events
+ */
+struct wlan_cm_utf {
+	qdf_list_node_t cm_utf_node;
+	struct wlan_objmgr_vdev *vdev;
+	struct dentry *debugfs_de[NUM_UTF_DEBUGFS_INFOS];
+	enum wlan_cm_utf_test test_id;
+	struct wlan_cm_connect_req req;
+	qdf_timer_t  cm_utf_timer;
+	qdf_timer_t  cm_utf_test_timer;
+	struct wlan_cm_utf_node utf_node;
+	uint32_t last_cmd_id;
+	enum wlan_cm_source last_cmd_source;
+	qdf_work_t cm_utf_work;
+};
+
+/*
+ * Debugfs read/write functions
+ */
+/**
+ * wlan_cm_utf_cm_test_id_show() - debugfs function to display CM test case name
+ * @m: seq_file handle
+ * @v: not used, offset of read
+ */
+int wlan_cm_utf_cm_test_id_show(qdf_debugfs_file_t m, void *v);
+
+int wlan_cm_utf_scan_db_update_show(qdf_debugfs_file_t m, void *v);
+
+/**
+ * wlan_cm_utf_cm_test_id_write() - debugfs write to start CM UTF test
+ *
+ * @file: file handler to access cm utf handle
+ * @buf: received data buffer
+ * @count: length of received buffer
+ * @ppos: Not used
+ *
+ * Return: count
+ */
+ssize_t wlan_cm_utf_cm_test_id_write(struct file *file,
+				     const char __user *buf,
+				     size_t count, loff_t *ppos);
+
+/**
+ * wlan_cm_utf_scan_db_update_write() - debugfs write to add manual scan entry
+ *
+ * @file: file handler to access cm utf handle
+ * @buf: received data buffer
+ * @count: length of received buffer
+ * @ppos: Not used
+ *
+ * Return: count
+ */
+ssize_t wlan_cm_utf_scan_db_update_write(struct file *file,
+					 const char __user *buf,
+					 size_t count, loff_t *ppos);
+
+/**
+ * wlan_cm_utf_attach: Connection manager UTF init API
+ * @vdev: Vdev object
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_utf_attach(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_cm_utf_detach: Connection manager UTF deinit API
+ * @vdev: Vdev object
+ *
+ * Return: QDF_STATUS
+ */
+void wlan_cm_utf_detach(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_cm_utf_bss_peer_create_req: Connection manager UTF bss peer
+ * create request handler
+ * @vdev: VDEV object
+ * @peer_mac: Peer mac address
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_utf_bss_peer_create_req(struct wlan_objmgr_vdev *vdev,
+					   struct qdf_mac_addr *peer_mac);
+
+/**
+ * wlan_cm_utf_connect_req_active: Connection manager UTF handler when connect
+ * request is activated
+ * @vdev: VDEV object
+ * @vdev_connect_req: Vdev connect request
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_utf_connect_req_active(
+			struct wlan_objmgr_vdev *vdev,
+			struct wlan_cm_vdev_connect_req *vdev_connect_req);
+
+/**
+ * wlan_cm_utf_connect_req: Connection manager UTF connect request handler
+ * @vdev: VDEV object
+ * @vdev_connect_req: Vdev connect request
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_utf_connect_req(
+			struct wlan_objmgr_vdev *vdev,
+			struct wlan_cm_vdev_connect_req *vdev_connect_req);
+
+/**
+ * wlan_cm_utf_disconnect_req: Connection manager UTF disconnect
+ * request handler
+ * @vdev: VDEV object
+ * @vdev_connect_req: Vdev connect request
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_utf_disconnect_req(
+		struct wlan_objmgr_vdev *vdev,
+		struct wlan_cm_vdev_discon_req *vdev_disconnect_req);
+
+/**
+ * wlan_cm_utf_bss_peer_delete_req: Connection manager UTF bss peer
+ * delete request handler
+ * @vdev: VDEV object
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_utf_bss_peer_delete_req(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_cm_utf_vdev_down: Connection manager UTF vdev down request handler
+ * @vdev: VDEV object
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_utf_vdev_down(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * osif_cm_utf_register_cb() - API to register connection manager callbacks
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS osif_cm_utf_register_cb(void);
+#endif //WLAN_CM_UTF_H

+ 1032 - 0
umac/mlme/connection_mgr/utf/src/wlan_cm_utf_main.c

@@ -0,0 +1,1032 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * DOC: Implements CM UTF
+ */
+
+#ifdef FEATURE_CM_UTF_ENABLE
+#include <wlan_cm_utf.h>
+#include <wlan_cm_api.h>
+#include <qdf_str.h>
+#include <wlan_cm_ucfg_api.h>
+#include <include/wlan_mlme_cmn.h>
+
+#define CM_UTF_LIST_SIZE 1
+
+qdf_list_t wlan_cm_utf_list;
+
+static const char *cm_utf_test_names[] = {
+	"CONNECT_SUCCESS",
+	"DISCONNECT_SUCCESS",
+	"PEER_CREATE_FAILURE",
+	"PEER_CREATE_TIMEOUT",
+	"PEER_DELETE_TIMEOUT",
+	"AUTH_FAILURE",
+	"AUTH_TIMEOUT",
+	"ASSOC_FAILURE",
+	"ASSOC_TIMEOUT",
+	"CONNECT_SCAN_FAILURE",
+	"CONNECT_SER_TIMEOUT",
+	"DISCONNECT_SER_TIMEOUT",
+	"CONNECT_SER_FAILED",
+	"DISCONNECT_SER_FAIL",
+};
+
+/* Structure to maintain debug information */
+struct cm_utf_debugfs_info {
+	const char *name;
+	const struct file_operations *ops;
+};
+
+#define DEBUG_FOO(func_base) { .name = #func_base,                      \
+	.ops = &wlan_cm_utf_##func_base##_ops }
+
+/*
+ * wlan_cm_utf_##func_base##_open() - Open debugfs entry for respective command
+ * and event buffer.
+ * @inode: node for debug dir entry
+ * @file: file handler
+ *
+ * Return: open status
+ */
+#define GENERATE_DEBUG_STRUCTS(func_base)                                     \
+	static int wlan_cm_utf_##func_base##_open(struct inode *inode,        \
+			struct file *file)                                    \
+	{                                                                     \
+		return single_open(file, wlan_cm_utf_##func_base##_show,      \
+				   inode->i_private);                         \
+	}                                                                     \
+									      \
+	static const struct file_operations wlan_cm_utf_##func_base##_ops = { \
+		.open           = wlan_cm_utf_##func_base##_open,             \
+		.read           = seq_read,                                   \
+		.llseek         = seq_lseek,                                  \
+		.write          = wlan_cm_utf_##func_base##_write,            \
+		.release        = single_release,                             \
+	};
+
+GENERATE_DEBUG_STRUCTS(scan_db_update);
+GENERATE_DEBUG_STRUCTS(cm_test_id);
+
+struct cm_utf_debugfs_info cm_utf_debugfs_infos[NUM_UTF_DEBUGFS_INFOS] = {
+	DEBUG_FOO(scan_db_update),
+	DEBUG_FOO(cm_test_id),
+};
+
+/**
+ * wlan_cm_debugfs_create() - Create debugfs entry for cm db
+ * @cm_utf: CM UTF object
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS wlan_cm_utf_debugfs_create(struct wlan_cm_utf *cm_utf)
+{
+	struct wlan_objmgr_vdev *vdev = cm_utf->vdev;
+	struct wlan_objmgr_pdev *pdev;
+	uint8_t pdev_id;
+	uint8_t vdev_id;
+	char name[32];
+
+	if (cm_utf->debugfs_de[0] || cm_utf->debugfs_de[1]) {
+		mlme_info("CM UTF debugfs file already exist");
+		return QDF_STATUS_SUCCESS;
+	}
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		mlme_err("Pdev is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
+	vdev_id = wlan_vdev_get_id(vdev);
+
+	snprintf(name, sizeof(name), "CM_UTF_PDEV%u_VDEV%u_SCAN",
+		 pdev_id, vdev_id);
+	cm_utf->debugfs_de[0] = debugfs_create_file(
+				name, 0644, qdf_debugfs_get_root(),
+				cm_utf, cm_utf_debugfs_infos[0].ops);
+
+	if (!cm_utf->debugfs_de[0]) {
+		mlme_err("Failed to create debugfs entry");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	snprintf(name, sizeof(name), "CM_UTF_PDEV%u_VDEV%u_UTF",
+		 pdev_id, vdev_id);
+	cm_utf->debugfs_de[1] = debugfs_create_file(
+				name, 0644, qdf_debugfs_get_root(),
+				cm_utf, cm_utf_debugfs_infos[1].ops);
+
+	if (!cm_utf->debugfs_de[1]) {
+		mlme_err("Failed to create debugfs entry");
+		debugfs_remove(cm_utf->debugfs_de[0]);
+		cm_utf->debugfs_de[0] = NULL;
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wlan_cm_utf_debugfs_remove: Remove connection manager UTF debugfs entries
+ * @cm_utf: Connection Manager UTF object
+ *
+ * Return: None
+ */
+static void wlan_cm_utf_debugfs_remove(struct wlan_cm_utf *cm_utf)
+{
+	if (cm_utf->debugfs_de[0]) {
+		qdf_debugfs_remove_file(cm_utf->debugfs_de[0]);
+		cm_utf->debugfs_de[0] = NULL;
+	}
+
+	if (cm_utf->debugfs_de[1]) {
+		qdf_debugfs_remove_file(cm_utf->debugfs_de[1]);
+		cm_utf->debugfs_de[1] = NULL;
+	}
+}
+
+/**
+ * wlan_cm_utf_bss_peer_create_rsp: Connection manager UTF bss peer
+ * create response
+ * @cm_utf: Connection Manager UTF object
+ *
+ * Return: None
+ */
+static void wlan_cm_utf_bss_peer_create_rsp(struct wlan_cm_utf *cm_utf)
+{
+	struct qdf_mac_addr *peer_mac;
+	QDF_STATUS status;
+
+	peer_mac = cm_utf->utf_node.peer_mac;
+	switch (cm_utf->test_id) {
+	case CM_UTF_ID_PEER_CREATE_FAILURE:
+		status = QDF_STATUS_E_FAILURE;
+		break;
+	default:
+		status = QDF_STATUS_SUCCESS;
+		break;
+	}
+	wlan_cm_bss_peer_create_rsp(cm_utf->vdev, status, peer_mac);
+}
+
+/**
+ * wlan_cm_utf_bss_peer_delete_rsp: Connection manager UTF bss peer
+ * delete response
+ * @cm_utf: Connection Manager UTF object
+ *
+ * Return: None
+ */
+static void wlan_cm_utf_bss_peer_delete_rsp(struct wlan_cm_utf *cm_utf)
+{
+	wlan_cm_bss_peer_delete_rsp(cm_utf->vdev, QDF_STATUS_SUCCESS);
+}
+
+/**
+ * wlan_cm_utf_connect_rsp: Connection manager UTF connect response
+ * @cm_utf: Connection Manager UTF object
+ *
+ * Return: None
+ */
+static void wlan_cm_utf_connect_rsp(struct wlan_cm_utf *cm_utf)
+{
+	struct wlan_cm_connect_rsp *cm_conn_rsp;
+	struct wlan_cm_vdev_connect_req conn_req = cm_utf->utf_node.conn_req;
+
+	cm_conn_rsp = qdf_mem_malloc(sizeof(struct wlan_cm_connect_rsp));
+	if (!cm_conn_rsp) {
+		mlme_err("failed ta allocate memory");
+		return;
+	}
+	qdf_mem_zero(cm_conn_rsp, sizeof(struct wlan_cm_connect_rsp));
+
+	cm_conn_rsp->vdev_id = conn_req.vdev_id;
+	cm_conn_rsp->cm_id = conn_req.cm_id;
+	cm_conn_rsp->aid = 1;
+	cm_conn_rsp->connect_status = QDF_STATUS_E_FAILURE;
+	cm_conn_rsp->reason_code = 0;
+	cm_conn_rsp->freq = conn_req.bss->entry->channel.chan_freq;
+	cm_conn_rsp->connect_ies.bcn_probe_rsp.ptr =
+				conn_req.bss->entry->raw_frame.ptr;
+	cm_conn_rsp->connect_ies.bcn_probe_rsp.len =
+				conn_req.bss->entry->raw_frame.len;
+	cm_conn_rsp->bssid = conn_req.bss->entry->bssid;
+	cm_conn_rsp->ssid = conn_req.bss->entry->ssid;
+
+	switch (cm_utf->test_id) {
+	case CM_UTF_ID_AUTH_FAILURE:
+		cm_conn_rsp->reason = CM_AUTH_FAILED;
+		break;
+	case CM_UTF_ID_AUTH_TIMEOUT:
+		cm_conn_rsp->reason = CM_AUTH_TIMEOUT;
+		break;
+	case CM_UTF_ID_ASSOC_FAILURE:
+		cm_conn_rsp->reason = CM_ASSOC_FAILED;
+		break;
+	case CM_UTF_ID_ASSOC_TIMEOUT:
+		cm_conn_rsp->reason = CM_ASSOC_TIMEOUT;
+		break;
+	default:
+		cm_conn_rsp->connect_status = QDF_STATUS_SUCCESS;
+		break;
+	}
+	wlan_cm_connect_rsp(cm_utf->vdev, cm_conn_rsp);
+	qdf_mem_free(cm_conn_rsp);
+}
+
+/**
+ * wlan_cm_utf_disconnect_rsp: Connection manager UTF disconnect response
+ * @cm_utf: Connection Manager UTF object
+ *
+ * Return: None
+ */
+static void wlan_cm_utf_disconnect_rsp(struct wlan_cm_utf *cm_utf)
+{
+	struct wlan_cm_discon_rsp *cm_discon_rsp;
+
+	cm_discon_rsp = qdf_mem_malloc(sizeof(struct wlan_cm_discon_rsp));
+	if (!cm_discon_rsp) {
+		mlme_err("failed ta allocate memory");
+		return;
+	}
+	cm_discon_rsp->req = cm_utf->utf_node.disconn_req;
+
+	wlan_cm_disconnect_rsp(cm_utf->vdev, cm_discon_rsp);
+	qdf_mem_free(cm_discon_rsp);
+}
+
+/**
+ * wlan_cm_utf_peer_del_ind: Connection manager UTF peer delete indication
+ * @cm_utf: Connection Manager UTF object
+ *
+ * Return: None
+ */
+static void wlan_cm_utf_peer_del_ind(struct wlan_cm_utf *cm_utf)
+{
+	struct qdf_mac_addr peer_mac;
+
+	peer_mac.bytes[0] = 0x1;
+	peer_mac.bytes[1] = 0x2;
+	peer_mac.bytes[2] = 0x3;
+	peer_mac.bytes[3] = 0x4;
+	peer_mac.bytes[4] = 0x5;
+	peer_mac.bytes[5] = 0x6;
+
+	wlan_cm_bss_peer_delete_ind(cm_utf->vdev, &peer_mac);
+}
+
+static void wlan_cm_utf_stop_test(void *arg)
+{
+	struct wlan_cm_utf *cm_utf = (struct wlan_cm_utf *)arg;
+
+	mlme_err("No Response from CM");
+	cm_utf->test_id = CM_UTF_ID_MAX;
+}
+
+static void wlan_cm_utf_deliver_event(void *arg)
+{
+	struct wlan_cm_utf *cm_utf = (struct wlan_cm_utf *)arg;
+
+	qdf_sched_work(NULL, &cm_utf->cm_utf_work);
+}
+
+/**
+ * wlan_cm_utf_default_connect_param: Update default connect req params
+ * for connection manager UTF
+ * @cm_utf: Connection Manager UTF object
+ *
+ * Return: None
+ */
+static QDF_STATUS
+wlan_cm_utf_default_connect_param(struct wlan_cm_utf *cm_utf)
+{
+	cm_utf->req.vdev_id = wlan_vdev_get_id(cm_utf->vdev);
+	cm_utf->req.source = CM_OSIF_CONNECT;
+	cm_utf->req.bssid.bytes[0] = 0x1;
+	cm_utf->req.bssid.bytes[1] = 0x2;
+	cm_utf->req.bssid.bytes[2] = 0x3;
+	cm_utf->req.bssid.bytes[3] = 0x4;
+	cm_utf->req.bssid.bytes[4] = 0x5;
+	cm_utf->req.bssid.bytes[5] = 0x6;
+	cm_utf->req.ssid.length = 6;
+	qdf_str_lcopy(cm_utf->req.ssid.ssid, "CM_STA", cm_utf->req.ssid.length);
+	cm_utf->req.chan_freq = 5200;
+	cm_utf->req.crypto.wep_keys.key_len = 0;
+	return QDF_STATUS_SUCCESS;
+}
+
+static void wlan_cm_utf_work_cb(void *arg)
+{
+	struct wlan_cm_utf *cm_utf = (struct wlan_cm_utf *)arg;
+	enum wlan_cm_utf_evt event_id = cm_utf->utf_node.evt_id;
+
+	switch (event_id) {
+	case CM_UTF_BSS_PEER_CREATE_RESP:
+		wlan_cm_utf_bss_peer_create_rsp(cm_utf);
+		break;
+	case CM_UTF_BSS_PEER_DELETE_RESP:
+		wlan_cm_utf_bss_peer_delete_rsp(cm_utf);
+		break;
+	case CM_UTF_CONNECT_RESP:
+		wlan_cm_utf_connect_rsp(cm_utf);
+		break;
+	case CM_UTF_DISCONNECT_RESP:
+		wlan_cm_utf_disconnect_rsp(cm_utf);
+		break;
+	case CM_UTF_PEER_DELETE_IND:
+		wlan_cm_utf_peer_del_ind(cm_utf);
+		break;
+	default:
+		break;
+	}
+}
+
+QDF_STATUS wlan_cm_utf_attach(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_cm_utf *cm_utf;
+	QDF_STATUS status;
+
+	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) {
+		mlme_err("Vdev is not a STA vdev");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (qdf_list_size(&wlan_cm_utf_list) == CM_UTF_LIST_SIZE) {
+		mlme_err("List is at max size");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!qdf_list_size(&wlan_cm_utf_list))
+		qdf_list_create(&wlan_cm_utf_list, CM_UTF_LIST_SIZE);
+
+	cm_utf = (struct wlan_cm_utf *)
+			qdf_mem_malloc(sizeof(struct wlan_cm_utf));
+
+	if (!cm_utf) {
+		mlme_err("Failed to allocate CM utf context");
+		qdf_list_destroy(&wlan_cm_utf_list);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	cm_utf->vdev = vdev;
+	cm_utf->test_id = CM_UTF_ID_MAX;
+	wlan_cm_utf_default_connect_param(cm_utf);
+	status = wlan_cm_utf_debugfs_create(cm_utf);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		qdf_mem_free(cm_utf);
+		qdf_list_destroy(&wlan_cm_utf_list);
+		return status;
+	}
+
+	qdf_timer_init(NULL, &cm_utf->cm_utf_timer,
+		       wlan_cm_utf_deliver_event, (void *)cm_utf,
+		       QDF_TIMER_TYPE_WAKE_APPS);
+
+	qdf_timer_init(NULL, &cm_utf->cm_utf_test_timer,
+		       wlan_cm_utf_stop_test, (void *)cm_utf,
+		       QDF_TIMER_TYPE_WAKE_APPS);
+
+	qdf_create_work(NULL, &cm_utf->cm_utf_work,
+			wlan_cm_utf_work_cb, cm_utf);
+
+	qdf_list_insert_back(&wlan_cm_utf_list, &cm_utf->cm_utf_node);
+	mlme_err("CM UTF attach Success");
+	return QDF_STATUS_SUCCESS;
+}
+
+static struct wlan_cm_utf *wlan_cm_get_utf(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_cm_utf *cm_utf;
+	qdf_list_node_t *node;
+	qdf_list_node_t *next_node;
+
+	if (!qdf_list_size(&wlan_cm_utf_list)) {
+		mlme_err("UTF list is empty");
+		return NULL;
+	}
+
+	if (qdf_list_peek_front(&wlan_cm_utf_list, &next_node)
+					!= QDF_STATUS_SUCCESS) {
+		mlme_err("UTF list is empty");
+		return NULL;
+	}
+
+	do {
+		node = next_node;
+		cm_utf = qdf_container_of(node, struct wlan_cm_utf,
+					  cm_utf_node);
+		if (cm_utf->vdev == vdev)
+			return cm_utf;
+	} while (qdf_list_peek_next(&wlan_cm_utf_list, node, &next_node)
+			== QDF_STATUS_SUCCESS);
+
+	return NULL;
+}
+
+void wlan_cm_utf_detach(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_cm_utf *cm_utf;
+	QDF_STATUS status;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("UTF not initialized for the vdev %d",
+			 wlan_vdev_get_id(vdev));
+		return;
+	}
+
+	status = qdf_list_remove_node(&wlan_cm_utf_list,
+				      &cm_utf->cm_utf_node);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		qdf_timer_free(&cm_utf->cm_utf_timer);
+		qdf_timer_free(&cm_utf->cm_utf_test_timer);
+
+		if (cm_utf->req.assoc_ie.ptr) {
+			qdf_mem_free(cm_utf->req.assoc_ie.ptr);
+			cm_utf->req.assoc_ie.ptr = NULL;
+		}
+
+		if (cm_utf->req.crypto.wep_keys.key) {
+			qdf_mem_free(cm_utf->req.crypto.wep_keys.key);
+			cm_utf->req.crypto.wep_keys.key = NULL;
+		}
+
+		qdf_disable_work(&cm_utf->cm_utf_work);
+		wlan_cm_utf_debugfs_remove(cm_utf);
+		qdf_mem_free(cm_utf);
+		mlme_err("CM UTF Deinit Success");
+		return;
+	}
+
+	mlme_err("Failed to remove UTF node");
+}
+
+QDF_STATUS wlan_cm_utf_bss_peer_create_req(struct wlan_objmgr_vdev *vdev,
+					   struct qdf_mac_addr *peer_mac)
+{
+	struct wlan_cm_utf *cm_utf;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("cm_utf is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	switch (cm_utf->test_id) {
+	case CM_UTF_ID_PEER_CREATE_TIMEOUT:
+		break;
+	default:
+		cm_utf->utf_node.peer_mac = peer_mac;
+		cm_utf->utf_node.evt_id = CM_UTF_BSS_PEER_CREATE_RESP;
+		qdf_timer_start(&cm_utf->cm_utf_timer, 100);
+		break;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cm_utf_connect_req_active(
+			struct wlan_objmgr_vdev *vdev,
+			struct wlan_cm_vdev_connect_req *vdev_connect_req)
+{
+	//Resp API to be added
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cm_utf_connect_req(
+			struct wlan_objmgr_vdev *vdev,
+			struct wlan_cm_vdev_connect_req *vdev_connect_req)
+{
+	struct wlan_cm_utf *cm_utf;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("cm_utf is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	switch (cm_utf->test_id) {
+	case CM_UTF_ID_CONNECT_SER_TIMEOUT:
+		break;
+	default:
+		qdf_mem_copy(&cm_utf->utf_node.conn_req, vdev_connect_req,
+			     sizeof(struct wlan_cm_vdev_connect_req));
+		cm_utf->utf_node.evt_id = CM_UTF_CONNECT_RESP;
+		qdf_timer_start(&cm_utf->cm_utf_timer, 100);
+		break;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cm_utf_disconnect_req(
+		struct wlan_objmgr_vdev *vdev,
+		struct wlan_cm_vdev_discon_req *vdev_disconnect_req)
+{
+	struct wlan_cm_utf *cm_utf;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("cm_utf is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	switch (cm_utf->test_id) {
+	case CM_UTF_ID_DISCONNECT_SER_TIMEOUT:
+		break;
+	default:
+		qdf_mem_copy(&cm_utf->utf_node.disconn_req, vdev_disconnect_req,
+			     sizeof(struct wlan_cm_vdev_discon_req));
+		cm_utf->utf_node.evt_id = CM_UTF_PEER_DELETE_IND;
+		qdf_timer_start(&cm_utf->cm_utf_timer, 100);
+		break;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cm_utf_bss_peer_delete_req(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_cm_utf *cm_utf;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("cm_utf is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	switch (cm_utf->test_id) {
+	case CM_UTF_ID_PEER_DELETE_TIMEOUT:
+		break;
+	default:
+		cm_utf->utf_node.evt_id = CM_UTF_BSS_PEER_DELETE_RESP;
+		qdf_timer_start(&cm_utf->cm_utf_timer, 100);
+		break;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cm_utf_vdev_down(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_cm_utf *cm_utf;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("cm_utf is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	switch (cm_utf->test_id) {
+	default:
+		cm_utf->utf_node.evt_id = CM_UTF_DISCONNECT_RESP;
+		qdf_timer_start(&cm_utf->cm_utf_timer, 100);
+		break;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+static
+QDF_STATUS wlan_cm_utf_validate_test(struct wlan_cm_utf *cm_utf,
+				     struct wlan_cm_connect_rsp *cm_conn_rsp)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	switch (cm_utf->test_id) {
+	case CM_UTF_ID_PEER_CREATE_FAILURE:
+	case CM_UTF_ID_PEER_CREATE_TIMEOUT:
+		if (cm_conn_rsp->reason == CM_PEER_CREATE_FAILED) {
+			// check (CM state to be valid as per test in all cases)
+			status = QDF_STATUS_SUCCESS;
+		}
+		break;
+	case CM_UTF_ID_CONNECT_SER_TIMEOUT:
+	case CM_UTF_ID_CONNECT_SER_FAILED:
+		if (cm_conn_rsp->reason == CM_SER_FAILURE)
+			status = QDF_STATUS_SUCCESS;
+		break;
+	case CM_UTF_ID_CONNECT_SCAN_FAILURE:
+		if (cm_conn_rsp->reason == CM_NO_CANDIDATE_FOUND)
+			status = QDF_STATUS_SUCCESS;
+		break;
+	case CM_UTF_ID_AUTH_FAILURE:
+		if (cm_conn_rsp->reason == CM_AUTH_FAILED)
+			status = QDF_STATUS_SUCCESS;
+		break;
+	case CM_UTF_ID_AUTH_TIMEOUT:
+		if (cm_conn_rsp->reason == CM_AUTH_TIMEOUT)
+			status = QDF_STATUS_SUCCESS;
+		break;
+	case CM_UTF_ID_ASSOC_FAILURE:
+		if (cm_conn_rsp->reason == CM_ASSOC_FAILED)
+			status = QDF_STATUS_SUCCESS;
+		break;
+	case CM_UTF_ID_ASSOC_TIMEOUT:
+		if (cm_conn_rsp->reason == CM_ASSOC_TIMEOUT)
+			status = QDF_STATUS_SUCCESS;
+		break;
+	default:
+		if (cm_conn_rsp->connect_status == QDF_STATUS_SUCCESS)
+			status = QDF_STATUS_SUCCESS;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * wlan_cm_utf_osif_connect_cb: Connection manager UTF
+ * connect callback handler
+ * @vdev: VDEV object
+ * @cm_conn_rsp: Connect Response
+ *
+ * Return: None
+ */
+static QDF_STATUS
+wlan_cm_utf_osif_connect_cb(struct wlan_objmgr_vdev *vdev,
+			    struct wlan_cm_connect_rsp *cm_conn_rsp)
+{
+	struct wlan_cm_utf *cm_utf;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("cm_utf is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (cm_conn_rsp->cm_id != cm_utf->last_cmd_id ||
+	    cm_utf->last_cmd_source != CM_OSIF_CONNECT) {
+		mlme_err("Incorrect cmd id/source");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = wlan_cm_utf_validate_test(cm_utf, cm_conn_rsp);
+	if (status == QDF_STATUS_SUCCESS)
+		mlme_err("Test case Success for Test: %s",
+			 cm_utf_test_names[cm_utf->test_id]);
+	else
+		mlme_err("Test case Failed for Test: %s",
+			 cm_utf_test_names[cm_utf->test_id]);
+
+	qdf_timer_stop(&cm_utf->cm_utf_test_timer);
+	cm_utf->test_id = CM_UTF_ID_MAX;
+
+	return status;
+}
+
+/**
+ * wlan_cm_utf_osif_disconnect_cb: Connection manager UTF
+ * disconnect callback handler
+ * @vdev: VDEV object
+ * @cm_disconn_rsp: Disconnect Response
+ *
+ * Return: None
+ */
+static QDF_STATUS wlan_cm_utf_osif_disconnect_cb(
+		struct wlan_objmgr_vdev *vdev,
+		struct wlan_cm_discon_rsp *cm_disconn_rsp)
+{
+	struct wlan_cm_utf *cm_utf;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("cm_utf is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (cm_disconn_rsp->req.cm_id != cm_utf->last_cmd_id ||
+	    cm_disconn_rsp->req.req.source != cm_utf->last_cmd_source) {
+		mlme_err("Incorrect cmd id/source");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	mlme_err("Test case Success for Test: %s",
+		 cm_utf_test_names[cm_utf->test_id]);
+	qdf_timer_stop(&cm_utf->cm_utf_test_timer);
+	cm_utf->test_id = CM_UTF_ID_MAX;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wlan_cm_utf_update_conn_id_and_src_cb: Connection manager UTF
+ * callback to update connect id and source of the connect request
+ * @vdev: VDEV object
+ * @cm_disconn_rsp: Disconnect Response
+ *
+ * Return: None
+ */
+static QDF_STATUS wlan_cm_utf_update_conn_id_and_src_cb(
+		struct wlan_objmgr_vdev *vdev,
+		enum wlan_cm_source source, wlan_cm_id cm_id)
+{
+	struct wlan_cm_utf *cm_utf;
+
+	cm_utf = wlan_cm_get_utf(vdev);
+	if (!cm_utf) {
+		mlme_err("cm_utf is Null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	cm_utf->last_cmd_id = cm_id;
+	cm_utf->last_cmd_source = source;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static struct mlme_cm_ops cm_ops = {
+	.mlme_cm_connect_complete_cb = wlan_cm_utf_osif_connect_cb,
+	.mlme_cm_failed_candidate_cb = NULL,
+	.mlme_cm_update_id_and_src_cb =
+			wlan_cm_utf_update_conn_id_and_src_cb,
+	.mlme_cm_disconnect_complete_cb = wlan_cm_utf_osif_disconnect_cb,
+	.mlme_cm_disconnect_start_cb = NULL,
+};
+
+static struct mlme_cm_ops *osif_cm_get_global_ops(void)
+{
+	return &cm_ops;
+}
+
+QDF_STATUS osif_cm_utf_register_cb(void)
+{
+	mlme_set_osif_cm_cb(osif_cm_get_global_ops);
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wlan_cm_utf_update_connect_param: API to update connect req params
+ * @cm_utf: CM UTF object
+ * @buffer: user input buffer
+ *
+ * Return: None
+ *
+ */
+static void
+wlan_cm_utf_update_connect_param(struct wlan_cm_utf *cm_utf, char *buffer)
+{
+	char *token;
+	uint8_t idx = 0;
+
+	token = qdf_str_sep(&buffer, "\n");
+
+	if (!token) {
+		mlme_err("Invalid Parameters");
+		return;
+	}
+
+	if (cm_utf->req.assoc_ie.ptr) {
+		qdf_mem_free(cm_utf->req.assoc_ie.ptr);
+		cm_utf->req.assoc_ie.ptr = NULL;
+	}
+
+	if (cm_utf->req.crypto.wep_keys.key) {
+		qdf_mem_free(cm_utf->req.crypto.wep_keys.key);
+		cm_utf->req.crypto.wep_keys.key = NULL;
+	}
+
+	qdf_mem_zero(cm_utf->req.ssid.ssid, WLAN_SSID_MAX_LEN);
+	if (sscanf(token, "%2x:%2x:%2x:%2x:%2x:%2x ,%2x:%2x:%2x:%2x:%2x:%2x "
+		   ",%2x:%2x:%2x:%2x:%2x:%2x ,%u ,%u ,%u ,%u ,%u ,%u ,%u ,%u "
+		   ",%u ,%u ,%u ,%u ,%u ,%s",
+		   (unsigned int *)&cm_utf->req.bssid.bytes[0],
+		   (unsigned int *)&cm_utf->req.bssid.bytes[1],
+		   (unsigned int *)&cm_utf->req.bssid.bytes[2],
+		   (unsigned int *)&cm_utf->req.bssid.bytes[3],
+		   (unsigned int *)&cm_utf->req.bssid.bytes[4],
+		   (unsigned int *)&cm_utf->req.bssid.bytes[5],
+		   (unsigned int *)&cm_utf->req.prev_bssid.bytes[0],
+		   (unsigned int *)&cm_utf->req.prev_bssid.bytes[1],
+		   (unsigned int *)&cm_utf->req.prev_bssid.bytes[2],
+		   (unsigned int *)&cm_utf->req.prev_bssid.bytes[3],
+		   (unsigned int *)&cm_utf->req.prev_bssid.bytes[4],
+		   (unsigned int *)&cm_utf->req.prev_bssid.bytes[5],
+		   (unsigned int *)&cm_utf->req.bssid_hint.bytes[0],
+		   (unsigned int *)&cm_utf->req.bssid_hint.bytes[1],
+		   (unsigned int *)&cm_utf->req.bssid_hint.bytes[2],
+		   (unsigned int *)&cm_utf->req.bssid_hint.bytes[3],
+		   (unsigned int *)&cm_utf->req.bssid_hint.bytes[4],
+		   (unsigned int *)&cm_utf->req.bssid_hint.bytes[5],
+		   &cm_utf->req.chan_freq,
+		   &cm_utf->req.crypto.wpa_versions,
+		   &cm_utf->req.crypto.auth_type,
+		   &cm_utf->req.crypto.group_cipher,
+		   &cm_utf->req.crypto.ciphers_pairwise,
+		   &cm_utf->req.crypto.akm_suites,
+		   (unsigned int *)&cm_utf->req.crypto.rsn_caps,
+		   &cm_utf->req.crypto.mgmt_ciphers,
+		   (unsigned int *)&cm_utf->req.ht_caps,
+		   (unsigned int *)&cm_utf->req.ht_caps_mask,
+		   &cm_utf->req.vht_caps,
+		   &cm_utf->req.vht_caps_mask,
+		   (unsigned int *)&cm_utf->req.ssid.length,
+		   cm_utf->req.ssid.ssid) != 32) {
+		mlme_err("Invalid connect req params");
+		return;
+	}
+
+	qdf_err("Updated connect params %s", buffer);
+	while ((token = qdf_str_sep(&buffer, ",")) != NULL) {
+		switch (idx) {
+		case 0:
+			if (sscanf(token, "%u", &cm_utf->req.assoc_ie.len) != 1)
+				return;
+			if (!cm_utf->req.assoc_ie.len) {
+				idx += 2;
+				break;
+			}
+			idx++;
+			break;
+		case 1:
+			cm_utf->req.assoc_ie.ptr =
+				(uint8_t *)qdf_mem_malloc(cm_utf->req.assoc_ie.len);
+			if (!cm_utf->req.assoc_ie.ptr) {
+				mlme_err("Failed to alloc memory");
+				return;
+			}
+			qdf_mem_copy(cm_utf->req.assoc_ie.ptr, token,
+				     cm_utf->req.assoc_ie.len);
+			idx++;
+			break;
+		case 2:
+			if (sscanf(token, "%u",
+				   (unsigned int *)&cm_utf->req.crypto.wep_keys.key_len) != 1)
+				return;
+			if (!cm_utf->req.crypto.wep_keys.key_len)
+				return;
+			idx++;
+			break;
+		case 3:
+			cm_utf->req.crypto.wep_keys.key =
+				(uint8_t *)qdf_mem_malloc(cm_utf->req.crypto.wep_keys.key_len);
+			if (!cm_utf->req.crypto.wep_keys.key) {
+				mlme_err("Failed to alloc memory");
+				return;
+			}
+			qdf_mem_copy(cm_utf->req.crypto.wep_keys.key, token,
+				     cm_utf->req.crypto.wep_keys.key_len);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+/**
+ * wlan_cm_utf_start_test: Connection manager UTF entry function
+ * @cm_utf: Connection Manager UTF object
+ * *test_id: Test ID requested by user
+ *
+ */
+static void wlan_cm_utf_start_test(struct wlan_cm_utf *cm_utf, void *buffer)
+{
+	int reason = 0, ret;
+	uint8_t i = 0;
+	char *token;
+	char *token2;
+	char *buff = (char *)buffer;
+	struct wlan_cm_disconnect_req req;
+
+	if (cm_utf->test_id != CM_UTF_ID_MAX) {
+		mlme_err("Test Already in progress");
+		return;
+	}
+
+	token = qdf_str_sep(&buff, " ");
+	if (token) {
+		if (!qdf_str_cmp(token, "CONNECT_REQ")) {
+			mlme_err("Update Connect Params");
+			wlan_cm_utf_update_connect_param(cm_utf, buff);
+			return;
+		}
+
+		token2 = qdf_str_sep(&token, "\n");
+		for (i = 0; i < CM_UTF_ID_MAX; i++) {
+			if (!qdf_str_cmp(token2, cm_utf_test_names[i])) {
+				cm_utf->test_id = i;
+				break;
+			}
+		}
+	}
+
+	if (cm_utf->test_id == CM_UTF_ID_MAX) {
+		mlme_err("Invalid Test Case");
+		return;
+	}
+
+	mlme_err("Test ID: %d", cm_utf->test_id);
+	switch (cm_utf->test_id) {
+	case CM_UTF_ID_CONNECT_SUCCESS:
+	case CM_UTF_ID_PEER_CREATE_FAILURE:
+	case CM_UTF_ID_PEER_CREATE_TIMEOUT:
+	case CM_UTF_ID_AUTH_FAILURE:
+	case CM_UTF_ID_AUTH_TIMEOUT:
+	case CM_UTF_ID_ASSOC_FAILURE:
+	case CM_UTF_ID_ASSOC_TIMEOUT:
+	case CM_UTF_ID_CONNECT_SCAN_FAILURE:
+	case CM_UTF_ID_CONNECT_SER_TIMEOUT:
+	case CM_UTF_ID_CONNECT_SER_FAILED:
+		cm_utf->req.vdev_id = wlan_vdev_get_id(cm_utf->vdev);
+		cm_utf->req.source = CM_OSIF_CONNECT;
+		ucfg_cm_start_connect(cm_utf->vdev, &cm_utf->req);
+		break;
+	case CM_UTF_ID_DISCONNECT_SUCCESS:
+	case CM_UTF_ID_DISCONNECT_SER_TIMEOUT:
+	case CM_UTF_ID_DISCONNECT_SER_FAILED:
+	case CM_UTF_ID_PEER_DELETE_TIMEOUT:
+		token = qdf_str_sep(&buff, " ");
+		if (!token) {
+			mlme_err("Provide reason code for disconnect");
+			cm_utf->test_id = CM_UTF_ID_MAX;
+			return;
+		} else {
+			ret = qdf_kstrtoint(token, 0, &reason);
+			if (ret) {
+				mlme_err("Invalid disconnect reason");
+				cm_utf->test_id = CM_UTF_ID_MAX;
+				return;
+			}
+		}
+		mlme_err("Disconnect reason %d", reason);
+		req.vdev_id = wlan_vdev_get_id(cm_utf->vdev);
+		req.source = CM_OSIF_DISCONNECT;
+		req.reason_code = reason;
+		ucfg_cm_start_disconnect(cm_utf->vdev, &req);
+		break;
+	default:
+		mlme_err("Invalid test ID");
+		cm_utf->test_id = CM_UTF_ID_MAX;
+		qdf_timer_stop(&cm_utf->cm_utf_test_timer);
+		break;
+	}
+
+	if (cm_utf->test_id == CM_UTF_ID_PEER_DELETE_TIMEOUT ||
+	    cm_utf->test_id == CM_UTF_ID_PEER_CREATE_TIMEOUT ||
+	    cm_utf->test_id == CM_UTF_ID_DISCONNECT_SER_TIMEOUT ||
+	    cm_utf->test_id == CM_UTF_ID_CONNECT_SER_TIMEOUT)
+		qdf_timer_start(&cm_utf->cm_utf_test_timer, 70000);
+	else
+		qdf_timer_start(&cm_utf->cm_utf_test_timer, 10000);
+}
+
+int wlan_cm_utf_cm_test_id_show(qdf_debugfs_file_t m, void *v)
+{
+	uint8_t i;
+
+	mlme_nofl_err("Usage:");
+	for (i = 0; i < CM_UTF_ID_MAX; i++) {
+		switch (i) {
+		case CM_UTF_ID_DISCONNECT_SUCCESS:
+		case CM_UTF_ID_DISCONNECT_SER_TIMEOUT:
+		case CM_UTF_ID_DISCONNECT_SER_FAILED:
+		case CM_UTF_ID_PEER_DELETE_TIMEOUT:
+			mlme_nofl_err("%22s <reason>", cm_utf_test_names[i]);
+			break;
+		default:
+			mlme_nofl_err("%22s", cm_utf_test_names[i]);
+			break;
+		}
+	}
+	return 0;
+}
+
+ssize_t wlan_cm_utf_cm_test_id_write(struct file *file,
+				     const char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	struct wlan_cm_utf *cm_utf =
+			((struct seq_file *)file->private_data)->private;
+	char *locbuf;
+
+	if ((!buf) || (count <= 0))
+		return -EFAULT;
+
+	locbuf = (char *)qdf_mem_malloc(count + 1);
+
+	if (!locbuf)
+		return -EFAULT;
+
+	qdf_mem_zero(locbuf, count + 1);
+
+	if (copy_from_user(locbuf, buf, count))
+		return -EFAULT;
+
+	mlme_err("CM Start Test");
+	wlan_cm_utf_start_test(cm_utf, locbuf);
+	qdf_mem_free(locbuf);
+
+	return count;
+}
+#endif

+ 166 - 0
umac/mlme/connection_mgr/utf/src/wlan_cm_utf_scan.c

@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * DOC: Implements scan functinality for CM UTF
+ */
+
+#ifdef FEATURE_CM_UTF_ENABLE
+#include <wlan_cm_utf.h>
+#include <qdf_str.h>
+
+struct wlan_cm_utf_raw_bcn {
+	uint32_t channel_number;
+	int32_t rssi;
+	uint8_t band;
+	uint8_t bssid[QDF_MAC_ADDR_SIZE];
+	uint8_t ssid[WLAN_SSID_MAX_LEN];
+};
+
+static void wlan_cm_utf_scan_db_update(struct wlan_objmgr_vdev *vdev,
+				       void *buffer)
+{
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_cm_utf_raw_bcn *event = NULL;
+	struct mgmt_rx_event_params *rx_param = NULL;
+	struct wlan_objmgr_psoc *psoc;
+	char *buff = (char *)buffer;
+	char *token;
+	uint32_t frame_len = 0;
+	qdf_nbuf_t buf;
+	struct ie_ssid ssid;
+	struct ie_header *ie;
+	struct wlan_frame_hdr *hdr;
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		mlme_err("Pdev is Null");
+		return;
+	}
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		mlme_err("Psoc is Null");
+		return;
+	}
+
+	while ((token = qdf_str_sep(&buff, "\n")) != NULL) {
+		mlme_err("%s", token);
+		event = qdf_mem_malloc(sizeof(struct wlan_cm_utf_raw_bcn));
+		if (!event) {
+			mlme_err("Failed to allocate event memory");
+			return;
+		}
+		if (sscanf(token,
+			   "%2x:%2x:%2x:%2x:%2x:%2x ,%u ,%u ,%u ,%s",
+			   (unsigned int *)&event->bssid[0],
+			   (unsigned int *)&event->bssid[1],
+			   (unsigned int *)&event->bssid[2],
+			   (unsigned int *)&event->bssid[3],
+			   (unsigned int *)&event->bssid[4],
+			   (unsigned int *)&event->bssid[5],
+			   &event->channel_number,
+			   (unsigned int *)&event->band,
+			   &event->rssi,
+			   event->ssid) != 10) {
+			goto free_buf;
+		}
+		ssid.ssid_id = 0;	//Element id for ssid
+		ssid.ssid_len = strlen(event->ssid);
+		qdf_mem_copy(ssid.ssid, event->ssid, strlen(event->ssid));
+
+		rx_param = qdf_mem_malloc(sizeof(struct mgmt_rx_event_params));
+		if (!rx_param) {
+			mlme_err("Failed to allocate memory");
+			goto free_buf;
+		}
+
+		qdf_mem_zero(rx_param, sizeof(struct mgmt_rx_event_params));
+		rx_param->snr = event->rssi;
+		rx_param->channel = event->channel_number;
+		rx_param->chan_freq = wlan_reg_chan_band_to_freq(
+						pdev,
+						event->channel_number,
+						BIT(event->band));
+
+		rx_param->pdev_id = 0;
+		frame_len = sizeof(struct wlan_frame_hdr) +
+			    sizeof(struct wlan_bcn_frame) -
+			    sizeof(struct ie_header) +
+			    sizeof(struct ie_header) + ssid.ssid_len;
+
+		buf = qdf_nbuf_alloc(NULL, frame_len, 0, 0, FALSE);
+		if (!buf) {
+			mlme_err("Failed to allocate buffer");
+			goto free_buf;
+		}
+
+		qdf_nbuf_set_pktlen(buf, frame_len);
+		qdf_mem_zero((uint8_t *)qdf_nbuf_data(buf), frame_len);
+
+		hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(buf);
+		qdf_mem_copy(hdr->i_addr3, event->bssid, QDF_MAC_ADDR_SIZE);
+		qdf_mem_copy(hdr->i_addr2, event->bssid, QDF_MAC_ADDR_SIZE);
+		ie = (struct ie_header *)(((uint8_t *)qdf_nbuf_data(buf))
+				+ sizeof(struct wlan_frame_hdr)
+				+ offsetof(struct wlan_bcn_frame, ie));
+
+		qdf_mem_copy(ie, &ssid, sizeof(struct ie_ssid));
+		tgt_scan_bcn_probe_rx_callback(psoc, NULL, buf,
+					       rx_param, MGMT_BEACON);
+free_buf:
+		if (event) {
+			qdf_mem_free(event);
+			event = NULL;
+		}
+		if (rx_param) {
+			qdf_mem_free(rx_param);
+			rx_param = NULL;
+		}
+	}
+}
+
+int wlan_cm_utf_scan_db_update_show(qdf_debugfs_file_t m, void *v)
+{
+	return 0;
+}
+
+ssize_t wlan_cm_utf_scan_db_update_write(struct file *file,
+					 const char __user *buf,
+					 size_t count, loff_t *ppos)
+{
+	struct wlan_cm_utf *cm_utf =
+			((struct seq_file *)file->private_data)->private;
+	char *locbuf;
+
+	if ((!buf) || (count <= 0))
+		return -EFAULT;
+
+	locbuf = (char *)qdf_mem_malloc(count);
+
+	if (!locbuf)
+		return -EFAULT;
+
+	qdf_mem_zero(locbuf, count);
+
+	if (copy_from_user(locbuf, buf, count))
+		return -EFAULT;
+
+	wlan_cm_utf_scan_db_update(cm_utf->vdev, locbuf);
+	qdf_mem_free(locbuf);
+	return count;
+}
+#endif