Browse Source

qcacmn: Add basic infra for connection manager

Add basic infra for connection mgr state machine
to handle connect and disconnect requests.

Change-Id: I671f62f66ab511912886c1da84c3a69be0032872
CRs-Fixed: 2707901
gaurank kathpalia 5 năm trước cách đây
mục cha
commit
9375922ab2

+ 19 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_cmn.c

@@ -0,0 +1,19 @@
+/*
+ * 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 general apis of connection manager
+ */

+ 19 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_connect.c

@@ -0,0 +1,19 @@
+/*
+ * 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 connect specific APIs of connection manager
+ */

+ 20 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_connect_scan.c

@@ -0,0 +1,20 @@
+/*
+ * 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 connect scan (scan for ssid) specific apis of
+ * connection manager
+ */

+ 19 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c

@@ -0,0 +1,19 @@
+/*
+ * 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 disconnect specific apis of connection manager
+ */

+ 64 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_main.c

@@ -0,0 +1,64 @@
+/*
+ * 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 init/deinit specific apis of connection manager
+ */
+
+#include "wlan_cm_main.h"
+#include "wlan_cm_sm.h"
+
+QDF_STATUS mlme_cm_init(struct vdev_mlme_obj *vdev_mlme)
+{
+	struct wlan_objmgr_vdev *vdev = vdev_mlme->vdev;
+	enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev);
+	QDF_STATUS status;
+
+	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
+		return QDF_STATUS_SUCCESS;
+
+	vdev_mlme->cnx_mgr_ctx = qdf_mem_malloc(sizeof(struct cnx_mgr));
+	if (!vdev_mlme->cnx_mgr_ctx)
+		return QDF_STATUS_E_NOMEM;
+
+	vdev_mlme->cnx_mgr_ctx->vdev = vdev_mlme->vdev;
+	status = mlme_cm_sm_create(vdev_mlme->cnx_mgr_ctx);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mlme_err("CM MLME SM allocation failed");
+		qdf_mem_free(vdev_mlme->cnx_mgr_ctx);
+		vdev_mlme->cnx_mgr_ctx = NULL;
+		return QDF_STATUS_E_NOMEM;
+	}
+	qdf_list_create(&vdev_mlme->cnx_mgr_ctx->req_list, CM_MAX_REQ);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS mlme_cm_deinit(struct vdev_mlme_obj *vdev_mlme)
+{
+	struct wlan_objmgr_vdev *vdev = vdev_mlme->vdev;
+	enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev);
+
+	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
+		return QDF_STATUS_SUCCESS;
+
+	qdf_list_destroy(&vdev_mlme->cnx_mgr_ctx->req_list);
+	mlme_cm_sm_destroy(vdev_mlme->cnx_mgr_ctx);
+	qdf_mem_free(vdev_mlme->cnx_mgr_ctx);
+	vdev_mlme->cnx_mgr_ctx = NULL;
+
+	return QDF_STATUS_SUCCESS;
+}

+ 353 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_main.h

@@ -0,0 +1,353 @@
+/*
+ * 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: wlan_cm_main.h
+ *
+ * This header file maintain structures required for connection mgr core
+ */
+
+#ifndef __WLAN_CM_MAIN_H__
+#define __WLAN_CM_MAIN_H__
+
+#include "include/wlan_vdev_mlme.h"
+
+#ifdef FEATURE_CM_ENABLE
+#include <wlan_cm_public_struct.h>
+
+/* Max candidate to be tried to connect */
+#define CM_MAX_CANDIDATE_TO_BE_TRIED 5
+/* Max time to wait for scan for SSID */
+#define CM_SCAN_MAX_TIME 5000
+/* Max connect/disconnect/roam req that can be queued at a time */
+#define CM_MAX_REQ 5
+
+/**
+ * enum wlan_cm_sm_state - Connection manager states
+ * @WLAN_CM_S_INIT:                     Default state, IDLE state
+ * @WLAN_CM_S_CONNECTING:               State when connect request comes
+ * @WLAN_CM_S_CONNECTED:                State when connect is complete
+ * @WLAN_CM_S_DISCONNECTING:            State when disconnect request comes
+ * @WLAN_CM_S_ROAMING:                  State when roaming is in progress
+ * @WLAN_CM_S_MAX:                      Max State
+ * @WLAN_CM_SS_IDLE:                    Idle state (no substate)
+ * @WLAN_CM_SS_JOIN_PENDING:            Connect request not serialized
+ * @WLAN_CM_SS_SCAN:                    Scan for SSID state
+ * @WLAN_CM_SS_JOIN_ACTIVE:             Conenct request activated
+ * @WLAN_CM_SS_PREAUTH:                 Roam substate of preauth stage
+ * @WLAN_CM_SS_REASSOC:                 Roam substate for reassoc state
+ * @WLAN_CM_SS_ROAM_STARTED:            Roaming in progress (LFR 3.0)
+ * @WLAN_CM_SS_ROAM_SYNC:               Roam sync indication from FW
+ * @WLAN_CM_SS_MAX:                     Max Substate
+ */
+enum wlan_cm_sm_state {
+	WLAN_CM_S_INIT = 0,
+	WLAN_CM_S_CONNECTING = 1,
+	WLAN_CM_S_CONNECTED = 2,
+	WLAN_CM_S_DISCONNECTING = 3,
+	WLAN_CM_S_ROAMING = 4,
+	WLAN_CM_S_MAX = 5,
+	WLAN_CM_SS_IDLE = 6,
+	WLAN_CM_SS_JOIN_PENDING = 7,
+	WLAN_CM_SS_SCAN = 8,
+	WLAN_CM_SS_JOIN_ACTIVE = 9,
+	WLAN_CM_SS_PREAUTH = 10,
+	WLAN_CM_SS_REASSOC = 11,
+	WLAN_CM_SS_ROAM_STARTED = 12,
+	WLAN_CM_SS_ROAM_SYNC = 13,
+	WLAN_CM_SS_MAX = 14,
+};
+
+/**
+ * enum wlan_cm_sm_evt - connection manager related events
+ * @WLAN_CM_SM_EV_CONNECT_REQ:            Connect request event
+ * @WLAN_CM_SM_EV_SCAN_FOR_SSID:          Event for scan for SSID
+ * @WLAN_CM_SM_EV_SCAN_FOR_SSID_SUCCESS:  Scan for SSID success event
+ * @WLAN_CM_SM_EV_SCAN_FOR_SSID_FAILURE:  Scan for SSID fail event
+ * @WLAN_CM_SM_EV_CONNECT_START_REQ:      Connect start request after BSSID list
+ *                                        is prepared
+ * @WLAN_CM_SM_EV_CONNECT_START:          Connect request for a particular BSSID
+ * @WLAN_CM_SM_EV_CONNECT_SUCCESS:        Connect success
+ * @WLAN_CM_SM_EV_CONNECT_NEXT_CANDIDATE: Select next candidate for connection
+ * @WLAN_CM_SM_EV_CONNECT_FAILURE:        Connect failed event
+ * @WLAN_CM_SM_EV_DISCONNECT_REQ:         Disconnect request event
+ * @WLAN_CM_SM_EV_DISCONNECT_START_REQ:   Start disconnect sequence
+ * @WLAN_CM_SM_EV_DISCONNECT_START:       Disconnect process start event
+ * @WLAN_CM_SM_EV_DISCONNECT_DONE:        Disconnect done event
+ * @WLAN_CM_SM_EV_ROAM_START:             Roam start event
+ * @WLAN_CM_SM_EV_ROAM_SYNC:              Roam sync event
+ * @WLAN_CM_SM_EV_ROAM_INVOKE_FAIL:       Roam invoke fail event
+ * @WLAN_CM_SM_EV_ROAM_HO_FAIL:           Hand off failed event
+ * @WLAN_CM_SM_EV_PREAUTH_DONE:           Preauth is completed
+ * @WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP:    Get next candidate as preauth failed
+ * @WLAN_CM_SM_EV_PREAUTH_FAIL:           Preauth failed for all candidate
+ * @WLAN_CM_SM_EV_START_REASSOC:          Start reassoc after preauth done
+ * @WLAN_CM_SM_EV_REASSOC_DONE:           Reassoc completed
+ * @WLAN_CM_SM_EV_REASSOC_FAILURE:        Reassoc failed
+ * @WLAN_CM_SM_EV_ROAM_COMPLETE:          Roaming completed
+ * @WLAN_CM_SM_EV_CONNECT_TIMEOUT:        Connect timeout event
+ * @WLAN_CM_SM_EV_CONNECT_SER_FAIL:       Connect request failed to serialize
+ * @WLAN_CM_SM_EV_HW_MODE_CHANGE_FAIL:    HW mode change failed event
+ * @WLAN_CM_SM_EV_MAX:                    Max event
+ */
+enum wlan_cm_sm_evt {
+	WLAN_CM_SM_EV_CONNECT_REQ = 0,
+	WLAN_CM_SM_EV_SCAN_FOR_SSID = 1,
+	WLAN_CM_SM_EV_SCAN_FOR_SSID_SUCCESS = 2,
+	WLAN_CM_SM_EV_SCAN_FOR_SSID_FAILURE = 3,
+	WLAN_CM_SM_EV_CONNECT_START_REQ = 4,
+	WLAN_CM_SM_EV_CONNECT_START = 5,
+	WLAN_CM_SM_EV_CONNECT_SUCCESS = 6,
+	WLAN_CM_SM_EV_CONNECT_NEXT_CANDIDATE = 7,
+	WLAN_CM_SM_EV_CONNECT_FAILURE = 8,
+	WLAN_CM_SM_EV_DISCONNECT_REQ = 9,
+	WLAN_CM_SM_EV_DISCONNECT_START_REQ = 10,
+	WLAN_CM_SM_EV_DISCONNECT_START = 11,
+	WLAN_CM_SM_EV_DISCONNECT_DONE = 12,
+	WLAN_CM_SM_EV_ROAM_START = 13,
+	WLAN_CM_SM_EV_ROAM_SYNC = 14,
+	WLAN_CM_SM_EV_ROAM_INVOKE_FAIL = 15,
+	WLAN_CM_SM_EV_ROAM_HO_FAIL = 16,
+	WLAN_CM_SM_EV_PREAUTH_DONE = 17,
+	WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP = 18,
+	WLAN_CM_SM_EV_PREAUTH_FAIL = 19,
+	WLAN_CM_SM_EV_START_REASSOC = 20,
+	WLAN_CM_SM_EV_REASSOC_DONE = 21,
+	WLAN_CM_SM_EV_REASSOC_FAILURE = 22,
+	WLAN_CM_SM_EV_ROAM_COMPLETE = 23,
+	WLAN_CM_SM_EV_CONNECT_TIMEOUT = 24,
+	WLAN_CM_SM_EV_CONNECT_SER_FAIL = 25,
+	WLAN_CM_SM_EV_HW_MODE_CHANGE_FAIL = 26,
+	WLAN_CM_SM_EV_MAX,
+};
+
+/**
+ * struct cm_state_sm - connection manager sm
+ * @cm_sm_lock: sm lock
+ * @sm_hdl: sm handlers
+ * @cm_state: current state
+ * @cm_substate: current substate
+ */
+struct cm_state_sm {
+#ifdef WLAN_CM_USE_SPINLOCK
+	qdf_spinlock_t cm_sm_lock;
+#else
+	qdf_mutex_t cm_sm_lock;
+#endif
+	struct wlan_sm *sm_hdl;
+	enum wlan_cm_sm_state cm_state;
+	enum wlan_cm_sm_state cm_substate;
+};
+
+/**
+ * struct cm_connect_req - connect req stored in connect manager
+ * @cm_id: Connect manager id
+ * @scan_id: scan id for scan for ssid
+ * @scan_timer: timer for scan for ssid to get completed
+ * @hw_mode_timer: timer for hw mode chane to get completed
+ * @req: connect req from osif
+ * @candidate_list: candidate list
+ * @cur_candidate: current candidate
+ */
+struct cm_connect_req {
+	uint64_t cm_id;
+	uint64_t scan_id;
+	qdf_timer_t scan_timer;
+	qdf_timer_t hw_mode_timer;
+	struct wlan_cm_connect_req req;
+	qdf_list_t candidate_list;
+	struct scan_cache_node *cur_candidate;
+};
+
+/**
+ * struct cm_disconnect_req - disconnect req
+ * @cm_id: Connect manager id
+ * @req: disconnect connect req from osif
+ */
+struct cm_disconnect_req {
+	uint64_t cm_id;
+	struct wlan_cm_disconnect_req req;
+};
+
+/**
+ * struct cm_req - connect manager req
+ * @node: connection manager req node
+ * @source: req source
+ * @cm_id: cm id
+ * @connect_req: connect req
+ * @disconnect_req: disconnect req
+ */
+struct cm_req {
+	qdf_list_node_t node;
+	enum wlan_cm_source source;
+	uint64_t cm_id;
+	union {
+		struct cm_connect_req connect_req;
+		struct cm_disconnect_req discon_req;
+	};
+};
+
+/**
+ * struct connect_req_ies - connect req ies stored in vdev
+ * @additional_assoc_ie: assoc req additional IE to be appended to assoc req
+ * @auth_ft_ies: auth ft ies received during preauth phase
+ * @reassoc_ft_ies: reassoc ft ies received during reassoc phase
+ * @cck_ie: cck ie for cck connection
+ * @forced_rsn_ie: set if force_rsne_override is set from the connect IE. This
+ * is used to store the invalid RSN IE from suplicant to enable testbed STA for
+ * cert cases.
+ */
+struct connect_req_ies {
+	struct element_info additional_assoc_ie;
+	struct element_info auth_ft_ies;
+	struct element_info reassoc_ft_ies;
+	struct element_info cck_ie;
+	struct element_info forced_rsn_ie;
+};
+
+#ifdef WLAN_FEATURE_FILS_SK
+#define CM_FILS_MAX_HLP_DATA_LEN 2048
+#define MAX_KEK_LENGTH 64
+#define MAX_TK_LENGTH 32
+#define MAX_GTK_LENGTH 255
+
+/**
+ * struct fils_connect_rsp_params - fils related connect rsp params
+ * @fils_pmk: fils pmk
+ * @fils_pmk_len: fils pmk length
+ * @fils_pmkid: fils pmkid
+ * @kek: kek
+ * @kek_len: kek length
+ * @tk: tk
+ * @tk_len: tk length
+ * @gtk: gtk
+ * @gtk_len: gtk length
+ * @dst_mac: dst mac
+ * @src_mac: src mac
+ * @hlp_data: hlp data
+ * @hlp_data_len: hlp data length
+ */
+struct fils_connect_rsp_params {
+	uint8_t *fils_pmk;
+	uint8_t fils_pmk_len;
+	uint8_t fils_pmkid[PMKID_LEN];
+	uint8_t kek[MAX_KEK_LENGTH];
+	uint8_t kek_len;
+	uint8_t tk[MAX_TK_LENGTH];
+	uint8_t tk_len;
+	uint8_t gtk[MAX_GTK_LENGTH];
+	uint8_t gtk_len;
+	struct qdf_mac_addr dst_mac;
+	struct qdf_mac_addr src_mac;
+	uint8_t hlp_data[CM_FILS_MAX_HLP_DATA_LEN];
+	uint16_t hlp_data_len;
+};
+#endif
+
+/**
+ * struct connect_rsp_ies - connect rsp ies stored in vdev filled during connect
+ * @bcn_probe_rsp: beacon or probe rsp of connected AP
+ * @assoc_req: assoc req send during conenct
+ * @assoc_rsq: assoc rsp received during connection
+ * @ric_resp_ie: ric ie from assoc resp received during connection
+ * @fills_ie: fills connection ie received during connection
+ */
+struct connect_rsp_ies {
+	struct element_info bcn_probe_rsp;
+	struct element_info assoc_req;
+	struct element_info assoc_rsp;
+	struct element_info ric_resp_ie;
+#ifdef WLAN_FEATURE_FILS_SK
+	struct fils_connect_rsp_params fils_ie;
+#endif
+};
+
+/**
+ * struct disconnect_ies - disconnect ies stored in vdev filled during
+ * disconnect
+ * @peer_discon_ie: disconnect ie sent by peer to be sent to OSIF
+ * @self_discon_ie: disconnect ie to be sent in disassoc/deauth filled by OSIF
+ */
+struct disconnect_ies {
+	struct element_info peer_discon_ie;
+	struct element_info self_discon_ie;
+};
+
+/**
+ * struct cnx_mgr - connect manager req
+ * @vdev: vdev back pointer
+ * @sm: state machine
+ * @req_list: connect/disconnect req list
+ * @disconnect_count: disconnect count
+ * @connect_count: connect count
+ * @force_rsne_override: if QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE is set by
+ * framework
+ * @req_ie: request ies for connect
+ * @rsp_ie: connect resp ie
+ * @discon_ie: disconnect IE
+ * @fils_info: fils info for the connect req
+ */
+struct cnx_mgr {
+	struct wlan_objmgr_vdev *vdev;
+	struct cm_state_sm sm;
+	qdf_list_t req_list;
+	uint8_t disconnect_count;
+	uint8_t connect_count;
+	bool force_rsne_override;
+	struct connect_req_ies req_ie;
+	struct connect_rsp_ies rsp_ie;
+	struct disconnect_ies discon_ie;
+#ifdef WLAN_FEATURE_FILS_SK
+	struct wlan_fils_con_info fils_info;
+#endif
+};
+
+/**
+ * mlme_cm_init() - Invoke connection manager init
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ *
+ * API allocates CM and init
+ *
+ * Return: SUCCESS on successful allocation
+ *         FAILURE, if registration fails
+ */
+QDF_STATUS mlme_cm_init(struct vdev_mlme_obj *vdev_mlme);
+
+/**
+ * mlme_cm_deinit() - Invoke connection manager deinit
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ *
+ * API destroys CM
+ *
+ * Return: SUCCESS on successful deletion
+ *         FAILURE, if deletion fails
+ */
+QDF_STATUS mlme_cm_deinit(struct vdev_mlme_obj *vdev_mlme);
+#else
+
+static inline QDF_STATUS mlme_cm_init(struct vdev_mlme_obj *vdev_mlme)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS mlme_cm_deinit(struct vdev_mlme_obj *vdev_mlme)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+#endif /* FEATURE_CM_ENABLE */
+
+#endif /* __WLAN_CM_MAIN_H__ */

+ 26 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h

@@ -0,0 +1,26 @@
+/*
+ * 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: wlan_cm_main_api.h
+ *
+ * This header file maintain connect, disconnect APIs of connection manager
+ */
+
+#ifndef __WLAN_CM_MAIN_API_H__
+#define __WLAN_CM_MAIN_API_H__
+
+#endif /* __WLAN_CM_MAIN_API_H__ */

+ 178 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_roam_sm.c

@@ -0,0 +1,178 @@
+/*
+ * 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 general SM framework for connection manager roaming sm
+ */
+
+#include "wlan_cm_main.h"
+#include "wlan_cm_roam_sm.h"
+#include "wlan_cm_sm.h"
+
+void mlme_cm_state_roaming_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	mlme_cm_sm_state_update(cm_ctx, WLAN_CM_S_ROAMING, WLAN_CM_SS_IDLE);
+}
+
+void mlme_cm_state_roaming_exit(void *ctx)
+{
+}
+
+bool mlme_cm_state_roaming_event(void *ctx, uint16_t event,
+				 uint16_t event_data_len,
+				 void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+#ifdef WLAN_FEATURE_HOST_ROAM
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+void mlme_cm_subst_preauth_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	if (mlme_cm_get_state(cm_ctx) != WLAN_CM_S_ROAMING)
+		QDF_BUG(0);
+
+	mlme_cm_set_substate(cm_ctx, WLAN_CM_SS_PREAUTH);
+}
+
+void mlme_cm_subst_preauth_exit(void *ctx)
+{
+}
+
+bool mlme_cm_subst_preauth_event(void *ctx, uint16_t event,
+				 uint16_t event_data_len,
+				 void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+#endif /* WLAN_FEATURE_PREAUTH_ENABLE */
+
+void mlme_cm_subst_reassoc_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	if (mlme_cm_get_state(cm_ctx) != WLAN_CM_S_ROAMING)
+		QDF_BUG(0);
+
+	mlme_cm_set_substate(cm_ctx, WLAN_CM_SS_REASSOC);
+}
+
+void mlme_cm_subst_reassoc_exit(void *ctx)
+{
+}
+
+bool mlme_cm_subst_reassoc_event(void *ctx, uint16_t event,
+				 uint16_t event_data_len,
+				 void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+#endif /* WLAN_FEATURE_HOST_ROAM */
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+void mlme_cm_subst_roam_start_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	if (mlme_cm_get_state(cm_ctx) != WLAN_CM_S_ROAMING)
+		QDF_BUG(0);
+
+	mlme_cm_set_substate(cm_ctx, WLAN_CM_SS_ROAM_STARTED);
+}
+
+void mlme_cm_subst_roam_start_exit(void *ctx)
+{
+}
+
+bool mlme_cm_subst_roam_start_event(void *ctx, uint16_t event,
+				    uint16_t event_data_len,
+				    void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+void mlme_cm_subst_roam_sync_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	if (mlme_cm_get_state(cm_ctx) != WLAN_CM_S_ROAMING)
+		QDF_BUG(0);
+
+	mlme_cm_set_substate(cm_ctx, WLAN_CM_SS_ROAM_SYNC);
+}
+
+void mlme_cm_subst_roam_sync_exit(void *ctx)
+{
+}
+
+bool mlme_cm_subst_roam_sync_event(void *ctx, uint16_t event,
+				   uint16_t event_data_len,
+				   void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+#endif /* WLAN_FEATURE_ROAM_OFFLOAD */

+ 219 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_roam_sm.h

@@ -0,0 +1,219 @@
+/*
+ * 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: wlan_cm_roam_sm.h
+ *
+ * This header file maintain structures required for connection mgr roam sm
+ */
+
+#ifndef __WLAN_CM_ROAM_SM_H__
+#define __WLAN_CM_ROAM_SM_H__
+
+/**
+ * mlme_cm_state_roaming_entry() - Entry API for roaming state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to roaming state
+ *
+ * Return: void
+ */
+void mlme_cm_state_roaming_entry(void *ctx);
+
+/**
+ * mlme_cm_state_roaming_exit() - Exit API for roaming state for connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from roaming state
+ *
+ * Return: void
+ */
+void mlme_cm_state_roaming_exit(void *ctx);
+
+/**
+ * mlme_cm_state_roaming_event() - Roaming State event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in roaming state
+ *
+ * Return: bool
+ */
+bool mlme_cm_state_roaming_event(void *ctx, uint16_t event,
+				 uint16_t event_data_len,
+				 void *event_data);
+
+#ifdef WLAN_FEATURE_HOST_ROAM
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+/**
+ * mlme_cm_subst_preauth_entry() - Entry API for preauth sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to preauth sub-state
+ *
+ * Return: void
+ */
+void mlme_cm_subst_preauth_entry(void *ctx);
+
+/**
+ * mlme_cm_subst_preauth_exit() - Exit API for preauth sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from preauth sub-state
+ *
+ * Return: void
+ */
+void mlme_cm_subst_preauth_exit(void *ctx);
+
+/**
+ * mlme_cm_subst_preauth_event() - Preauth sub-state event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in preauth sub-state
+ *
+ * Return: bool
+ */
+bool mlme_cm_subst_preauth_event(void *ctx, uint16_t event,
+				 uint16_t event_data_len,
+				 void *event_data);
+#else /* WLAN_FEATURE_PREAUTH_ENABLE  && WLAN_FEATURE_HOST_ROAM */
+
+static inline void mlme_cm_subst_preauth_entry(void *ctx) {}
+
+static inline void mlme_cm_subst_preauth_exit(void *ctx) {}
+
+static inline bool mlme_cm_subst_preauth_event(void *ctx, uint16_t event,
+					       uint16_t event_data_len,
+					       void *event_data)
+{
+	return true;
+}
+#endif /* WLAN_FEATURE_PREAUTH_ENABLE */
+
+/**
+ * mlme_cm_subst_reassoc_entry() - Entry API for reassoc sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to reassoc sub-state
+ *
+ * Return: void
+ */
+void mlme_cm_subst_reassoc_entry(void *ctx);
+
+/**
+ * mlme_cm_subst_reassoc_exit() - Exit API for reassoc sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from reassoc sub-state
+ *
+ * Return: void
+ */
+void mlme_cm_subst_reassoc_exit(void *ctx);
+
+/**
+ * mlme_cm_subst_reassoc_event() - Reassoc sub-state event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in preauth sub-state
+ *
+ * Return: bool
+ */
+bool mlme_cm_subst_reassoc_event(void *ctx, uint16_t event,
+				 uint16_t event_data_len,
+				 void *event_data);
+#endif /* WLAN_FEATURE_HOST_ROAM */
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+
+/**
+ * mlme_cm_subst_roam_start_entry() - Entry API for roam start sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to roam start sub-state
+ *
+ * Return: void
+ */
+void mlme_cm_subst_roam_start_entry(void *ctx);
+
+/**
+ * mlme_cm_subst_roam_start_exit() - Exit API for roam start sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from roam start sub-state
+ *
+ * Return: void
+ */
+void mlme_cm_subst_roam_start_exit(void *ctx);
+
+/**
+ * mlme_cm_subst_roam_start_event() - Roam start sub-state event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in roam start sub-state
+ *
+ * Return: bool
+ */
+bool mlme_cm_subst_roam_start_event(void *ctx, uint16_t event,
+				    uint16_t event_data_len,
+				    void *event_data);
+
+/**
+ * mlme_cm_subst_roam_sync_entry() - Entry API for roam sync sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to roam sync sub-state
+ *
+ * Return: void
+ */
+void mlme_cm_subst_roam_sync_entry(void *ctx);
+
+/**
+ * mlme_cm_subst_roam_sync_exit() - Exit API for roam sync sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from roam sync sub-state
+ *
+ * Return: void
+ */
+void mlme_cm_subst_roam_sync_exit(void *ctx);
+
+/**
+ * mlme_cm_subst_roam_sync_event() - Roam sync sub-state event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in roam sync sub-state
+ *
+ * Return: bool
+ */
+bool mlme_cm_subst_roam_sync_event(void *ctx, uint16_t event,
+				   uint16_t event_data_len,
+				   void *event_data);
+#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
+
+#endif /* __WLAN_CM_ROAM_SM_H__ */

+ 764 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_sm.c

@@ -0,0 +1,764 @@
+/*
+ * 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 general SM framework for connection manager
+ */
+
+#include "wlan_cm_main.h"
+#include "wlan_cm_sm.h"
+#include "wlan_cm_roam_sm.h"
+
+void mlme_cm_set_state(struct cnx_mgr *cm_ctx, enum wlan_cm_sm_state state)
+{
+	if (state < WLAN_CM_S_MAX)
+		cm_ctx->sm.cm_state = state;
+	else
+		mlme_err("mlme state (%d) is invalid", state);
+}
+
+void mlme_cm_set_substate(struct cnx_mgr *cm_ctx,
+			  enum wlan_cm_sm_state substate)
+{
+	if ((substate > WLAN_CM_S_MAX) && (substate < WLAN_CM_SS_MAX))
+		cm_ctx->sm.cm_substate = substate;
+	else
+		mlme_err(" mlme sub state (%d) is invalid", substate);
+}
+
+void mlme_cm_sm_state_update(struct cnx_mgr *cm_ctx,
+			     enum wlan_cm_sm_state state,
+			     enum wlan_cm_sm_state substate)
+{
+	if (!cm_ctx) {
+		mlme_err("cm_ctx is NULL");
+		return;
+	}
+
+	mlme_cm_set_state(cm_ctx, state);
+	mlme_cm_set_substate(cm_ctx, substate);
+}
+
+/**
+ * mlme_cm_state_init_entry() - Entry API for init state for connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to init state
+ *
+ * Return: void
+ */
+static void mlme_cm_state_init_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	mlme_cm_sm_state_update(cm_ctx, WLAN_CM_S_INIT, WLAN_CM_SS_IDLE);
+}
+
+/**
+ * mlme_cm_state_init_exit() - Exit API for init state for connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from init state
+ *
+ * Return: void
+ */
+static void mlme_cm_state_init_exit(void *ctx)
+{
+}
+
+/**
+ * mlme_cm_state_init_event() - Init State event handler for connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in INIT state
+ *
+ * Return: bool
+ */
+static bool mlme_cm_state_init_event(void *ctx, uint16_t event,
+				     uint16_t event_data_len,
+				     void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * mlme_cm_state_connecting_entry() - Entry API for connecting state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to connecting state
+ *
+ * Return: void
+ */
+static void mlme_cm_state_connecting_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	mlme_cm_sm_state_update(cm_ctx, WLAN_CM_S_CONNECTING, WLAN_CM_SS_IDLE);
+}
+
+/**
+ * mlme_cm_state_connecting_exit() - Exit API for connecting state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from connecting state
+ *
+ * Return: void
+ */
+static void mlme_cm_state_connecting_exit(void *ctx)
+{
+}
+
+/**
+ * mlme_cm_state_connecting_event() - Connecting State event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in CONNECTING state
+ *
+ * Return: bool
+ */
+static bool mlme_cm_state_connecting_event(void *ctx, uint16_t event,
+					   uint16_t event_data_len,
+					   void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * mlme_cm_state_connected_entry() - Entry API for connected state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to connected state
+ *
+ * Return: void
+ */
+static void mlme_cm_state_connected_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	mlme_cm_sm_state_update(cm_ctx, WLAN_CM_S_CONNECTED, WLAN_CM_SS_IDLE);
+}
+
+/**
+ * mlme_cm_state_connected_exit() - Exit API for connected state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from connected state
+ *
+ * Return: void
+ */
+static void mlme_cm_state_connected_exit(void *ctx)
+{
+}
+
+/**
+ * mlme_cm_state_connected_event() - Connected State event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in CONNECTED state
+ *
+ * Return: bool
+ */
+static bool mlme_cm_state_connected_event(void *ctx, uint16_t event,
+					  uint16_t event_data_len,
+					  void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * mlme_cm_state_disconnecting_entry() - Entry API for disconnecting state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to disconnecting state
+ *
+ * Return: void
+ */
+static void mlme_cm_state_disconnecting_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	mlme_cm_sm_state_update(cm_ctx, WLAN_CM_S_DISCONNECTING,
+				WLAN_CM_SS_IDLE);
+}
+
+/**
+ * mlme_cm_state_disconnecting_exit() - Exit API for disconnecting state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from disconnecting state
+ *
+ * Return: void
+ */
+static void mlme_cm_state_disconnecting_exit(void *ctx)
+{
+}
+
+/**
+ * mlme_cm_state_connected_event() - Disconnecting State event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in Disconnecting state
+ *
+ * Return: bool
+ */
+static bool mlme_cm_state_disconnecting_event(void *ctx, uint16_t event,
+					      uint16_t event_data_len,
+					      void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * mlme_cm_subst_join_pending_entry() - Entry API for join pending sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to join pending sub-state
+ *
+ * Return: void
+ */
+static void mlme_cm_subst_join_pending_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	if (mlme_cm_get_state(cm_ctx) != WLAN_CM_S_CONNECTING)
+		QDF_BUG(0);
+
+	mlme_cm_set_substate(cm_ctx, WLAN_CM_SS_JOIN_PENDING);
+}
+
+/**
+ * mlme_cm_subst_join_pending_exit() - Exit API for join pending sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from join pending sub-state
+ *
+ * Return: void
+ */
+static void mlme_cm_subst_join_pending_exit(void *ctx)
+{
+}
+
+/**
+ * mlme_cm_subst_join_pending_event() - Join pending sub-state event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in Join pending sub-state
+ *
+ * Return: bool
+ */
+static bool mlme_cm_subst_join_pending_event(void *ctx, uint16_t event,
+					     uint16_t event_data_len,
+					     void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * mlme_cm_subst_scan_entry() - Entry API for scan sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to scan sub-state
+ *
+ * Return: void
+ */
+static void mlme_cm_subst_scan_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	if (mlme_cm_get_state(cm_ctx) != WLAN_CM_S_CONNECTING)
+		QDF_BUG(0);
+
+	mlme_cm_set_substate(cm_ctx, WLAN_CM_SS_SCAN);
+}
+
+/**
+ * mlme_cm_subst_scan_exit() - Exit API for scan sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from scan sub-state
+ *
+ * Return: void
+ */
+static void mlme_cm_subst_scan_exit(void *ctx)
+{
+}
+
+/**
+ * mlme_cm_subst_scan_event() - Scan sub-state event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in scan sub-state
+ *
+ * Return: bool
+ */
+static bool mlme_cm_subst_scan_event(void *ctx, uint16_t event,
+				     uint16_t event_data_len, void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * mlme_cm_subst_join_active_entry() - Entry API for join active sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on moving to join active sub-state
+ *
+ * Return: void
+ */
+static void mlme_cm_subst_join_active_entry(void *ctx)
+{
+	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+
+	if (mlme_cm_get_state(cm_ctx) != WLAN_CM_S_CONNECTING)
+		QDF_BUG(0);
+
+	mlme_cm_set_substate(cm_ctx, WLAN_CM_SS_JOIN_ACTIVE);
+}
+
+/**
+ * mlme_cm_subst_join_active_exit() - Exit API for join active sub-state for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to perform operations on exiting from join active sub-state
+ *
+ * Return: void
+ */
+static void mlme_cm_subst_join_active_exit(void *ctx)
+{
+}
+
+/**
+ * mlme_cm_subst_join_active_event() - Join active sub-state event handler for
+ * connection mgr
+ * @ctx: connection manager ctx
+ *
+ * API to handle events in join active sub-state
+ *
+ * Return: bool
+ */
+static bool mlme_cm_subst_join_active_event(void *ctx, uint16_t event,
+					    uint16_t event_data_len,
+					    void *event_data)
+{
+//	struct cnx_mgr *cm_ctx = (struct cnx_mgr *)ctx;
+	bool status;
+
+	switch (event) {
+	default:
+		status = false;
+		break;
+	}
+
+	return status;
+}
+
+struct wlan_sm_state_info cm_sm_info[] = {
+	{
+		(uint8_t)WLAN_CM_S_INIT,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		true,
+		"INIT",
+		mlme_cm_state_init_entry,
+		mlme_cm_state_init_exit,
+		mlme_cm_state_init_event
+	},
+	{
+		(uint8_t)WLAN_CM_S_CONNECTING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		true,
+		"CONNECTING",
+		mlme_cm_state_connecting_entry,
+		mlme_cm_state_connecting_exit,
+		mlme_cm_state_connecting_event
+	},
+	{
+		(uint8_t)WLAN_CM_S_CONNECTED,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		true,
+		"CONNECTED",
+		mlme_cm_state_connected_entry,
+		mlme_cm_state_connected_exit,
+		mlme_cm_state_connected_event
+	},
+	{
+		(uint8_t)WLAN_CM_S_DISCONNECTING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		true,
+		"DISCONNECTING",
+		mlme_cm_state_disconnecting_entry,
+		mlme_cm_state_disconnecting_exit,
+		mlme_cm_state_disconnecting_event
+	},
+	{
+		(uint8_t)WLAN_CM_S_ROAMING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		true,
+		"ROAMING",
+		mlme_cm_state_roaming_entry,
+		mlme_cm_state_roaming_exit,
+		mlme_cm_state_roaming_event
+	},
+	{
+		(uint8_t)WLAN_CM_S_MAX,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"INVALID",
+		NULL,
+		NULL,
+		NULL
+	},
+	{
+		(uint8_t)WLAN_CM_SS_IDLE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"IDLE",
+		NULL,
+		NULL,
+		NULL
+	},
+	{
+		(uint8_t)WLAN_CM_SS_JOIN_PENDING,
+		(uint8_t)WLAN_CM_S_CONNECTING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"JOIN_PENDING",
+		mlme_cm_subst_join_pending_entry,
+		mlme_cm_subst_join_pending_exit,
+		mlme_cm_subst_join_pending_event
+	},
+	{
+		(uint8_t)WLAN_CM_SS_SCAN,
+		(uint8_t)WLAN_CM_S_CONNECTING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"SCAN",
+		mlme_cm_subst_scan_entry,
+		mlme_cm_subst_scan_exit,
+		mlme_cm_subst_scan_event
+	},
+	{
+		(uint8_t)WLAN_CM_SS_JOIN_ACTIVE,
+		(uint8_t)WLAN_CM_S_CONNECTING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"JOIN_ACTIVE",
+		mlme_cm_subst_join_active_entry,
+		mlme_cm_subst_join_active_exit,
+		mlme_cm_subst_join_active_event
+	},
+#ifdef WLAN_FEATURE_HOST_ROAM
+	{
+		(uint8_t)WLAN_CM_SS_PREAUTH,
+		(uint8_t)WLAN_CM_S_ROAMING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"PREAUTH",
+		mlme_cm_subst_preauth_entry,
+		mlme_cm_subst_preauth_exit,
+		mlme_cm_subst_preauth_event
+	},
+	{
+		(uint8_t)WLAN_CM_SS_REASSOC,
+		(uint8_t)WLAN_CM_S_ROAMING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"REASSOC",
+		mlme_cm_subst_reassoc_entry,
+		mlme_cm_subst_reassoc_exit,
+		mlme_cm_subst_reassoc_event
+	},
+#endif
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+	{
+		(uint8_t)WLAN_CM_SS_ROAM_STARTED,
+		(uint8_t)WLAN_CM_S_ROAMING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"ROAM_START",
+		mlme_cm_subst_roam_start_entry,
+		mlme_cm_subst_roam_start_exit,
+		mlme_cm_subst_roam_start_event
+	},
+	{
+		(uint8_t)WLAN_CM_SS_ROAM_SYNC,
+		(uint8_t)WLAN_CM_S_ROAMING,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"ROAM_SYNC",
+		mlme_cm_subst_roam_sync_entry,
+		mlme_cm_subst_roam_sync_exit,
+		mlme_cm_subst_roam_sync_event
+	},
+#endif
+	{
+		(uint8_t)WLAN_CM_SS_MAX,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
+		false,
+		"INVALID",
+		NULL,
+		NULL,
+		NULL
+	},
+};
+
+static const char *cm_sm_event_names[] = {
+	"EV_CONNECT_REQ",
+	"EV_SCAN_FOR_SSID",
+	"EV_SCAN_FOR_SSID_SUCCESS",
+	"EV_SCAN_FOR_SSID_FAILURE",
+	"EV_CONNECT_START_REQ",
+	"EV_CONNECT_START",
+	"EV_CONNECT_SUCCESS",
+	"EV_CONNECT_NEXT_CANDIDATE",
+	"EV_CONNECT_FAILURE",
+	"EV_DISCONNECT_REQ",
+	"EV_DISCONNECT_START_REQ",
+	"EV_DISCONNECT_START",
+	"EV_DISCONNECT_DONE",
+	"EV_ROAM_START",
+	"EV_ROAM_SYNC",
+	"EV_ROAM_INVOKE_FAIL",
+	"EV_ROAM_HO_FAIL",
+	"EV_PREAUTH_DONE",
+	"EV_GET_NEXT_PREAUTH_AP",
+	"EV_PREAUTH_FAIL",
+	"EV_START_REASSOC",
+	"EV_REASSOC_DONE",
+	"EV_REASSOC_FAILURE",
+	"EV_ROAM_COMPLETE",
+	"EV_CONNECT_TIMEOUT",
+	"EV_CONNECT_SER_FAIL",
+	"EV_HW_MODE_CHANGE_FAIL",
+};
+
+enum wlan_cm_sm_state mlme_cm_get_state(struct cnx_mgr *cm_ctx)
+{
+	enum QDF_OPMODE op_mode;
+
+	if (!cm_ctx || !cm_ctx->vdev)
+		return WLAN_CM_S_MAX;
+
+	op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev);
+
+	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
+		return WLAN_CM_S_MAX;
+
+	return cm_ctx->sm.cm_state;
+}
+
+enum wlan_cm_sm_state mlme_cm_get_sub_state(struct cnx_mgr *cm_ctx)
+{
+	enum QDF_OPMODE op_mode;
+
+	if (!cm_ctx || !cm_ctx->vdev)
+		return WLAN_CM_SS_MAX;
+
+	op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev);
+
+	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
+		return WLAN_CM_SS_MAX;
+
+	return cm_ctx->sm.cm_substate;
+}
+
+static inline
+QDF_STATUS mlme_cm_sm_deliver_event(struct cnx_mgr *cm_ctx,
+				    enum wlan_cm_sm_evt event,
+				    uint16_t event_data_len, void *event_data)
+{
+	return wlan_sm_dispatch(cm_ctx->sm.sm_hdl, event,
+				event_data_len, event_data);
+}
+
+static void mlme_cm_sm_print_state_event(struct cnx_mgr *cm_ctx,
+					 enum wlan_cm_sm_evt event)
+{
+	enum wlan_cm_sm_state state;
+	enum wlan_cm_sm_state substate;
+
+	state = mlme_cm_get_state(cm_ctx);
+	substate = mlme_cm_get_sub_state(cm_ctx);
+
+	mlme_nofl_debug("[%s]%s - %s, %s", cm_ctx->sm.sm_hdl->name,
+			cm_sm_info[state].name, cm_sm_info[substate].name,
+			cm_sm_event_names[event]);
+}
+
+static void mlme_cm_sm_print_state(struct cnx_mgr *cm_ctx)
+{
+	enum wlan_cm_sm_state state;
+	enum wlan_cm_sm_state substate;
+
+	state = mlme_cm_get_state(cm_ctx);
+	substate = mlme_cm_get_sub_state(cm_ctx);
+
+	mlme_nofl_debug("[%s]%s - %s", cm_ctx->sm.sm_hdl->name,
+			cm_sm_info[state].name, cm_sm_info[substate].name);
+}
+
+QDF_STATUS mlme_cm_sm_deliver_evt(struct wlan_objmgr_vdev *vdev,
+				  enum wlan_cm_sm_evt event,
+				  uint16_t event_data_len,
+				  void *event_data)
+{
+	struct vdev_mlme_obj *vdev_mlme;
+	QDF_STATUS status;
+	enum wlan_cm_sm_state state_entry, state_exit;
+	enum wlan_cm_sm_state substate_entry, substate_exit;
+	enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev);
+	struct cnx_mgr *cm_ctx;
+
+	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) {
+		mlme_err("Invalid mode %d", op_mode);
+		return QDF_STATUS_E_NOSUPPORT;
+	}
+
+	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
+	if (!vdev_mlme || !vdev_mlme->cnx_mgr_ctx) {
+		mlme_err("vdev mlme or cm ctx is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+	cm_ctx = vdev_mlme->cnx_mgr_ctx;
+	mlme_cm_lock_acquire(cm_ctx);
+
+	/* store entry state and sub state for prints */
+	state_entry = mlme_cm_get_state(cm_ctx);
+	substate_entry = mlme_cm_get_sub_state(cm_ctx);
+	mlme_cm_sm_print_state_event(cm_ctx, event);
+
+	status = mlme_cm_sm_deliver_event(cm_ctx, event, event_data_len,
+					  event_data);
+	/* Take exit state, exit substate for prints */
+	state_exit = mlme_cm_get_state(cm_ctx);
+	substate_exit = mlme_cm_get_sub_state(cm_ctx);
+	/* If no state and substate change, don't print */
+	if (!((state_entry == state_exit) && (substate_entry == substate_exit)))
+		mlme_cm_sm_print_state(cm_ctx);
+	mlme_cm_lock_release(cm_ctx);
+
+	return status;
+}
+
+QDF_STATUS mlme_cm_sm_create(struct cnx_mgr *cm_ctx)
+{
+	struct wlan_sm *sm;
+	uint8_t name[WLAN_SM_ENGINE_MAX_NAME];
+
+	qdf_snprintf(name, sizeof(name), "CM-VDEV-%d",
+		     wlan_vdev_get_id(cm_ctx->vdev));
+	sm = wlan_sm_create(name, cm_ctx,
+			    WLAN_CM_S_INIT,
+			    cm_sm_info,
+			    QDF_ARRAY_SIZE(cm_sm_info),
+			    cm_sm_event_names,
+			    QDF_ARRAY_SIZE(cm_sm_event_names));
+	if (!sm) {
+		mlme_err("CM MLME SM allocation failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+	cm_ctx->sm.sm_hdl = sm;
+
+	mlme_cm_lock_create(cm_ctx);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS mlme_cm_sm_destroy(struct cnx_mgr *cm_ctx)
+{
+	mlme_cm_lock_destroy(cm_ctx);
+	wlan_sm_delete(cm_ctx->sm.sm_hdl);
+
+	return QDF_STATUS_SUCCESS;
+}

+ 237 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_sm.h

@@ -0,0 +1,237 @@
+/*
+ * 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: wlan_cm_sm.h
+ *
+ * This header file maintain structures required for connection mgr sm infra
+ */
+
+#ifndef __WLAN_CM_SM_H__
+#define __WLAN_CM_SM_H__
+
+#ifdef FEATURE_CM_ENABLE
+#include <wlan_sm_engine.h>
+
+/**
+ * mlme_cm_sm_create() - Invoke SM creation for connection manager
+ * @cm_ctx:  connection manager ctx
+ *
+ * API allocates CM MLME SM and initializes SM lock
+ *
+ * Return: SUCCESS on successful allocation
+ *         FAILURE, if registration fails
+ */
+QDF_STATUS mlme_cm_sm_create(struct cnx_mgr *cm_ctx);
+
+/**
+ * mlme_cm_sm_destroy() - Invoke SM deletion for connection manager
+ * @cm_ctx:  connection manager ctx
+ *
+ * API destroys CM MLME SM and SM lock
+ *
+ * Return: SUCCESS on successful deletion
+ *         FAILURE, if deletion fails
+ */
+QDF_STATUS mlme_cm_sm_destroy(struct cnx_mgr *cm_ctx);
+
+/**
+ * mlme_cm_sm_history_print() - Prints SM history
+ * @cm_ctx:  connection manager ctx
+ *
+ * API to print CM SM history
+ *
+ * Return: void
+ */
+#ifdef SM_ENG_HIST_ENABLE
+static inline void mlme_cm_sm_history_print(struct cnx_mgr *cm_ctx)
+{
+	return wlan_sm_print_history(cm_ctx->sm.sm_hdl);
+}
+#else
+static inline void mlme_cm_sm_history_print(struct cnx_mgr *cm_ctx)
+{
+}
+#endif
+
+#ifdef WLAN_CM_USE_SPINLOCK
+/**
+ * mlme_cm_lock_create - Create CM SM mutex/spinlock
+ * @cm_ctx:  connection manager ctx
+ *
+ * Creates CM SM mutex/spinlock
+ *
+ * Return: void
+ */
+static inline void
+mlme_cm_lock_create(struct cnx_mgr *cm_ctx)
+{
+	qdf_spinlock_create(&cm_ctx->sm.cm_sm_lock);
+}
+
+/**
+ * mlme_cm_lock_destroy - Destroy CM SM mutex/spinlock
+ * @cm_ctx:  connection manager ctx
+ *
+ * Destroy CM SM mutex/spinlock
+ *
+ * Return: void
+ */
+static inline void
+mlme_cm_lock_destroy(struct cnx_mgr *cm_ctx)
+{
+	qdf_spinlock_destroy(&cm_ctx->sm.cm_sm_lock);
+}
+
+/**
+ * mlme_cm_lock_acquire - acquire CM SM mutex/spinlock
+ * @cm_ctx:  connection manager ctx
+ *
+ * acquire CM SM mutex/spinlock
+ *
+ * return: void
+ */
+static inline void mlme_cm_lock_acquire(struct cnx_mgr *cm_ctx)
+{
+	qdf_spinlock_acquire(&cm_ctx->sm.cm_sm_lock);
+}
+
+/**
+ * mlme_cm_lock_release - release CM SM mutex/spinlock
+ * @cm_ctx:  connection manager ctx
+ *
+ * release CM SM mutex/spinlock
+ *
+ * return: void
+ */
+static inline void mlme_cm_lock_release(struct cnx_mgr *cm_ctx)
+{
+	qdf_spinlock_release(&cm_ctx->sm.cm_sm_lock);
+}
+#else
+static inline void
+mlme_cm_lock_create(struct cnx_mgr *cm_ctx)
+{
+	qdf_mutex_create(&cm_ctx->sm.cm_sm_lock);
+}
+
+static inline void
+mlme_cm_lock_destroy(struct cnx_mgr *cm_ctx)
+{
+	qdf_mutex_destroy(&cm_ctx->sm.cm_sm_lock);
+}
+
+static inline void mlme_cm_lock_acquire(struct cnx_mgr *cm_ctx)
+{
+	qdf_mutex_acquire(&cm_ctx->sm.cm_sm_lock);
+}
+
+static inline void mlme_cm_lock_release(struct cnx_mgr *cm_ctx)
+{
+	qdf_mutex_release(&cm_ctx->sm.cm_sm_lock);
+}
+#endif /* WLAN_CM_USE_SPINLOCK */
+
+/**
+ * mlme_cm_sm_transition_to() - invokes state transition
+ * @cm_ctx:  connection manager ctx
+ * @state: new cm state
+ *
+ * API to invoke SM API to move to new state
+ *
+ * Return: void
+ */
+static inline void mlme_cm_sm_transition_to(struct cnx_mgr *cm_ctx,
+					    enum wlan_cm_sm_state state)
+{
+	wlan_sm_transition_to(cm_ctx->sm.sm_hdl, state);
+}
+
+/**
+ * mlme_cm_get_state() - get mlme state
+ * @cm_ctx: connection manager SM ctx
+ *
+ * API to get cm state
+ *
+ * Return: state of cm
+ */
+enum wlan_cm_sm_state mlme_cm_get_state(struct cnx_mgr *cm_ctx);
+
+/**
+ * mlme_cm_get_sub_state() - get mlme substate
+ * @cm_ctx: connection manager SM ctx
+ *
+ * API to get cm substate
+ *
+ * Return: substate of cm
+ */
+enum wlan_cm_sm_state mlme_cm_get_sub_state(struct cnx_mgr *cm_ctx);
+
+/**
+ * mlme_cm_set_state() - set cm mlme state
+ * @cm_ctx: connection manager SM ctx
+ * @state: cm state
+ *
+ * API to set cm state
+ *
+ * Return: void
+ */
+void mlme_cm_set_state(struct cnx_mgr *cm_ctx, enum wlan_cm_sm_state state);
+/**
+ * mlme_cm_set_substate() - set cm mlme sub state
+ * @cm_ctx: connection manager SM ctx
+ * @substate: cm sub state
+ *
+ * API to set cm sub state
+ *
+ * Return: void
+ */
+void mlme_cm_set_substate(struct cnx_mgr *cm_ctx,
+			  enum wlan_cm_sm_state substate);
+
+/**
+ * mlme_cm_sm_state_update() - set cm mlme state and sub state
+ * @cm_ctx: connection manager SM ctx
+ * @state: cm state
+ * @substate: cm sub state
+ *
+ * API to invoke util APIs to set state and MLME sub state
+ *
+ * Return: void
+ */
+void mlme_cm_sm_state_update(struct cnx_mgr *cm_ctx,
+			     enum wlan_cm_sm_state state,
+			     enum wlan_cm_sm_state substate);
+
+/**
+ * mlme_cm_sm_deliver_evt() - Delivers event to CM SM
+ * @vdev: Object manager VDEV object
+ * @event: CM event
+ * @event_data_len: data size
+ * @event_data: event data
+ *
+ * API to dispatch event to VDEV MLME SM with lock acquired
+ *
+ * Return: SUCCESS: on handling event
+ *         FAILURE: on ignoring the event
+ */
+QDF_STATUS mlme_cm_sm_deliver_evt(struct wlan_objmgr_vdev *vdev,
+				  enum wlan_cm_sm_evt event,
+				  uint16_t event_data_len,
+				  void *event_data);
+
+#endif /* FEATURE_CM_ENABLE */
+#endif /* __WLAN_CM_SM_H__ */

+ 260 - 0
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h

@@ -0,0 +1,260 @@
+/*
+ * 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: wlan_cm_public_struct.h
+ *
+ * This header file maintain public structures required for connection mgr
+ */
+
+#ifndef __WLAN_CM_PUBLIC_STRUCT_H__
+#define __WLAN_CM_PUBLIC_STRUCT_H__
+
+#ifdef FEATURE_CM_ENABLE
+#include <wlan_scan_public_structs.h>
+
+/**
+ * struct wlan_cm_wep_key_params - store wep key info
+ * @key: key info
+ * @seq: seq info
+ * @key_len: key length
+ * @seq_len: seq len
+ * @key_idx: key index
+ */
+struct wlan_cm_wep_key_params {
+	uint8_t *key;
+	uint8_t *seq;
+	uint8_t key_len;
+	uint8_t seq_len;
+	uint8_t key_idx;
+};
+
+#define WLAN_CM_MAX_NR_CIPHER_SUITES 5
+#define WLAN_CM_MAX_NR_AKM_SUITES 2
+
+/**
+ * struct wlan_cm_connect_crypto_info - Crypto settings
+ * @wpa_versions: indicates which, if any, WPA versions are enabled
+ *	(from enum nl80211_wpa_versions)
+ * @group_cipher: group key cipher suite (or 0 if unset)
+ * @n_ciphers_pairwise: number of AP supported unicast ciphers
+ * @ciphers_pairwise: unicast key cipher suites
+ * @n_akm_suites: number of AKM suites
+ * @akm_suites: AKM suites
+ * @wep_keys: static WEP keys, if not NULL points to an array of
+ *	MAX_WEP_KEYS WEP keys
+ * @pmf_cap: Pmf capability
+ */
+struct wlan_cm_connect_crypto_info {
+	uint32_t wpa_versions;
+	wlan_crypto_auth_mode auth_type;
+	wlan_crypto_cipher_type group_cipher;
+	uint32_t n_ciphers_pairwise;
+	wlan_crypto_cipher_type ciphers_pairwise[WLAN_CM_MAX_NR_CIPHER_SUITES];
+	uint32_t n_akm_suites;
+	wlan_crypto_key_mgmt akm_suites[WLAN_CM_MAX_NR_AKM_SUITES];
+	struct wlan_cm_wep_key_params wep_keys;
+	enum wlan_pmf_cap pmf_cap;
+	uint32_t rsn_ie_len;
+	uint8_t *rsn_ie;
+};
+
+#ifdef WLAN_FEATURE_FILS_SK
+#define WLAN_CM_FILS_MAX_KEYNAME_NAI_LENGTH 253
+#define WLAN_CM_FILS_MAX_REALM_LEN 255
+#define WLAN_CM_FILS_MAX_RRK_LENGTH 64
+#define WLAN_CM_FILS_MAX_RIK_LENGTH CM_FILS_MAX_RRK_LENGTH
+
+/**
+ * struct wlan_fils_con_info - fils connect req info
+ * @is_fils_connection: is fils connection
+ * @username_len: username length
+ * @username: username
+ * @realm_len: realm length
+ * @realm: realm
+ * @next_seq_num: next seq number
+ * @rrk_len: rrk length
+ * @rrk: rrk
+ */
+struct wlan_fils_con_info {
+	bool is_fils_connection;
+	uint32_t username_len;
+	uint8_t username[WLAN_CM_FILS_MAX_KEYNAME_NAI_LENGTH];
+	uint32_t realm_len;
+	uint8_t realm[WLAN_CM_FILS_MAX_REALM_LEN];
+	uint16_t next_seq_num;
+	uint32_t rrk_len;
+	uint8_t rrk[WLAN_CM_FILS_MAX_RRK_LENGTH];
+};
+#endif
+
+/**
+ * enum wlan_cm_source - connection manager req source
+ * @CM_OSIF_CONENCT_REQ: Connect req initiated by OSIF or north bound
+ * @CM_ROAMING: Roaming request
+ * @CM_OSIF_DISCONNECT: Disconnect req initiated by OSIF or north bound
+ * @CM_PEER_DISCONNECT: Disconnect req initiated by peer sending deauth/disassoc
+ * only for this localy generated will be false while indicating to kernel
+ * @CM_SB_DISCONNECT: Disconnect req initiated by South bound/VDEV mgr/Peer mgr
+ * @CM_INTERNAL_DISCONNECT: Internal disconnect initiated by Connection manager
+ * on receiving the back to back commands
+ * @CM_ROAM_DISCONNECT: Disconnect req due to HO failure
+ */
+enum wlan_cm_source {
+	CM_OSIF_CONENCT_REQ,
+	CM_ROAMING,
+	CM_OSIF_DISCONNECT,
+	CM_PEER_DISCONNECT,
+	CM_SB_DISCONNECT,
+	CM_INTERNAL_DISCONNECT,
+	CM_ROAM_DISCONNECT,
+};
+
+/**
+ * struct wlan_cm_connect_req - connect req from requester
+ * @vdev_id: vdev id
+ * @source: source of the req
+ * @bssid: bssid given
+ * @prev_bssid: prev AP bssid, given in case supplican want to roam to new BSSID
+ * @ssid: profile SSID
+ * @bssid_hint: bssid hint to connect
+ * @chan_freq: channel of the AP
+ * @crypto: crypto related info
+ * @connect_ie: connect IE additional assoc IE
+ * @ht_caps: ht capability
+ * @ht_caps_mask: mask of valid ht caps
+ * @vht_caps: vht capability
+ * @vht_caps_mask: mask of valid vht caps
+ * @fils_info: Fills related connect info
+ */
+struct wlan_cm_connect_req {
+	uint8_t vdev_id;
+	enum wlan_cm_source source;
+	struct qdf_mac_addr bssid;
+	struct qdf_mac_addr prev_bssid;
+	struct wlan_ssid ssid;
+	struct qdf_mac_addr bssid_hint;
+	uint32_t chan_freq;
+	struct wlan_cm_connect_crypto_info crypto;
+	struct element_info connect_ie;
+	uint16_t ht_caps;
+	uint16_t ht_caps_mask;
+	uint32_t vht_caps;
+	uint32_t vht_caps_mask;
+#ifdef WLAN_FEATURE_FILS_SK
+	struct wlan_fils_con_info fils_info;
+#endif
+};
+
+/**
+ * struct wlan_cm_vdev_connect_req - connect req from connection manager to
+ * vdev mgr
+ * @vdev_id: vdev id
+ * @cm_id: Connect manager id
+ * @bss: scan entry for the candidate
+ */
+struct wlan_cm_vdev_connect_req {
+	uint8_t vdev_id;
+	uint8_t cm_id;
+	struct scan_cache_node *bss;
+};
+
+/**
+ * struct wlan_cm_disconnect_req - disconnect req from requester
+ * @vdev_id: vdev id
+ * @source: source of disconnect
+ * @reason_code: protocol/propitiatory reason code of the disconnect.
+ * propitiatory will be used to send in
+ * QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON
+ * @bssid: bssid of AP
+ */
+struct wlan_cm_disconnect_req {
+	uint8_t vdev_id;
+	enum wlan_cm_source source;
+	uint16_t reason_code;
+	struct qdf_mac_addr bssid;
+};
+
+/**
+ * struct wlan_cm_vdev_discon_req - disconnect req from connection manager to
+ * vdev mgr
+ * @cm_id: connection manager ID
+ * @req: disconnect req
+ */
+struct wlan_cm_vdev_discon_req {
+	uint8_t cm_id;
+	struct wlan_cm_disconnect_req req;
+};
+
+/*
+ * enum wlan_cm_connect_fail_reason: connection manager connect fail reason
+ * @CM_NO_CANDIDATE_FOUND: No candidate found
+ * @CM_JOIN_FAILED: Failed in joining state
+ * (BSS peer creation or other handling)
+ * @CM_JOIN_TIMEOUT: Did not receive beacon or probe response after unicast
+ * probe request
+ * @CM_AUTH_FAILED: Auth rejected by AP
+ * @CM_AUTH_TIMEOUT: No Auth resp from AP
+ * @CM_ASSOC_FAILED: Assoc rejected by AP
+ * @CM_ASSOC_TIMEOUT: No Assoc resp from AP
+ * @CM_HW_MODE_FAILURE: failed to change HW mode
+ * @CM_SER_FAILURE: Failed to serialize command
+ * @CM_GENERIC_FAILURE: Generic failure apart from above
+ */
+enum wlan_cm_connect_fail_reason {
+	CM_NO_CANDIDATE_FOUND,
+	CM_JOIN_FAILED,
+	CM_JOIN_TIMEOUT,
+	CM_AUTH_FAILED,
+	CM_AUTH_TIMEOUT,
+	CM_ASSOC_FAILED,
+	CM_ASSOC_TIMEOUT,
+	CM_HW_MODE_FAILURE,
+	CM_SER_FAILURE,
+	CM_GENERIC_FAILURE,
+};
+
+/**
+ * struct wlan_cm_connect_rsp - connect resp from VDEV mgr and will be sent to
+ * OSIF
+ * @vdev_id: vdev id
+ * @cm_id: Connect manager id
+ * @connect_status: connect status success or failure
+ * @reason: connect fail reason
+ * @reason_code: protocol reason code of the connect failure
+ * @peer_macaddr: bssid of AP
+ */
+struct wlan_cm_connect_rsp {
+	uint8_t vdev_id;
+	uint8_t cm_id;
+	uint8_t connect_status;
+	enum wlan_cm_connect_fail_reason reason;
+	uint8_t failure_code;
+	uint8_t aid;
+};
+
+/**
+ * struct wlan_cm_discon_rsp - disconnect resp from VDEV mgr and will be sent to
+ * OSIF
+ * @req: disconnect req sent to vdev mgr
+ */
+struct wlan_cm_discon_rsp {
+	struct wlan_cm_vdev_discon_req req;
+};
+
+#endif /* FEATURE_CM_ENABLE */
+
+#endif /* __WLAN_CM_PUBLIC_STRUCT_H__ */

+ 5 - 0
umac/mlme/include/wlan_vdev_mlme.h

@@ -26,6 +26,7 @@
 #include <wlan_ext_mlme_obj_types.h>
 
 struct vdev_mlme_obj;
+struct cnx_mgr;
 
 /* Requestor ID for multiple vdev restart */
 #define MULTIPLE_VDEV_RESTART_REQ_ID 0x1234
@@ -536,6 +537,7 @@ struct vdev_mlme_ops {
  * @sm_lock:              VDEV SM lock
  * @vdev_cmd_lock:        VDEV MLME command atomicity
  * @sm_hdl:               VDEV SM handle
+ * @cnx_mgr_ctx: connection manager context, valid for STA and P2P-CLI mode only
  * @vdev: Pointer to vdev objmgr
  * @ops:                  VDEV MLME callback table
  * @ext_vdev_ptr:         VDEV MLME legacy pointer
@@ -550,6 +552,9 @@ struct vdev_mlme_obj {
 	qdf_mutex_t vdev_cmd_lock;
 #endif
 	struct wlan_sm *sm_hdl;
+	union {
+		struct cnx_mgr *cnx_mgr_ctx;
+	};
 	struct wlan_objmgr_vdev *vdev;
 	struct vdev_mlme_ops *ops;
 	mlme_vdev_ext_t *ext_vdev_ptr;

+ 9 - 0
umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c

@@ -33,6 +33,7 @@
 #include <cdp_txrx_cmn.h>
 #include <wlan_lmac_if_def.h>
 #include <target_if_vdev_mgr_tx_ops.h>
+#include "connection_mgr/core/src/wlan_cm_main.h"
 
 static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev,
 					       void *arg)
@@ -103,6 +104,11 @@ static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev,
 		goto init_failed;
 	}
 
+	if (QDF_IS_STATUS_ERROR(mlme_cm_init(vdev_mlme))) {
+		mlme_err("CM SM create failed");
+		goto cm_sm_create_failed;
+	}
+
 	if (mlme_vdev_ops_ext_hdl_create(vdev_mlme) !=
 						QDF_STATUS_SUCCESS) {
 		mlme_err("Legacy vdev object creation failed");
@@ -127,6 +133,8 @@ ext_hdl_post_create_failed:
 	wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME,
 					      vdev_mlme);
 ext_hdl_create_failed:
+	mlme_cm_deinit(vdev_mlme);
+cm_sm_create_failed:
 	mlme_vdev_sm_destroy(vdev_mlme);
 init_failed:
 	wlan_minidump_remove(vdev_mlme);
@@ -150,6 +158,7 @@ static QDF_STATUS mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev,
 		return QDF_STATUS_SUCCESS;
 	}
 
+	mlme_cm_deinit(vdev_mlme);
 	mlme_vdev_sm_destroy(vdev_mlme);
 
 	mlme_vdev_ops_ext_hdl_destroy(vdev_mlme);