From 4af3739c3dc7cbd2c1a39d22dfc29e667d64bc59 Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Mon, 14 Sep 2020 19:34:06 +0530 Subject: [PATCH] qcacmn: Add connect path logic after serialization Add connect logic after serialization in connection manager. Change-Id: I6aabc956d4ade20379aec000f566ccbfcfdcfd23 CRs-Fixed: 2776348 --- .../connection_mgr/core/src/wlan_cm_connect.c | 245 +++++++++++++++++- .../core/src/wlan_cm_disconnect.c | 12 +- .../connection_mgr/core/src/wlan_cm_main.h | 4 + .../core/src/wlan_cm_main_api.h | 41 +++ .../mlme/connection_mgr/core/src/wlan_cm_sm.c | 5 + .../mlme/connection_mgr/core/src/wlan_cm_sm.h | 36 +-- .../connection_mgr/core/src/wlan_cm_util.c | 19 +- .../dispatcher/inc/wlan_cm_api.h | 2 +- .../dispatcher/src/wlan_cm_api.c | 4 +- 9 files changed, 330 insertions(+), 38 deletions(-) diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c index a5890e11ec6b..c78962cc304a 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c +++ b/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) { - /* - * get first valid candidate, create bss peer. - * fill vdev crypto for the peer. - * call vdev sm to start connect for the candidate. - */ 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 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) { diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c index 30bda41aeb85..c66c9783debd 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c +++ b/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. */ diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_main.h b/umac/mlme/connection_mgr/core/src/wlan_cm_main.h index 5b04228d2429..856bfdb3fe40 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_main.h +++ b/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; diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h b/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h index 467435a54c7f..151e7ded13bb 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h +++ b/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 +#ifdef WLAN_FEATURE_INTERFACE_MGR +#include +#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 diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.c b/umac/mlme/connection_mgr/core/src/wlan_cm_sm.c index 3532b36b19c3..9cc22b89ee2e 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.c +++ b/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", diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h b/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h index 3374c93341b7..7aeca0ba2072 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h +++ b/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, }; diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_util.c b/umac/mlme/connection_mgr/core/src/wlan_cm_util.c index ef026a228e3a..9e1a6613ffae 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_util.c +++ b/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 /** diff --git a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h index 2bfeaed7bff4..9c63d2e11257 100644 --- a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h +++ b/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); /** diff --git a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c b/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c index 0b27d936cc52..2acecf04c7be 100644 --- a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c +++ b/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,