Prechádzať zdrojové kódy

qcacmn: Add connect path logic after serialization

Add connect logic after serialization in connection manager.

Change-Id: I6aabc956d4ade20379aec000f566ccbfcfdcfd23
CRs-Fixed: 2776348
gaurank kathpalia 4 rokov pred
rodič
commit
4af3739c3d

+ 232 - 9
umac/mlme/connection_mgr/core/src/wlan_cm_connect.c

@@ -62,7 +62,7 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd,
 		QDF_ASSERT(0);
 		break;
 	case WLAN_SER_CB_RELEASE_MEM_CMD:
-		/* command completed. Release reference of vdev */
+		cm_reset_active_cm_id(vdev, cmd->cmd_id);
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
 		break;
 	default:
@@ -420,25 +420,187 @@ connect_err:
 	return cm_send_connect_start_fail(cm_ctx, cm_req, reason);
 }
 
-QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
+#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);
+}
+#else
+static inline
+QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
+				 struct scan_cache_entry *scan_entry)
 {
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * cm_get_valid_candidate() - This API will be called to get the next valid
+ * candidate
+ * @cm_ctx: connection manager context
+ * @cm_req: Connect request.
+ *
+ * This function return a valid candidate to try connection. It return failure
+ * if no valid candidate is present or all valid candidate are tried.
+ *
+ * Return: QDF status
+ */
+static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx,
+					 struct cm_req *cm_req)
+{
+	struct scan_cache_node *scan_node = NULL;
+	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
+	struct scan_cache_node *cur_candidate;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (cm_req->connect_req.connect_attempts >=
+	    CM_MAX_CANDIDATE_TO_BE_TRIED) {
+		mlme_info("Max %d candidates tried for the conenction",
+			  cm_req->connect_req.connect_attempts);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	cur_candidate = cm_req->connect_req.cur_candidate;
 	/*
-	 * get first valid candidate, create bss peer.
-	 * fill vdev crypto for the peer.
-	 * call vdev sm to start connect for the candidate.
+	 * Get next candidate if cur_candidate is not NULL, else get
+	 * the first candidate
+	 */
+	if (cur_candidate)
+		qdf_list_peek_next(cm_req->connect_req.candidate_list,
+				   &cur_candidate->node, &cur_node);
+	else
+		qdf_list_peek_front(cm_req->connect_req.candidate_list,
+				    &cur_node);
+
+	while (cur_node) {
+		qdf_list_peek_next(cm_req->connect_req.candidate_list,
+				   cur_node, &next_node);
+		scan_node = qdf_container_of(cur_node, struct scan_cache_node,
+					     node);
+		status = cm_validate_candidate(cm_ctx, scan_node->entry);
+		if (QDF_IS_STATUS_SUCCESS(status)) {
+			cur_candidate = scan_node;
+			break;
+		}
+
+		cur_node = next_node;
+		next_node = NULL;
+	}
+
+	/*
+	 * If cur_node is NULL cur candidate was last to be tried so no more
+	 * candidates left for connect now.
 	 */
+	if (!cur_node) {
+		mlme_debug("No more candidates left");
+		cm_req->connect_req.cur_candidate = NULL;
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	cm_req->connect_req.connect_attempts++;
+	cm_req->connect_req.cur_candidate = cur_candidate;
+
 	return QDF_STATUS_SUCCESS;
 }
 
+static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
+			       struct cm_connect_req *req)
+{
+	QDF_STATUS status;
+	struct qdf_mac_addr *bssid;
+
+	bssid = &req->cur_candidate->entry->bssid;
+	status = mlme_cm_bss_peer_create_req(cm_ctx->vdev, bssid);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		struct wlan_cm_connect_rsp *resp;
+
+		/* 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_sm_deliver_event_sync(cm_ctx,
+				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
+				    sizeof(*resp), resp);
+		qdf_mem_free(resp);
+	}
+}
+
 QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
 				 struct wlan_cm_connect_rsp *resp)
+{
+	QDF_STATUS status;
+	struct cm_req *cm_req;
+
+	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;
+	}
+
+	status = cm_get_valid_candidate(cm_ctx, cm_req);
+	if (QDF_IS_STATUS_ERROR(status))
+		goto connect_err;
+
+	mlme_cm_osif_failed_candidate_ind(cm_ctx->vdev, resp);
+
+	cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
+
+	return QDF_STATUS_SUCCESS;
+
+connect_err:
+	return cm_send_connect_start_fail(cm_ctx, &cm_req->connect_req,
+					  CM_JOIN_FAILED);
+}
+
+QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
+{
+	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 connect fail");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	cm_ctx->active_cm_id = *cm_id;
+
+	status = cm_get_valid_candidate(cm_ctx, cm_req);
+	if (QDF_IS_STATUS_ERROR(status))
+		goto connect_err;
+
+	cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
+
+	return QDF_STATUS_SUCCESS;
+
+connect_err:
+	return cm_send_connect_start_fail(cm_ctx,
+					  &cm_req->connect_req, CM_JOIN_FAILED);
+}
+
+QDF_STATUS
+cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 {
 	/*
-	 * get next valid candidate, if no candidate left, post
-	 * WLAN_CM_SM_EV_CONNECT_FAILURE to SM, inform osif about failure for
-	 * the candidate if its not last one. and initiate the connect for
-	 * next candidate.
+	 * fill vdev crypto for the peer.
+	 * call vdev sm to start connect for the candidate.
 	 */
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -477,6 +639,67 @@ QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx,
 	return 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;
+
+	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);
+		/* Delete peer if create was success */
+		return QDF_STATUS_E_INVAL;
+	}
+
+	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);
+		if (QDF_IS_STATUS_SUCCESS(qdf_status))
+			return qdf_status;
+		goto post_err;
+	}
+
+	resp = qdf_mem_malloc(sizeof(*resp));
+	if (!resp)
+		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;
+
+	/* 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);
+	qdf_mem_free(resp);
+	if (QDF_IS_STATUS_SUCCESS(qdf_status))
+		return qdf_status;
+
+post_err:
+	/*
+	 * handle post error i.e. STATE is not connect active, so
+	 * do cleanup of req.
+	 */
+	return qdf_status;
+}
+
 QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev,
 				struct wlan_cm_connect_req *req)
 {

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

@@ -57,7 +57,7 @@ cm_ser_disconnect_cb(struct wlan_serialization_command *cmd,
 		QDF_ASSERT(0);
 		break;
 	case WLAN_SER_CB_RELEASE_MEM_CMD:
-		/* command completed. Release reference of vdev */
+		cm_reset_active_cm_id(vdev, cmd->cmd_id);
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
 		break;
 	default:
@@ -133,6 +133,16 @@ QDF_STATUS cm_disconnect_start(struct cnx_mgr *cm_ctx,
 
 QDF_STATUS cm_disconnect_active(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 connect fail");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	cm_ctx->active_cm_id = *cm_id;
+
 	/*
 	 * call vdev sm to start disconnect.
 	 */

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

@@ -99,6 +99,7 @@ struct cm_state_sm {
  * @rsn_ie: rsn_ie in connect req
  * @candidate_list: candidate list
  * @cur_candidate: current candidate
+ * @connect_attempts: number of connect attempts tried
  */
 struct cm_connect_req {
 	wlan_cm_id cm_id;
@@ -109,6 +110,7 @@ struct cm_connect_req {
 	struct element_info rsn_ie;
 	qdf_list_t *candidate_list;
 	struct scan_cache_node *cur_candidate;
+	uint8_t connect_attempts;
 };
 
 /**
@@ -157,6 +159,7 @@ struct connect_ies {
  * struct cnx_mgr - connect manager req
  * @vdev: vdev back pointer
  * @sm: state machine
+ * @active_cm_id: cm_id of the active command, if any active command present
  * @req_list: connect/disconnect req list
  * @cm_req_lock: lock to manupulate/read the cm req list
  * @disconnect_count: disconnect count
@@ -170,6 +173,7 @@ struct connect_ies {
 struct cnx_mgr {
 	struct wlan_objmgr_vdev *vdev;
 	struct cm_state_sm sm;
+	wlan_cm_id active_cm_id;
 	qdf_list_t req_list;
 #ifdef WLAN_CM_USE_SPINLOCK
 	qdf_spinlock_t cm_req_lock;

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

@@ -26,6 +26,15 @@
 #include "wlan_cm_main.h"
 #include "wlan_cm_sm.h"
 #include <include/wlan_mlme_cmn.h>
+#ifdef WLAN_FEATURE_INTERFACE_MGR
+#include <wlan_if_mgr_api.h>
+#endif
+
+#define CONNECT_REQ_PREFIX          0x00C00000
+#define DISCONNECT_REQ_PREFIX       0x00D00000
+#define CM_ID_MASK                  0x0000FFFF
+
+#define CM_ID_GET_PREFIX(cm_id)     cm_id & 0xFFFF0000
 
 /*************** CONNECT APIs ****************/
 
@@ -92,6 +101,28 @@ QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
  */
 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
+ * @cm_id: Connection mgr ID assigned to this connect request.
+ *
+ * Return: QDF status
+ */
+QDF_STATUS
+cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id);
+
+/**
+ * cm_bss_peer_create_rsp() - handle bss peer create response
+ * @vdev: vdev
+ * @status: bss peer create status
+ * @peer_mac: peer mac
+ *
+ * Return: QDF status
+ */
+QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
+				  QDF_STATUS status,
+				  struct qdf_mac_addr *peer_mac);
+
 /**
  * cm_connect_complete() - This API would be called after connect complete
  * request from the serialization.
@@ -232,6 +263,16 @@ wlan_cm_id cm_get_cm_id(struct cnx_mgr *cm_ctx, enum wlan_cm_source source);
  */
 struct cnx_mgr *cm_get_cm_ctx(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * cm_reset_active_cm_id() - Reset active cm_id from cm context, if its same as
+ * passed cm_id
+ * @vdev: vdev object pointer
+ * @cm_id: cmid to match
+ *
+ * Return: void
+ */
+void cm_reset_active_cm_id(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id);
+
 /**
  * cm_check_cmid_match_list_head() - check if list head command matches the
  * given cm_id

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

@@ -551,6 +551,10 @@ 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:
+		cm_resume_connect_after_peer_create(cm_ctx, data);
+		status = true;
+		break;
 	default:
 		status = false;
 		break;
@@ -722,6 +726,7 @@ static const char *cm_sm_event_names[] = {
 	"EV_CONNECT_START",
 	"EV_CONNECT_ACTIVE",
 	"EV_CONNECT_SUCCESS",
+	"EV_BSS_CREATE_PEER_SUCCESS"
 	"EV_CONNECT_GET_NXT_CANDIDATE",
 	"EV_CONNECT_FAILURE",
 	"EV_DISCONNECT_REQ",

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

@@ -37,6 +37,7 @@
  * @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_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
@@ -67,23 +68,24 @@ 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_SM_EV_CONNECT_GET_NEXT_CANDIDATE = 9,
-	WLAN_CM_SM_EV_CONNECT_FAILURE = 10,
-	WLAN_CM_SM_EV_DISCONNECT_REQ = 11,
-	WLAN_CM_SM_EV_DISCONNECT_START = 12,
-	WLAN_CM_SM_EV_DISCONNECT_ACTIVE = 13,
-	WLAN_CM_SM_EV_DISCONNECT_DONE = 14,
-	WLAN_CM_SM_EV_ROAM_START = 15,
-	WLAN_CM_SM_EV_ROAM_SYNC = 16,
-	WLAN_CM_SM_EV_ROAM_INVOKE_FAIL = 17,
-	WLAN_CM_SM_EV_ROAM_HO_FAIL = 18,
-	WLAN_CM_SM_EV_PREAUTH_DONE = 19,
-	WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP = 20,
-	WLAN_CM_SM_EV_PREAUTH_FAIL = 21,
-	WLAN_CM_SM_EV_START_REASSOC = 22,
-	WLAN_CM_SM_EV_REASSOC_DONE = 23,
-	WLAN_CM_SM_EV_REASSOC_FAILURE = 24,
-	WLAN_CM_SM_EV_ROAM_COMPLETE = 25,
+	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_MAX,
 };
 

+ 13 - 6
umac/mlme/connection_mgr/core/src/wlan_cm_util.c

@@ -22,12 +22,6 @@
 #include "wlan_scan_api.h"
 #include "wlan_cm_public_struct.h"
 
-#define CONNECT_REQ_PREFIX          0x00C00000
-#define DISCONNECT_REQ_PREFIX       0x00D00000
-#define CM_ID_MASK                  0x0000FFFF
-
-#define CM_ID_GET_PREFIX(cm_id)     cm_id & 0xFFFF0000
-
 static uint32_t cm_get_prefix_for_cm_id(enum wlan_cm_source source) {
 	switch (source) {
 	case CM_OSIF_CONNECT:
@@ -63,6 +57,19 @@ struct cnx_mgr *cm_get_cm_ctx(struct wlan_objmgr_vdev *vdev)
 	return vdev_mlme->cnx_mgr_ctx;
 }
 
+void cm_reset_active_cm_id(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id)
+{
+	struct cnx_mgr *cm_ctx;
+
+	cm_ctx = cm_get_cm_ctx(vdev);
+	if (!cm_ctx)
+		return;
+
+	/* Reset active cm id if cm id match */
+	if (cm_ctx->active_cm_id == cm_id)
+		cm_ctx->active_cm_id = CM_ID_INVALID;
+}
+
 
 #ifdef WLAN_CM_USE_SPINLOCK
 /**

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

@@ -55,7 +55,7 @@ QDF_STATUS wlan_cm_start_disconnect(struct wlan_objmgr_vdev *vdev,
  * Return: QDF_STATUS
  */
 QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
-				       uint32_t status,
+				       QDF_STATUS status,
 				       struct qdf_mac_addr *peer_mac);
 
 /**

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

@@ -36,10 +36,10 @@ QDF_STATUS wlan_cm_start_disconnect(struct wlan_objmgr_vdev *vdev,
 }
 
 QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
-				       uint32_t status,
+				       QDF_STATUS status,
 				       struct qdf_mac_addr *peer_mac)
 {
-	return QDF_STATUS_SUCCESS;
+	return cm_bss_peer_create_rsp(vdev, status, peer_mac);
 }
 
 QDF_STATUS wlan_cm_connect_rsp(struct wlan_objmgr_vdev *vdev,