Selaa lähdekoodia

qcacmn: Add connection logic after serialization part 2

Add event handling for mlme indication for connect start for
peer and its response. Add the interface manager missing
events. Add sync and async event handling for serialization
callback

Change-Id: I5cbb9a6ac1350f8035224135fb159010311a8468
CRs-Fixed: 2784163
gaurank kathpalia 4 vuotta sitten
vanhempi
sitoutus
fdfaaf5260

+ 265 - 94
umac/mlme/connection_mgr/core/src/wlan_cm_connect.c

@@ -31,6 +31,20 @@
 #include "wlan_blm_api.h"
 #endif
 
+static void
+cm_fill_failure_resp_from_cm_id(struct cnx_mgr *cm_ctx,
+				struct wlan_cm_connect_rsp *resp,
+				wlan_cm_id cm_id,
+				enum wlan_cm_connect_fail_reason reason)
+{
+	resp->connect_status = QDF_STATUS_E_FAILURE;
+	resp->cm_id = cm_id;
+	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
+	resp->reason = reason;
+	/* Get bssid and ssid and freq for the cm id from the req list */
+	cm_fill_bss_info_in_connect_rsp_by_cm_id(cm_ctx, cm_id, resp);
+}
+
 /**
  * cm_connect_handle_event_post_fail() - initiate connect failure if msg posting
  * to SM fails
@@ -52,11 +66,8 @@ cm_connect_handle_event_post_fail(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
 	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_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
+					CM_ABORT_DUE_TO_NEW_REQ_RECVD);
 	cm_connect_complete(cm_ctx, resp);
 	qdf_mem_free(resp);
 }
@@ -71,13 +82,7 @@ static QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx,
 	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);
-
+	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, CM_SER_TIMEOUT);
 	status = cm_sm_deliver_event(cm_ctx->vdev,
 				     WLAN_CM_SM_EV_CONNECT_FAILURE,
 				     sizeof(*resp), resp);
@@ -105,10 +110,29 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd,
 
 	vdev = cmd->vdev;
 
+	cm_ctx = cm_get_cm_ctx(vdev);
+	if (!cm_ctx) {
+		mlme_err("cm_ctx is NULL, reason: %d", reason);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
 	switch (reason) {
 	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);
+		/*
+		 * For pending to active reason, use async api to take lock.
+		 * For direct activation use sync api to avoid taking lock
+		 * as lock is already acquired by the requester.
+		 */
+		if (cmd->activation_reason == SER_PENDING_TO_ACTIVE)
+			status = cm_sm_deliver_event(vdev,
+						   WLAN_CM_SM_EV_CONNECT_ACTIVE,
+						   sizeof(wlan_cm_id),
+						   &cmd->cmd_id);
+		else
+			status = cm_sm_deliver_event_sync(cm_ctx,
+						   WLAN_CM_SM_EV_CONNECT_ACTIVE,
+						   sizeof(wlan_cm_id),
+						   &cmd->cmd_id);
 		if (QDF_IS_STATUS_SUCCESS(status))
 			break;
 		/*
@@ -118,9 +142,7 @@ 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);
+		cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id);
 		break;
 	case WLAN_SER_CB_CANCEL_CMD:
 		/* command removed from pending list. */
@@ -128,9 +150,8 @@ 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);
+
+		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);
@@ -471,6 +492,68 @@ static QDF_STATUS cm_connect_get_candidates(struct wlan_objmgr_pdev *pdev,
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_INTERFACE_MGR
+static QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
+					struct scan_cache_entry *scan_entry)
+{
+	struct if_mgr_event_data event_data = {0};
+
+	event_data.validate_bss_info.chan_freq = scan_entry->channel.chan_freq;
+	qdf_copy_macaddr(&event_data.validate_bss_info.peer_addr,
+			 &scan_entry->bssid);
+
+	return if_mgr_deliver_event(cm_ctx->vdev,
+				    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;
+}
+
+static QDF_STATUS
+cm_inform_if_mgr_connect_start(struct wlan_objmgr_vdev *vdev)
+{
+	return if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_START, NULL);
+}
+
+#else
+static inline
+QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
+				 struct scan_cache_entry *scan_entry)
+{
+	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;
+}
+
+static QDF_STATUS
+cm_inform_if_mgr_connect_start(struct wlan_objmgr_vdev *vdev)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+#endif
+
 QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx,
 			    struct cm_connect_req *cm_req)
 {
@@ -493,6 +576,9 @@ QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx,
 		goto connect_err;
 	}
 
+	cm_inform_if_mgr_connect_start(cm_ctx->vdev);
+	mlme_cm_connect_start_ind(cm_ctx->vdev, &cm_req->req);
+
 	status = cm_connect_get_candidates(pdev, cm_ctx, cm_req);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		reason = CM_NO_CANDIDATE_FOUND;
@@ -523,54 +609,6 @@ connect_err:
 	return cm_send_connect_start_fail(cm_ctx, cm_req, reason);
 }
 
-#ifdef WLAN_FEATURE_INTERFACE_MGR
-static QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
-					struct scan_cache_entry *scan_entry)
-{
-	struct if_mgr_event_data event_data = {0};
-
-	event_data.validate_bss_info.chan_freq = scan_entry->channel.chan_freq;
-	qdf_copy_macaddr(&event_data.validate_bss_info.peer_addr,
-			 &scan_entry->bssid);
-
-	return if_mgr_deliver_event(cm_ctx->vdev,
-				    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,
-				 struct scan_cache_entry *scan_entry)
-{
-	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
-
 /**
  * cm_get_valid_candidate() - This API will be called to get the next valid
  * candidate
@@ -640,20 +678,6 @@ 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)
 {
@@ -672,8 +696,8 @@ static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
 		if (!resp)
 			return;
 
-		cm_fill_resp_for_bss_create_fail(cm_ctx->vdev, resp, req->cm_id,
-						 bssid);
+		cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id,
+						CM_PEER_CREATE_FAILED);
 		cm_sm_deliver_event_sync(cm_ctx,
 				WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
 				sizeof(*resp), resp);
@@ -681,6 +705,39 @@ static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
 	}
 }
 
+static QDF_STATUS
+cm_send_candidate_select_indication(struct cnx_mgr *cm_ctx,
+				    struct cm_connect_req *req)
+{
+	QDF_STATUS status;
+	struct wlan_cm_vdev_connect_req vdev_req;
+	struct wlan_cm_connect_rsp *resp;
+
+	vdev_req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
+	vdev_req.cm_id = req->cm_id;
+	vdev_req.bss = req->cur_candidate;
+
+	status = mlme_cm_candidate_select_ind(cm_ctx->vdev, &vdev_req);
+	if (QDF_IS_STATUS_SUCCESS(status) ||
+	    status == QDF_STATUS_E_NOSUPPORT)
+		return status;
+
+	/* In supported and failure try with next candidate */
+	mlme_err("mlme candidate select indication failed %d", status);
+	resp = qdf_mem_malloc(sizeof(*resp));
+	if (!resp)
+		return QDF_STATUS_E_FAILURE;
+
+	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id,
+					CM_CANDIDATE_SELECT_IND_FAILED);
+	cm_sm_deliver_event_sync(cm_ctx,
+				 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
+				 sizeof(*resp), resp);
+	qdf_mem_free(resp);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
 				 struct wlan_cm_connect_rsp *resp)
 {
@@ -699,7 +756,16 @@ QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
 
 	mlme_cm_osif_failed_candidate_ind(cm_ctx->vdev, resp);
 
-	cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
+	status = cm_send_candidate_select_indication(cm_ctx,
+						     &cm_req->connect_req);
+	/*
+	 * If candidate select indication is not supported continue with bss
+	 * peer create, else peer will be created after resp.
+	 */
+	if (status == QDF_STATUS_E_NOSUPPORT)
+		cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
+	else if (QDF_IS_STATUS_ERROR(status))
+		goto connect_err;
 
 	return QDF_STATUS_SUCCESS;
 
@@ -735,7 +801,16 @@ QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 	if (QDF_IS_STATUS_ERROR(status))
 		goto connect_err;
 
-	cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
+	status = cm_send_candidate_select_indication(cm_ctx,
+						     &cm_req->connect_req);
+	/*
+	 * If candidate select indication is not supported continue with bss
+	 * peer create, else peer will be created after resp.
+	 */
+	if (status == QDF_STATUS_E_NOSUPPORT)
+		cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
+	else if (QDF_IS_STATUS_ERROR(status))
+		goto connect_err;
 
 	return QDF_STATUS_SUCCESS;
 
@@ -744,6 +819,23 @@ connect_err:
 					  &cm_req->connect_req, CM_JOIN_FAILED);
 }
 
+QDF_STATUS
+cm_peer_create_on_candidate_select_ind_resp(struct cnx_mgr *cm_ctx,
+					    wlan_cm_id *cm_id)
+{
+	struct cm_req *cm_req;
+
+	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;
+	}
+
+	cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS
 cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 {
@@ -806,6 +898,10 @@ cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx,
 			       struct wlan_cm_connect_rsp *resp)
 {
+	enum wlan_cm_sm_state sm_state;
+	struct bss_info bss_info;
+	struct mlme_info mlme_info;
+
 	/*
 	 * If the entry is not present in the list, it must have been cleared
 	 * already.
@@ -813,16 +909,30 @@ QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx,
 	if (!cm_get_req_by_cm_id(cm_ctx, resp->cm_id))
 		return QDF_STATUS_SUCCESS;
 
+	sm_state = cm_get_state(cm_ctx);
 	mlme_cm_osif_connect_complete(cm_ctx->vdev, resp);
+	mlme_cm_connect_complete_ind(cm_ctx->vdev, resp);
 
-	if (cm_get_state(cm_ctx) == WLAN_CM_S_INIT ||
-	    cm_get_state(cm_ctx) == WLAN_CM_S_CONNECTED) {
+	if (sm_state == WLAN_CM_S_INIT || sm_state == 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 scan entry in case connect is success or fails with bssid */
+	if (!qdf_is_macaddr_zero(&resp->bssid)) {
+		if (QDF_IS_STATUS_SUCCESS(resp->connect_status))
+			mlme_info.assoc_state  = SCAN_ENTRY_CON_STATE_ASSOC;
+		else
+			mlme_info.assoc_state = SCAN_ENTRY_CON_STATE_NONE;
+		qdf_copy_macaddr(&bss_info.bssid, &resp->bssid);
+		bss_info.freq = resp->freq;
+		bss_info.ssid.length = resp->ssid.length;
+		qdf_mem_copy(&bss_info.ssid.ssid, resp->ssid.ssid,
+			     bss_info.ssid.length);
+		wlan_scan_update_mlme_by_bssinfo(
+					wlan_vdev_get_pdev(cm_ctx->vdev),
+					&bss_info, &mlme_info);
 	}
 
 	/*
@@ -908,6 +1018,67 @@ post_err:
 	return qdf_status;
 }
 
+QDF_STATUS cm_candidate_select_ind_rsp(struct wlan_objmgr_vdev *vdev,
+				       QDF_STATUS status)
+{
+	struct cnx_mgr *cm_ctx;
+	QDF_STATUS qdf_status;
+	wlan_cm_id cm_id;
+	uint32_t prefix;
+	struct wlan_cm_connect_rsp *resp;
+
+	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) {
+		mlme_err("Active req %x is not connect req", cm_id);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		qdf_status =
+			cm_sm_deliver_event(vdev,
+				WLAN_CM_SM_EV_CANDIDATE_SELECT_IND_SUCCESS,
+				sizeof(wlan_cm_id), &cm_id);
+		if (QDF_IS_STATUS_SUCCESS(qdf_status))
+			return qdf_status;
+
+		goto post_err;
+	}
+
+	/* In case of failure try with next candidate */
+	resp = qdf_mem_malloc(sizeof(*resp));
+	if (!resp) {
+		qdf_status = QDF_STATUS_E_NOMEM;
+		goto post_err;
+	}
+
+	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
+					CM_CANDIDATE_SELECT_IND_FAILED);
+	qdf_status =
+		cm_sm_deliver_event(vdev,
+				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
+				    sizeof(*resp), resp);
+	qdf_mem_free(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_handle_event_post_fail(cm_ctx, cm_id);
+	return qdf_status;
+}
+
 QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 				  QDF_STATUS status,
 				  struct qdf_mac_addr *peer_mac)
@@ -936,8 +1107,8 @@ QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 	if (QDF_IS_STATUS_SUCCESS(status)) {
 		qdf_status =
 			cm_sm_deliver_event(vdev,
-					    WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS,
-					    sizeof(wlan_cm_id), &cm_id);
+					  WLAN_CM_SM_EV_BSS_CREATE_PEER_SUCCESS,
+					  sizeof(wlan_cm_id), &cm_id);
 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
 			return qdf_status;
 
@@ -952,8 +1123,8 @@ QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 		goto post_err;
 	}
 
-	cm_fill_resp_for_bss_create_fail(cm_ctx->vdev, resp, cm_id, peer_mac);
-
+	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
+					CM_PEER_CREATE_FAILED);
 	qdf_status =
 		cm_sm_deliver_event(vdev,
 				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,

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

@@ -103,6 +103,18 @@ 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_peer_create_on_candidate_select_ind_resp() - Called to create peer
+ * if peer select inidication's resp was success
+ * @cm_ctx: connection manager context
+ * @cm_id: Connection mgr ID assigned to this connect request.
+ *
+ * Return: QDF status
+ */
+QDF_STATUS
+cm_peer_create_on_candidate_select_ind_resp(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
@@ -113,6 +125,17 @@ QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
 QDF_STATUS
 cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id);
 
+/**
+ * cm_candidate_select_ind_rsp() - Connection manager resp for candidate
+ * select indication
+ * @vdev: vdev pointer
+ * @status: Status
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS cm_candidate_select_ind_rsp(struct wlan_objmgr_vdev *vdev,
+				       QDF_STATUS status);
+
 /**
  * cm_bss_peer_create_rsp() - handle bss peer create response
  * @vdev: vdev
@@ -352,6 +375,24 @@ void cm_free_connect_req_mem(struct cm_connect_req *connect_req);
  */
 QDF_STATUS cm_delete_req_from_list(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id);
 
+/**
+ * cm_fill_bss_info_in_connect_rsp_by_cm_id() - fill bss info for the cm id
+ * @cm_ctx: connection manager context
+ * @cm_id: cm id of connect/disconnect req
+ * @resp: resp to copy bss info like ssid/bssid and freq
+ *
+ * Fill the SSID form the connect req.
+ * Fill freq and bssid from current candidate if available (i.e the connection
+ * has tried to connect to a candidate), else get the bssid from req bssid or
+ * bssid hint which ever is present.
+ *
+ * Return: Success if entry was found else failure
+ */
+QDF_STATUS
+cm_fill_bss_info_in_connect_rsp_by_cm_id(struct cnx_mgr *cm_ctx,
+					 wlan_cm_id cm_id,
+					 struct wlan_cm_connect_rsp *resp);
+
 /**
  * cm_remove_cmd() - Remove cmd from req list and serialization
  * @cm_ctx: connection manager context

+ 11 - 1
umac/mlme/connection_mgr/core/src/wlan_cm_sm.c

@@ -571,7 +571,16 @@ static bool cm_subst_join_active_event(void *ctx, uint16_t event,
 		cm_sm_deliver_event_sync(cm_ctx, event, data_len, data);
 		status = true;
 		break;
-	case WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS:
+	case WLAN_CM_SM_EV_CANDIDATE_SELECT_IND_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_peer_create_on_candidate_select_ind_resp(cm_ctx, data);
+		status = true;
+		break;
+	case WLAN_CM_SM_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;
@@ -751,6 +760,7 @@ static const char *cm_sm_event_names[] = {
 	"EV_CONNECT_START",
 	"EV_CONNECT_ACTIVE",
 	"EV_CONNECT_SUCCESS",
+	"EV_MLME_CANDIDATE_SELECT_IND_SUCCESS",
 	"EV_BSS_CREATE_PEER_SUCCESS"
 	"EV_CONNECT_GET_NXT_CANDIDATE",
 	"EV_CONNECT_FAILURE",

+ 22 - 19
umac/mlme/connection_mgr/core/src/wlan_cm_sm.h

@@ -37,7 +37,9 @@
  * @WLAN_CM_SM_EV_CONNECT_START:          Connect start process initiate
  * @WLAN_CM_SM_EV_CONNECT_ACTIVE:         Connect request is activated
  * @WLAN_CM_SM_EV_CONNECT_SUCCESS:        Connect success
- * @WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS:   BSS peer create success
+ * @WLAN_CM_SM_EV_CANDIDATE_SELECT_IND_SUCCESS: Mlme resp for mlme active cmd
+ * req
+ * @WLAN_CM_SM_EV_BSS_CREATE_PEER_SUCCESS: BSS peer create success
  * @WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE: Get next candidate for connection
  * @WLAN_CM_SM_EV_CONNECT_FAILURE:        Connect failed for all candidate
  * @WLAN_CM_SM_EV_DISCONNECT_REQ:         Disconnect request event from
@@ -68,24 +70,25 @@ enum wlan_cm_sm_evt {
 	WLAN_CM_SM_EV_CONNECT_START = 6,
 	WLAN_CM_SM_EV_CONNECT_ACTIVE = 7,
 	WLAN_CM_SM_EV_CONNECT_SUCCESS = 8,
-	WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS = 9,
-	WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE = 10,
-	WLAN_CM_SM_EV_CONNECT_FAILURE = 11,
-	WLAN_CM_SM_EV_DISCONNECT_REQ = 12,
-	WLAN_CM_SM_EV_DISCONNECT_START = 13,
-	WLAN_CM_SM_EV_DISCONNECT_ACTIVE = 14,
-	WLAN_CM_SM_EV_DISCONNECT_DONE = 15,
-	WLAN_CM_SM_EV_ROAM_START = 16,
-	WLAN_CM_SM_EV_ROAM_SYNC = 17,
-	WLAN_CM_SM_EV_ROAM_INVOKE_FAIL = 18,
-	WLAN_CM_SM_EV_ROAM_HO_FAIL = 19,
-	WLAN_CM_SM_EV_PREAUTH_DONE = 20,
-	WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP = 21,
-	WLAN_CM_SM_EV_PREAUTH_FAIL = 22,
-	WLAN_CM_SM_EV_START_REASSOC = 23,
-	WLAN_CM_SM_EV_REASSOC_DONE = 24,
-	WLAN_CM_SM_EV_REASSOC_FAILURE = 25,
-	WLAN_CM_SM_EV_ROAM_COMPLETE = 26,
+	WLAN_CM_SM_EV_CANDIDATE_SELECT_IND_SUCCESS = 9,
+	WLAN_CM_SM_EV_BSS_CREATE_PEER_SUCCESS = 10,
+	WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE = 11,
+	WLAN_CM_SM_EV_CONNECT_FAILURE = 12,
+	WLAN_CM_SM_EV_DISCONNECT_REQ = 13,
+	WLAN_CM_SM_EV_DISCONNECT_START = 14,
+	WLAN_CM_SM_EV_DISCONNECT_ACTIVE = 15,
+	WLAN_CM_SM_EV_DISCONNECT_DONE = 16,
+	WLAN_CM_SM_EV_ROAM_START = 17,
+	WLAN_CM_SM_EV_ROAM_SYNC = 18,
+	WLAN_CM_SM_EV_ROAM_INVOKE_FAIL = 19,
+	WLAN_CM_SM_EV_ROAM_HO_FAIL = 20,
+	WLAN_CM_SM_EV_PREAUTH_DONE = 21,
+	WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP = 22,
+	WLAN_CM_SM_EV_PREAUTH_FAIL = 23,
+	WLAN_CM_SM_EV_START_REASSOC = 24,
+	WLAN_CM_SM_EV_REASSOC_DONE = 25,
+	WLAN_CM_SM_EV_REASSOC_FAILURE = 26,
+	WLAN_CM_SM_EV_ROAM_COMPLETE = 27,
 	WLAN_CM_SM_EV_MAX,
 };
 

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

@@ -198,6 +198,57 @@ struct cm_req *cm_get_req_by_cm_id(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
 	return NULL;
 }
 
+QDF_STATUS
+cm_fill_bss_info_in_connect_rsp_by_cm_id(struct cnx_mgr *cm_ctx,
+					 wlan_cm_id cm_id,
+					 struct wlan_cm_connect_rsp *resp)
+{
+	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
+	struct cm_req *cm_req;
+	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
+	struct scan_cache_node *candidate;
+	struct wlan_cm_connect_req *req;
+
+	if (prefix != CONNECT_REQ_PREFIX)
+		return QDF_STATUS_E_INVAL;
+
+	cm_req_lock_acquire(cm_ctx);
+	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
+	while (cur_node) {
+		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
+		cm_req = qdf_container_of(cur_node, struct cm_req, node);
+
+		if (cm_req->cm_id == cm_id) {
+			req = &cm_req->connect_req.req;
+			candidate = cm_req->connect_req.cur_candidate;
+			if (candidate)
+				qdf_copy_macaddr(&resp->bssid,
+						 &candidate->entry->bssid);
+			else if (!qdf_is_macaddr_zero(&req->bssid))
+				qdf_copy_macaddr(&resp->bssid,
+						 &req->bssid);
+			else
+				qdf_copy_macaddr(&resp->bssid,
+						 &req->bssid_hint);
+			if (candidate)
+				resp->freq =
+					candidate->entry->channel.chan_freq;
+			else
+				resp->freq = req->chan_freq;
+			qdf_mem_copy(&resp->ssid, &req->ssid,
+				     sizeof(resp->bssid));
+			cm_req_lock_release(cm_ctx);
+			return QDF_STATUS_SUCCESS;
+		}
+
+		cur_node = next_node;
+		next_node = NULL;
+	}
+	cm_req_lock_release(cm_ctx);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
 QDF_STATUS cm_add_req_to_list_and_indicate_osif(struct cnx_mgr *cm_ctx,
 						struct cm_req *cm_req,
 						enum wlan_cm_source source)

+ 11 - 0
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h

@@ -46,6 +46,17 @@ QDF_STATUS wlan_cm_start_connect(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS wlan_cm_start_disconnect(struct wlan_objmgr_vdev *vdev,
 				    struct wlan_cm_disconnect_req *req);
 
+/**
+ * wlan_cm_candidate_select_ind_rsp() - Connection manager resp for candidate
+ * select indication
+ * @vdev: vdev pointer
+ * @status: Status
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_candidate_select_ind_rsp(struct wlan_objmgr_vdev *vdev,
+					    QDF_STATUS status);
+
 /**
  * wlan_cm_bss_peer_create_rsp() - Connection manager bss peer create response
  * @vdev: vdev pointer

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

@@ -207,6 +207,7 @@ 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
+ * @CM_CANDIDATE_SELECT_IND_FAILED: Failed candidate select indication
  * 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
@@ -225,6 +226,7 @@ struct wlan_cm_vdev_discon_req {
 enum wlan_cm_connect_fail_reason {
 	CM_NO_CANDIDATE_FOUND,
 	CM_ABORT_DUE_TO_NEW_REQ_RECVD,
+	CM_CANDIDATE_SELECT_IND_FAILED,
 	CM_PEER_CREATE_FAILED,
 	CM_JOIN_FAILED,
 	CM_JOIN_TIMEOUT,

+ 6 - 0
umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c

@@ -35,6 +35,12 @@ QDF_STATUS wlan_cm_start_disconnect(struct wlan_objmgr_vdev *vdev,
 	return cm_disconnect_start_req(vdev, req);
 }
 
+QDF_STATUS wlan_cm_candidate_select_ind_rsp(struct wlan_objmgr_vdev *vdev,
+					    QDF_STATUS status)
+{
+	return cm_candidate_select_ind_rsp(vdev, status);
+}
+
 QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 				       QDF_STATUS status,
 				       struct qdf_mac_addr *peer_mac)

+ 7 - 6
umac/mlme/include/wlan_mlme_cmn.h

@@ -99,7 +99,8 @@ struct mlme_cm_ops {
  * @mlme_multi_vdev_restart_resp:           callback to process multivdev
  *                                          restart response
  * @mlme_cm_ext_connect_start_ind_cb:       callback to indicate connect start
- * @mlme_cm_ext_connect_active_ind_cb:      callback to indicate connect active
+ * @mlme_cm_ext_candidate_select_ind_cb:    callback to indicate candidate
+ *                                          select for connect
  * @mlme_cm_ext_bss_peer_create_req_cb:     callback to bss peer create request
  * @mlme_cm_ext_connect_req_cb:             callback for connect request to
  *                                          VDEV/PEER SM
@@ -148,7 +149,7 @@ struct mlme_ext_ops {
 	QDF_STATUS (*mlme_cm_ext_connect_start_ind_cb)(
 				struct wlan_objmgr_vdev *vdev,
 				struct wlan_cm_connect_req *req);
-	QDF_STATUS (*mlme_cm_ext_connect_active_ind_cb)(
+	QDF_STATUS (*mlme_cm_ext_candidate_select_ind_cb)(
 			struct wlan_objmgr_vdev *vdev,
 			struct wlan_cm_vdev_connect_req *req);
 	QDF_STATUS (*mlme_cm_ext_bss_peer_create_req_cb)(
@@ -383,15 +384,15 @@ QDF_STATUS mlme_cm_connect_start_ind(struct wlan_objmgr_vdev *vdev,
 				     struct wlan_cm_connect_req *req);
 
 /**
- * mlme_cm_connect_active_ind() - Connection manager ext Connect active
- * indication
+ * mlme_cm_candidate_select_ind() - Connection manager ext Connect candidate
+ * select indication, to do operations for the candidate
  * @vdev: VDEV object
  * @req: Vdev connect request
  *
  * Return: QDF_STATUS
  */
-QDF_STATUS mlme_cm_connect_active_ind(struct wlan_objmgr_vdev *vdev,
-				      struct wlan_cm_vdev_connect_req *req);
+QDF_STATUS mlme_cm_candidate_select_ind(struct wlan_objmgr_vdev *vdev,
+					struct wlan_cm_vdev_connect_req *req);
 
 /**
  * mlme_cm_bss_peer_create_req() - Connection manager ext bss peer create

+ 5 - 5
umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c

@@ -258,13 +258,13 @@ QDF_STATUS mlme_cm_connect_start_ind(struct wlan_objmgr_vdev *vdev,
 	return ret;
 }
 
-QDF_STATUS mlme_cm_connect_active_ind(struct wlan_objmgr_vdev *vdev,
-				      struct wlan_cm_vdev_connect_req *req)
+QDF_STATUS mlme_cm_candidate_select_ind(struct wlan_objmgr_vdev *vdev,
+					struct wlan_cm_vdev_connect_req *req)
 {
-	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+	QDF_STATUS ret = QDF_STATUS_E_NOSUPPORT;
 
-	if ((glbl_ops) && glbl_ops->mlme_cm_ext_connect_active_ind_cb)
-		ret = glbl_ops->mlme_cm_ext_connect_active_ind_cb(vdev, req);
+	if ((glbl_ops) && glbl_ops->mlme_cm_ext_candidate_select_ind_cb)
+		ret = glbl_ops->mlme_cm_ext_candidate_select_ind_cb(vdev, req);
 
 	return ret;
 }