Bladeren bron

qcacmn: Handle connect response in connection manager

Handle connection response in connection manager.

Change-Id: I796b3c19c728323901f1a44e851616d3a0286763
CRs-Fixed: 2781566
gaurank kathpalia 4 jaren geleden
bovenliggende
commit
4de6d6b0d5

+ 303 - 31
umac/mlme/connection_mgr/core/src/wlan_cm_connect.c

@@ -26,6 +26,67 @@
 #include "wlan_policy_mgr_api.h"
 #endif
 #include <wlan_serialization_api.h>
+#ifdef CONN_MGR_ADV_FEATURE
+#include "wlan_blm_api.h"
+#endif
+
+/**
+ * cm_connect_handle_event_post_fail() - initiate connect failure if msg posting
+ * to SM fails
+ * @cm_ctx: connection manager context
+ * @cm_id: cm_id for connect req for which post fails
+ *
+ * Context: Can be called from any context and to be used only after posting a
+ * msg to SM fails from external event e.g. peer create resp,
+ * HW mode change resp  serialization cb.
+ *
+ * Return: QDF_STATUS
+ */
+static void
+cm_connect_handle_event_post_fail(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
+{
+	struct wlan_cm_connect_rsp *resp;
+
+	resp = qdf_mem_malloc(sizeof(*resp));
+	if (!resp)
+		return;
+
+	resp->connect_status = QDF_STATUS_E_FAILURE;
+	resp->cm_id = cm_id;
+	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
+	resp->reason = CM_ABORT_DUE_TO_NEW_REQ_RECVD;
+
+	cm_connect_complete(cm_ctx, resp);
+	qdf_mem_free(resp);
+}
+
+static QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx,
+					 wlan_cm_id cm_id)
+{
+	struct wlan_cm_connect_rsp *resp;
+	QDF_STATUS status;
+
+	resp = qdf_mem_malloc(sizeof(*resp));
+	if (!resp)
+		return QDF_STATUS_E_NOMEM;
+
+	resp->connect_status = QDF_STATUS_E_FAILURE;
+	resp->cm_id = cm_id;
+	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
+	resp->reason = CM_SER_TIMEOUT;
+	wlan_vdev_mlme_get_ssid(cm_ctx->vdev, resp->ssid.ssid,
+				&resp->ssid.length);
+
+	status = cm_sm_deliver_event(cm_ctx->vdev,
+				     WLAN_CM_SM_EV_CONNECT_FAILURE,
+				     sizeof(*resp), resp);
+	qdf_mem_free(resp);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		cm_connect_handle_event_post_fail(cm_ctx, cm_id);
+
+	return status;
+}
 
 static QDF_STATUS
 cm_ser_connect_cb(struct wlan_serialization_command *cmd,
@@ -33,6 +94,7 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd,
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	struct wlan_objmgr_vdev *vdev;
+	struct cnx_mgr *cm_ctx;
 
 	if (!cmd) {
 		mlme_err("cmd is NULL, reason: %d", reason);
@@ -46,6 +108,8 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd,
 	case WLAN_SER_CB_ACTIVATE_CMD:
 		status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_CONNECT_ACTIVE,
 					     sizeof(wlan_cm_id), &cmd->cmd_id);
+		if (QDF_IS_STATUS_SUCCESS(status))
+			break;
 		/*
 		 * Handle failure if posting fails, i.e. the SM state has
 		 * changed or head cm_id doesn't match the active cm_id.
@@ -53,6 +117,9 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd,
 		 * new command has been received connect activation should be
 		 * aborted from here with connect req cleanup.
 		 */
+		cm_ctx = cm_get_cm_ctx(vdev);
+		if (cm_ctx)
+			cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id);
 		break;
 	case WLAN_SER_CB_CANCEL_CMD:
 		/* command removed from pending list. */
@@ -60,6 +127,9 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd,
 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
 		mlme_err("Active command timeout cm_id %d", cmd->cmd_id);
 		QDF_ASSERT(0);
+		cm_ctx = cm_get_cm_ctx(vdev);
+		if (cm_ctx)
+			cm_connect_cmd_timeout(cm_ctx, cmd->cmd_id);
 		break;
 	case WLAN_SER_CB_RELEASE_MEM_CMD:
 		cm_reset_active_cm_id(vdev, cmd->cmd_id);
@@ -97,6 +167,7 @@ static QDF_STATUS cm_ser_connect_req(struct wlan_objmgr_pdev *pdev,
 	cmd.is_high_priority = false;
 	cmd.cmd_timeout_duration = CONNECT_TIMEOUT;
 	cmd.vdev = cm_ctx->vdev;
+	cmd.is_blocking = cm_ser_get_blocking_cmd();
 
 	ser_cmd_status = wlan_serialization_request(&cmd);
 	switch (ser_cmd_status) {
@@ -116,6 +187,17 @@ static QDF_STATUS cm_ser_connect_req(struct wlan_objmgr_pdev *pdev,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * cm_send_connect_start_fail() - initiate conenct failure
+ * @cm_ctx: connection manager context
+ * @req: connect req for which connect failed
+ * @reason: failure reason
+ *
+ * Context: Can be called from any context and to be used only after posting a
+ * msg to SM (ie holding the SM lock) to avoid use after free for req.
+ *
+ * Return: QDF_STATUS
+ */
 static QDF_STATUS
 cm_send_connect_start_fail(struct cnx_mgr *cm_ctx,
 			   struct cm_connect_req *req,
@@ -128,7 +210,17 @@ cm_send_connect_start_fail(struct cnx_mgr *cm_ctx,
 	if (!resp)
 		return QDF_STATUS_E_NOMEM;
 
-	/* fill resp from req */
+	resp->connect_status = QDF_STATUS_E_FAILURE;
+	resp->cm_id = req->cm_id;
+	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
+	resp->reason = reason;
+	resp->ssid.length = req->req.ssid.length;
+	qdf_mem_copy(resp->ssid.ssid, req->req.ssid.ssid, resp->ssid.length);
+	if (req->cur_candidate) {
+		qdf_copy_macaddr(&resp->bssid,
+				 &req->cur_candidate->entry->bssid);
+		resp->freq = req->cur_candidate->entry->channel.chan_freq;
+	}
 
 	status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE,
 					  sizeof(*resp), resp);
@@ -182,6 +274,7 @@ void cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
 	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS qdf_status;
 	enum wlan_cm_sm_evt event = WLAN_CM_SM_EV_HW_MODE_SUCCESS;
+	struct cnx_mgr *cm_ctx;
 
 	mlme_debug("vdev %d cm id %d Continue connect after HW mode change, status %d",
 		   vdev_id, cm_id, status);
@@ -191,11 +284,18 @@ void cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
 	if (!vdev)
 		return;
 
+	cm_ctx = cm_get_cm_ctx(vdev);
+	if (!cm_ctx) {
+		mlme_err("cm ctx NULL");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
+		return;
+	}
+
 	if (QDF_IS_STATUS_ERROR(status))
 		event = WLAN_CM_SM_EV_HW_MODE_FAILURE;
 	qdf_status = cm_sm_deliver_event(vdev, event, sizeof(wlan_cm_id),
 					 &cm_id);
-	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
+
 	/*
 	 * Handle failure if posting fails, i.e. the SM state has
 	 * changed or head cm_id doesn't match the active cm_id.
@@ -203,6 +303,9 @@ void cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
 	 * new command has been received connect should be
 	 * aborted from here with connect req cleanup.
 	 */
+	if (QDF_IS_STATUS_ERROR(status))
+		cm_connect_handle_event_post_fail(cm_ctx, cm_id);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
 }
 
 static QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc,
@@ -434,6 +537,24 @@ static QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
 				    WLAN_IF_MGR_EV_VALIDATE_CANDIDATE,
 				    &event_data);
 }
+
+static QDF_STATUS
+cm_inform_if_mgr_connect_complete(struct wlan_objmgr_vdev *vdev,
+				  QDF_STATUS connect_status)
+{
+	struct if_mgr_event_data *connect_complete;
+
+	connect_complete = qdf_mem_malloc(sizeof(*connect_complete));
+	if (!connect_complete)
+		return QDF_STATUS_E_NOMEM;
+
+	connect_complete->status = connect_status;
+	if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_COMPLETE,
+			     connect_complete);
+	qdf_mem_free(connect_complete);
+
+	return QDF_STATUS_SUCCESS;
+}
 #else
 static inline
 QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
@@ -441,6 +562,13 @@ QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline QDF_STATUS
+cm_inform_if_mgr_connect_complete(struct wlan_objmgr_vdev *vdev,
+				  QDF_STATUS connect_status)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 /**
@@ -512,6 +640,20 @@ static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx,
 	return QDF_STATUS_SUCCESS;
 }
 
+static void
+cm_fill_resp_for_bss_create_fail(struct wlan_objmgr_vdev *vdev,
+				 struct wlan_cm_connect_rsp *resp,
+				 wlan_cm_id cm_id,
+				 struct qdf_mac_addr *peer_mac)
+{
+	resp->connect_status = QDF_STATUS_E_FAILURE;
+	resp->cm_id = cm_id;
+	resp->vdev_id = wlan_vdev_get_id(vdev);
+	resp->reason = CM_PEER_CREATE_FAILED;
+	qdf_copy_macaddr(&resp->bssid, peer_mac);
+	wlan_vdev_mlme_get_ssid(vdev, resp->ssid.ssid, &resp->ssid.length);
+}
+
 static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
 			       struct cm_connect_req *req)
 {
@@ -525,17 +667,16 @@ static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
 
 		/* In case of failure try with next candidate */
 		mlme_err("peer create request failed %d", status);
+
 		resp = qdf_mem_malloc(sizeof(*resp));
 		if (!resp)
 			return;
 
-		resp->connect_status = status;
-		resp->cm_id = req->cm_id;
-		resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
-		resp->reason = CM_JOIN_FAILED;
+		cm_fill_resp_for_bss_create_fail(cm_ctx->vdev, resp, req->cm_id,
+						 bssid);
 		cm_sm_deliver_event_sync(cm_ctx,
-				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
-				    sizeof(*resp), resp);
+				WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
+				sizeof(*resp), resp);
 		qdf_mem_free(resp);
 	}
 }
@@ -549,7 +690,7 @@ QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
 	cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id);
 	if (!cm_req) {
 		mlme_err("cm req NULL connect fail");
-		goto connect_err;
+		return QDF_STATUS_E_FAILURE;
 	}
 
 	status = cm_get_valid_candidate(cm_ctx, cm_req);
@@ -563,22 +704,32 @@ QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
 	return QDF_STATUS_SUCCESS;
 
 connect_err:
-	return cm_send_connect_start_fail(cm_ctx, &cm_req->connect_req,
-					  CM_JOIN_FAILED);
+	return cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE,
+					sizeof(*resp), resp);
+
+}
+
+bool cm_connect_resp_cmid_match_list_head(struct cnx_mgr *cm_ctx,
+					  struct wlan_cm_connect_rsp *resp)
+{
+	return cm_check_cmid_match_list_head(cm_ctx, &resp->cm_id);
 }
 
 QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 {
 	struct cm_req *cm_req;
 	QDF_STATUS status;
+	struct wlan_cm_connect_req *req;
 
 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
 	if (!cm_req) {
-		mlme_err("cm req NULL connect fail");
+		mlme_err("cm req NULL for *cm_id %x", *cm_id);
 		return QDF_STATUS_E_INVAL;
 	}
 
 	cm_ctx->active_cm_id = *cm_id;
+	req = &cm_req->connect_req.req;
+	wlan_vdev_mlme_set_ssid(cm_ctx->vdev, req->ssid.ssid, req->ssid.length);
 
 	status = cm_get_valid_candidate(cm_ctx, cm_req);
 	if (QDF_IS_STATUS_ERROR(status))
@@ -596,31 +747,91 @@ connect_err:
 QDF_STATUS
 cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 {
+	struct wlan_cm_vdev_connect_req req;
+	struct cm_req *cm_req;
+	QDF_STATUS status;
+
+	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
+	if (!cm_req) {
+		mlme_err("cm req NULL for *cm_id %x", *cm_id);
+		return QDF_STATUS_E_FAILURE;
+	}
 	/*
 	 * fill vdev crypto for the peer.
-	 * call vdev sm to start connect for the candidate.
 	 */
 
-	return QDF_STATUS_SUCCESS;
+	req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
+	req.cm_id = *cm_id;
+	req.bss = cm_req->connect_req.cur_candidate;
+
+	status = mlme_cm_connect_req(cm_ctx->vdev, &req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mlme_err("connect request failed for *cm_id %x", *cm_id);
+		status = cm_send_connect_start_fail(cm_ctx,
+						    &cm_req->connect_req,
+						    CM_JOIN_FAILED);
+	}
+
+	return status;
 }
 
-QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
+#ifdef CONN_MGR_ADV_FEATURE
+static QDF_STATUS
+cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
+			       struct wlan_cm_connect_rsp *resp)
 {
-	/*
-	 * get the connect req from connect list and post
-	 * WLAN_CM_SM_EV_CONNECT_FAILURE.
-	 */
+	struct wlan_objmgr_pdev *pdev;
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		mlme_err("Failed to find pdev from vdev");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (QDF_IS_STATUS_SUCCESS(resp->connect_status))
+		wlan_blm_update_bssid_connect_params(pdev, resp->bssid,
+						     BLM_AP_CONNECTED);
+
 	return QDF_STATUS_SUCCESS;
 }
+#else
+static QDF_STATUS
+cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
+			       struct wlan_cm_connect_rsp *resp)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 
 QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx,
 			       struct wlan_cm_connect_rsp *resp)
 {
 	/*
-	 * inform osif about success/failure, inform interface manager
+	 * If the entry is not present in the list, it must have been cleared
+	 * already.
+	 */
+	if (!cm_get_req_by_cm_id(cm_ctx, resp->cm_id))
+		return QDF_STATUS_SUCCESS;
+
+	mlme_cm_osif_connect_complete(cm_ctx->vdev, resp);
+
+	if (cm_get_state(cm_ctx) == WLAN_CM_S_INIT ||
+	    cm_get_state(cm_ctx) == WLAN_CM_S_CONNECTED) {
+		cm_inform_if_mgr_connect_complete(cm_ctx->vdev,
+						  resp->connect_status);
+
+		cm_inform_blm_connect_complete(cm_ctx->vdev, resp);
+
+		mlme_cm_connect_complete_ind(cm_ctx->vdev, resp);
+	}
+
+	/*
 	 * update fils/wep key and inform legacy, update bcn filter and scan
-	 * entry mlme info, blm action and remove from serialization at the end.
+	 * entry mlme info,, start OBSS scan for open mode.
 	 */
+
+	cm_remove_cmd(cm_ctx, resp->cm_id);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -639,15 +850,73 @@ QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx,
 	return status;
 }
 
+QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
+			  struct wlan_cm_connect_rsp *resp)
+{
+	struct cnx_mgr *cm_ctx;
+	QDF_STATUS qdf_status;
+	wlan_cm_id cm_id;
+	uint32_t prefix;
+
+	cm_ctx = cm_get_cm_ctx(vdev);
+	if (!cm_ctx) {
+		mlme_err("cm ctx NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	cm_id = cm_ctx->active_cm_id;
+	prefix = CM_ID_GET_PREFIX(cm_id);
+
+	if (prefix != CONNECT_REQ_PREFIX || cm_id != resp->cm_id) {
+		mlme_err("Active req %x is not connect req connect req cm_id %x",
+			 cm_id, resp->cm_id);
+		qdf_status = QDF_STATUS_E_FAILURE;
+		goto post_err;
+	}
+
+	if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) {
+		qdf_status =
+			cm_sm_deliver_event(vdev,
+					    WLAN_CM_SM_EV_CONNECT_SUCCESS,
+					    sizeof(*resp), resp);
+		if (QDF_IS_STATUS_SUCCESS(qdf_status))
+			return qdf_status;
+		/*
+		 * failure mean that the new connect/disconnect is received so
+		 * cleanup.
+		 */
+		goto post_err;
+	}
+
+	/* In case of failure try with next candidate */
+	qdf_status =
+		cm_sm_deliver_event(vdev,
+				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
+				    sizeof(*resp), resp);
+
+	if (QDF_IS_STATUS_SUCCESS(qdf_status))
+		return qdf_status;
+
+post_err:
+	/*
+	 * If there is a event posting error it means the SM state is not in
+	 * JOIN ACTIVE (some new cmd has changed the state of SM), so just
+	 * complete the connect command.
+	 */
+	cm_connect_complete(cm_ctx, resp);
+
+	return qdf_status;
+}
+
 QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 				  QDF_STATUS status,
 				  struct qdf_mac_addr *peer_mac)
 {
 	struct cnx_mgr *cm_ctx;
 	QDF_STATUS qdf_status;
-	struct wlan_cm_connect_rsp *resp;
 	wlan_cm_id cm_id;
 	uint32_t prefix;
+	struct wlan_cm_connect_rsp *resp;
 
 	cm_ctx = cm_get_cm_ctx(vdev);
 	if (!cm_ctx) {
@@ -660,7 +929,7 @@ QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 
 	if (prefix != CONNECT_REQ_PREFIX) {
 		mlme_err("Active req %x is not connect req", cm_id);
-		/* Delete peer if create was success */
+		mlme_cm_bss_peer_delete_req(vdev);
 		return QDF_STATUS_E_INVAL;
 	}
 
@@ -671,19 +940,20 @@ QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 					    sizeof(wlan_cm_id), &cm_id);
 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
 			return qdf_status;
+
+		mlme_cm_bss_peer_delete_req(vdev);
 		goto post_err;
 	}
 
+	/* In case of failure try with next candidate */
 	resp = qdf_mem_malloc(sizeof(*resp));
-	if (!resp)
+	if (!resp) {
+		qdf_status = QDF_STATUS_E_NOMEM;
 		goto post_err;
+	}
 
-	resp->connect_status = status;
-	resp->cm_id = cm_id;
-	resp->vdev_id = wlan_vdev_get_id(vdev);
-	resp->reason = CM_JOIN_FAILED;
+	cm_fill_resp_for_bss_create_fail(cm_ctx->vdev, resp, cm_id, peer_mac);
 
-	/* In case of failure try with next candidate */
 	qdf_status =
 		cm_sm_deliver_event(vdev,
 				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
@@ -694,9 +964,11 @@ QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 
 post_err:
 	/*
-	 * handle post error i.e. STATE is not connect active, so
-	 * do cleanup of req.
+	 * If there is a event posting error it means the SM state is not in
+	 * JOIN ACTIVE (some new cmd has changed the state of SM), so just
+	 * complete the connect command.
 	 */
+	cm_connect_handle_event_post_fail(cm_ctx, cm_id);
 	return qdf_status;
 }
 

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

@@ -92,6 +92,7 @@ static QDF_STATUS cm_ser_disconnect_req(struct wlan_objmgr_pdev *pdev,
 	cmd.is_high_priority = false;
 	cmd.cmd_timeout_duration = DISCONNECT_TIMEOUT;
 	cmd.vdev = cm_ctx->vdev;
+	cmd.is_blocking = cm_ser_get_blocking_cmd();
 
 	ser_cmd_status = wlan_serialization_request(&cmd);
 	switch (ser_cmd_status) {

+ 48 - 9
umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h

@@ -70,6 +70,17 @@ QDF_STATUS cm_connect_scan_start(struct cnx_mgr *cm_ctx,
 QDF_STATUS cm_connect_scan_resp(struct cnx_mgr *cm_ctx, wlan_scan_id *scan_id,
 				QDF_STATUS status);
 
+/**
+ * cm_connect_resp_cmid_match_list_head() - Check if resp cmid is same as list
+ * head
+ * @cm_ctx: connection manager context
+ * @resp: connect resp
+ *
+ * Return: bool
+ */
+bool cm_connect_resp_cmid_match_list_head(struct cnx_mgr *cm_ctx,
+					  struct wlan_cm_connect_rsp *resp);
+
 /**
  * cm_connect_active() - This API would be called after the connect
  * request gets activated in serialization.
@@ -92,15 +103,6 @@ QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id);
 QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
 				 struct wlan_cm_connect_rsp *connect_resp);
 
-/**
- * cm_connect_cmd_timeout() - Called if active connect command timeout
- * @cm_ctx: connection manager context
- * @cm_id: Connection mgr ID assigned to this connect request.
- *
- * Return: QDF status
- */
-QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id);
-
 /**
  * cm_resume_connect_after_peer_create() - Called after bss create rsp
  * @cm_ctx: connection manager context
@@ -123,6 +125,16 @@ QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 				  QDF_STATUS status,
 				  struct qdf_mac_addr *peer_mac);
 
+/**
+ * cm_connect_rsp() - Connection manager connect response
+ * @vdev: vdev pointer
+ * @resp: Connect response
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
+			  struct wlan_cm_connect_rsp *resp);
+
 /**
  * cm_connect_complete() - This API would be called after connect complete
  * request from the serialization.
@@ -246,6 +258,24 @@ QDF_STATUS cm_disconnect_start_req(struct wlan_objmgr_vdev *vdev,
 
 /*************** UTIL APIs ****************/
 
+/**
+ * cm_ser_get_blocking_cmd() - check if serialization command needs to be
+ * blocking
+ *
+ * Return: bool
+ */
+#ifdef CONN_MGR_ADV_FEATURE
+static inline bool cm_ser_get_blocking_cmd(void)
+{
+	return true;
+}
+#else
+static inline bool cm_ser_get_blocking_cmd(void)
+{
+	return false;
+}
+#endif
+
 /**
  * cm_get_cm_id() - Get unique cm id for connect/disconnect request
  * @cm_ctx: connection manager context
@@ -313,6 +343,15 @@ bool cm_check_scanid_match_list_head(struct cnx_mgr *cm_ctx,
  */
 QDF_STATUS cm_delete_req_from_list(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id);
 
+/**
+ * cm_remove_cmd() - Remove cmd from req list and serialization
+ * @cm_ctx: connection manager context
+ * @cm_id: cm id of connect/disconnect req
+ *
+ * Return: void
+ */
+void cm_remove_cmd(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id);
+
 /**
  * cm_add_req_to_list_and_indicate_osif() - Add the request to request list in
  * cm ctx and indicate same to osif

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

@@ -402,6 +402,11 @@ static bool cm_subst_join_pending_event(void *ctx, uint16_t event,
 		status = true;
 		break;
 	case WLAN_CM_SM_EV_CONNECT_FAILURE:
+		/* check if connect resp cm id is valid for the current req */
+		if (!cm_connect_resp_cmid_match_list_head(cm_ctx, data)) {
+			status = false;
+			break;
+		}
 		cm_sm_transition_to(cm_ctx, WLAN_CM_S_INIT);
 		cm_sm_deliver_event_sync(cm_ctx, event, data_len, data);
 		status = true;
@@ -538,20 +543,40 @@ static bool cm_subst_join_active_event(void *ctx, uint16_t event,
 		status = true;
 		break;
 	case WLAN_CM_SM_EV_CONNECT_SUCCESS:
+		/* check if connect resp cm id is valid for the current req */
+		if (!cm_connect_resp_cmid_match_list_head(cm_ctx, data)) {
+			status = false;
+			break;
+		}
 		cm_sm_transition_to(cm_ctx, WLAN_CM_S_CONNECTED);
 		cm_sm_deliver_event_sync(cm_ctx, event, data_len, data);
 		status = true;
 		break;
 	case WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE:
+		/* check if connect resp cm id is valid for the current req */
+		if (!cm_connect_resp_cmid_match_list_head(cm_ctx, data)) {
+			status = false;
+			break;
+		}
 		cm_try_next_candidate(cm_ctx, data);
 		status = true;
 		break;
 	case WLAN_CM_SM_EV_CONNECT_FAILURE:
+		/* check if connect resp cm id is valid for the current req */
+		if (!cm_connect_resp_cmid_match_list_head(cm_ctx, data)) {
+			status = false;
+			break;
+		}
 		cm_sm_transition_to(cm_ctx, WLAN_CM_S_INIT);
 		cm_sm_deliver_event_sync(cm_ctx, event, data_len, data);
 		status = true;
 		break;
 	case WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS:
+		/* check if cm id is valid for the current req */
+		if (!cm_check_cmid_match_list_head(cm_ctx, data)) {
+			status = false;
+			break;
+		}
 		cm_resume_connect_after_peer_create(cm_ctx, data);
 		status = true;
 		break;

+ 38 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_util.c

@@ -21,6 +21,7 @@
 #include "wlan_cm_main_api.h"
 #include "wlan_scan_api.h"
 #include "wlan_cm_public_struct.h"
+#include "wlan_serialization_api.h"
 
 static uint32_t cm_get_prefix_for_cm_id(enum wlan_cm_source source) {
 	switch (source) {
@@ -262,3 +263,40 @@ cm_delete_req_from_list(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
 
 	return QDF_STATUS_SUCCESS;
 }
+
+void cm_remove_cmd(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_serialization_queued_cmd_info cmd_info;
+	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
+	QDF_STATUS status;
+
+	psoc = wlan_vdev_get_psoc(cm_ctx->vdev);
+	if (!psoc) {
+		mlme_err("Failed to find psoc from vdev");
+		return;
+	}
+
+	status = cm_delete_req_from_list(cm_ctx, cm_id);
+	if (QDF_IS_STATUS_ERROR(status))
+		return;
+
+	qdf_mem_zero(&cmd_info, sizeof(cmd_info));
+	cmd_info.cmd_id = cm_id;
+	cmd_info.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD;
+
+	if (prefix == CONNECT_REQ_PREFIX)
+		cmd_info.cmd_type = WLAN_SER_CMD_VDEV_CONNECT;
+	else
+		cmd_info.cmd_type = WLAN_SER_CMD_VDEV_DISCONNECT;
+
+	cmd_info.vdev = cm_ctx->vdev;
+
+	if (cm_id == cm_ctx->active_cm_id) {
+		cmd_info.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
+		wlan_serialization_remove_cmd(&cmd_info);
+	} else {
+		cmd_info.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
+		wlan_serialization_cancel_request(&cmd_info);
+	}
+}

+ 2 - 2
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h

@@ -61,12 +61,12 @@ QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 /**
  * wlan_cm_connect_rsp() - Connection manager connect response
  * @vdev: vdev pointer
- * @cm_conn_rsp: Connect response
+ * @resp: Connect response
  *
  * Return: QDF_STATUS
  */
 QDF_STATUS wlan_cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
-			       struct wlan_cm_connect_rsp *cm_conn_rsp);
+			       struct wlan_cm_connect_rsp *resp);
 
 /**
  * wlan_cm_bss_peer_delete_ind() - Connection manager peer delete indication

+ 13 - 6
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h

@@ -206,6 +206,9 @@ struct wlan_cm_vdev_discon_req {
 /*
  * enum wlan_cm_connect_fail_reason: connection manager connect fail reason
  * @CM_NO_CANDIDATE_FOUND: No candidate found
+ * @CM_ABORT_DUE_TO_NEW_REQ_RECVD: Aborted as new command is received and
+ * State machine is not able to handle as state has changed due to new command.
+ * @CM_PEER_CREATE_FAILED: peer create failed
  * @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
@@ -216,10 +219,13 @@ struct wlan_cm_vdev_discon_req {
  * @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_SER_TIMEOUT: Serialization cmd timeout
  * @CM_GENERIC_FAILURE: Generic failure apart from above
  */
 enum wlan_cm_connect_fail_reason {
 	CM_NO_CANDIDATE_FOUND,
+	CM_ABORT_DUE_TO_NEW_REQ_RECVD,
+	CM_PEER_CREATE_FAILED,
 	CM_JOIN_FAILED,
 	CM_JOIN_TIMEOUT,
 	CM_AUTH_FAILED,
@@ -228,6 +234,7 @@ enum wlan_cm_connect_fail_reason {
 	CM_ASSOC_TIMEOUT,
 	CM_HW_MODE_FAILURE,
 	CM_SER_FAILURE,
+	CM_SER_TIMEOUT,
 	CM_GENERIC_FAILURE,
 };
 
@@ -295,19 +302,22 @@ struct wlan_connect_rsp_ies {
  * OSIF
  * @vdev_id: vdev id
  * @cm_id: Connect manager id
+ * @bssid: BSSID of the ap
+ * @ssid: SSID of the connection
+ * @freq: Channel frequency
  * @connect_status: connect status success or failure
  * @reason: connect fail reason, valid only in case of failure
  * @reason_code: protocol reason code of the connect failure
  * @aid: aid
  * @connect_ies: connect related IE required by osif to send to kernel
  * @is_fils_connection: is fils connection
- * @bssid: BSSID of the ap
- * @ssid: SSID of the connection
- * @freq: Channel frequency
  */
 struct wlan_cm_connect_rsp {
 	uint8_t vdev_id;
 	wlan_cm_id cm_id;
+	struct qdf_mac_addr bssid;
+	struct wlan_ssid ssid;
+	qdf_freq_t freq;
 	QDF_STATUS connect_status;
 	enum wlan_cm_connect_fail_reason reason;
 	uint8_t reason_code;
@@ -316,9 +326,6 @@ struct wlan_cm_connect_rsp {
 #ifdef WLAN_FEATURE_FILS_SK
 	bool is_fils_connection;
 #endif
-	struct qdf_mac_addr bssid;
-	struct wlan_ssid ssid;
-	qdf_freq_t freq;
 };
 
 

+ 2 - 2
umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c

@@ -43,9 +43,9 @@ QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 }
 
 QDF_STATUS wlan_cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
-			       struct wlan_cm_connect_rsp *cm_conn_rsp)
+			       struct wlan_cm_connect_rsp *resp)
 {
-	return QDF_STATUS_SUCCESS;
+	return cm_connect_rsp(vdev, resp);
 }
 
 QDF_STATUS wlan_cm_bss_peer_delete_ind(struct wlan_objmgr_vdev *vdev,