From 4de6d6b0d5b485a492257f3a5c4cfd02344f1228 Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Mon, 21 Sep 2020 13:10:16 +0530 Subject: [PATCH] qcacmn: Handle connect response in connection manager Handle connection response in connection manager. Change-Id: I796b3c19c728323901f1a44e851616d3a0286763 CRs-Fixed: 2781566 --- .../connection_mgr/core/src/wlan_cm_connect.c | 348 ++++++++++++++++-- .../core/src/wlan_cm_disconnect.c | 1 + .../core/src/wlan_cm_main_api.h | 57 ++- .../mlme/connection_mgr/core/src/wlan_cm_sm.c | 25 ++ .../connection_mgr/core/src/wlan_cm_util.c | 38 ++ .../dispatcher/inc/wlan_cm_api.h | 4 +- .../dispatcher/inc/wlan_cm_public_struct.h | 19 +- .../dispatcher/src/wlan_cm_api.c | 4 +- 8 files changed, 439 insertions(+), 57 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 c78962cc30..89cb904bc4 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c @@ -26,6 +26,67 @@ #include "wlan_policy_mgr_api.h" #endif #include +#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 - * update fils/wep key and inform legacy, update bcn filter and scan - * entry mlme info, blm action and remove from serialization at the end. + * 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,, start OBSS scan for open mode. + */ + + cm_remove_cmd(cm_ctx, resp->cm_id); + return QDF_STATUS_SUCCESS; } @@ -639,13 +850,11 @@ 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) +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; - struct wlan_cm_connect_rsp *resp; wlan_cm_id cm_id; uint32_t prefix; @@ -658,9 +867,69 @@ QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev, 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; + 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); - /* 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; } - 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 */ + resp = qdf_mem_malloc(sizeof(*resp)); + if (!resp) { + qdf_status = QDF_STATUS_E_NOMEM; + goto post_err; + } + + cm_fill_resp_for_bss_create_fail(cm_ctx->vdev, resp, cm_id, peer_mac); + 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; } 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 c66c9783de..cb5348877d 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c +++ b/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) { 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 151e7ded13..713a93c6ad 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 @@ -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 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 9cc22b89ee..142c0a4dbc 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.c +++ b/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; 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 9e1a6613ff..58c134e294 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_util.c +++ b/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); + } +} 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 bce5258c53..3f55945c23 100644 --- a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h +++ b/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 diff --git a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h index f2bf46fe8b..f791a3ec73 100644 --- a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h +++ b/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; }; 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 ddde298fa1..9b20120342 100644 --- a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c +++ b/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,