From b35ff6577caa8032dcf0506b7aacca319379642b Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Mon, 14 Sep 2020 12:46:33 +0530 Subject: [PATCH] qcacmn: use proper event post API for internal and external events Use cm_sm_deliver_event() API to post the event from any callback/req/resp from external modules. i.e serialization/hw mode callback OR any resp from SB/other module or req from NB. And use cm_sm_deliver_event_sync() API to post the event when the SM lock is already taken i.e. internal posting of the event. Also to avoid any race add the connect/disconnect req to the connection manager request list after posting to the SM. Change-Id: I98fc39be5ef51242553dae54448c3fe2cb9604d2 CRs-Fixed: 2776010 --- .../connection_mgr/core/src/wlan_cm_connect.c | 47 +++++++++------- .../core/src/wlan_cm_disconnect.c | 37 +++++++------ .../core/src/wlan_cm_main_api.h | 30 ++++++++++- .../mlme/connection_mgr/core/src/wlan_cm_sm.c | 54 +++++++++++-------- .../mlme/connection_mgr/core/src/wlan_cm_sm.h | 36 ++++++++----- .../connection_mgr/core/src/wlan_cm_util.c | 6 ++- 6 files changed, 141 insertions(+), 69 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 ef84d9c1cb1a..b0c20d686d2e 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c @@ -248,8 +248,8 @@ cm_send_connect_start_fail(struct cnx_mgr *cm_ctx, if (!resp) return QDF_STATUS_E_NOMEM; - status = cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE, - sizeof(*resp), resp); + status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE, + sizeof(*resp), resp); qdf_mem_free(resp); return status; @@ -291,8 +291,10 @@ static QDF_STATUS cm_connect_get_candidates(struct wlan_objmgr_pdev *pdev, * return failure */ if (!num_bss) - return cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_SCAN, - sizeof(*cm_req), cm_req); + return cm_sm_deliver_event_sync(cm_ctx, + WLAN_CM_SM_EV_SCAN, + sizeof(*cm_req), + cm_req); return QDF_STATUS_E_EMPTY; } @@ -395,6 +397,21 @@ QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx, return QDF_STATUS_SUCCESS; } +QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx, + struct cm_connect_req *req) +{ + QDF_STATUS status; + struct cm_req *cm_req; + + cm_req = qdf_container_of(req, struct cm_req, connect_req); + req->cm_id = cm_get_cm_id(cm_ctx, req->req.source); + cm_req->cm_id = req->cm_id; + status = cm_add_req_to_list_and_indicate_osif(cm_ctx, cm_req, + req->req.source); + + return status; +} + QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev, struct wlan_cm_connect_req *req) { @@ -410,7 +427,10 @@ QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_INVAL; } - /* This would be freed as part of list removal from req list */ + /* + * This would be freed as part of removal from cm req list if adding + * to list is success after posting WLAN_CM_SM_EV_CONNECT_REQ. + */ cm_req = qdf_mem_malloc(sizeof(*cm_req)); if (!cm_req) return QDF_STATUS_E_NOMEM; @@ -420,23 +440,14 @@ QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev, */ connect_req = &cm_req->connect_req; - connect_req->cm_id = cm_get_cm_id(cm_ctx, req->source); - cm_req->cm_id = connect_req->cm_id; connect_req->req = *req; - status = cm_add_req_to_list(cm_ctx, cm_req); - - if (QDF_IS_STATUS_ERROR(status)) { - qdf_mem_free(cm_req); - return status; - } - - mlme_cm_osif_update_id_and_src(vdev, req->source, cm_req->cm_id); - - status = cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_CONNECT_REQ, + status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_CONNECT_REQ, sizeof(*connect_req), connect_req); + + /* free the req if connect is not handled */ if (QDF_IS_STATUS_ERROR(status)) - cm_delete_req_from_list(cm_ctx, cm_req->cm_id); + qdf_mem_free(cm_req); return 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 fa5c88809633..131d22c9a52b 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c @@ -145,6 +145,21 @@ QDF_STATUS cm_disconnect_complete(struct cnx_mgr *cm_ctx, return QDF_STATUS_SUCCESS; } +QDF_STATUS cm_add_disconnect_req_to_list(struct cnx_mgr *cm_ctx, + struct cm_disconnect_req *req) +{ + QDF_STATUS status; + struct cm_req *cm_req; + + cm_req = qdf_container_of(req, struct cm_req, discon_req); + req->cm_id = cm_get_cm_id(cm_ctx, req->req.source); + cm_req->cm_id = req->cm_id; + status = cm_add_req_to_list_and_indicate_osif(cm_ctx, cm_req, + req->req.source); + + return status; +} + QDF_STATUS cm_disconnect_start_req(struct wlan_objmgr_vdev *vdev, struct wlan_cm_disconnect_req *req) { @@ -160,31 +175,23 @@ QDF_STATUS cm_disconnect_start_req(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_INVAL; } - /* This would be freed as part of list removal from req list */ + /* + * This would be freed as part of removal from cm req list if adding + * to list is success after posting WLAN_CM_SM_EV_DISCONNECT_REQ. + */ cm_req = qdf_mem_malloc(sizeof(*cm_req)); if (!cm_req) return QDF_STATUS_E_NOMEM; disconnect_req = &cm_req->discon_req; - - disconnect_req->cm_id = cm_get_cm_id(cm_ctx, req->source); - cm_req->cm_id = disconnect_req->cm_id; disconnect_req->req = *req; - status = cm_add_req_to_list(cm_ctx, cm_req); - if (QDF_IS_STATUS_ERROR(status)) { - qdf_mem_free(cm_req); - return status; - } - - mlme_cm_osif_update_id_and_src(vdev, req->source, cm_req->cm_id); - - status = cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_DISCONNECT_REQ, + status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_DISCONNECT_REQ, sizeof(*disconnect_req), disconnect_req); - + /* free the req if connect is not handled */ if (QDF_IS_STATUS_ERROR(status)) - cm_delete_req_from_list(cm_ctx, cm_req->cm_id); + qdf_mem_free(cm_req); return 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 b13726d1f098..99b48cfcb4eb 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 @@ -104,6 +104,17 @@ QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id); QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx, struct wlan_cm_connect_rsp *resp); +/** + * cm_add_connect_req_to_list() - add connect req to the connection manager + * req list + * @vdev: vdev on which connect is received + * @req: Connection req provided + * + * Return: QDF status + */ +QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx, + struct cm_connect_req *req); + /** * cm_connect_start_req() - Connect start req from the requester * @vdev: vdev on which connect is received @@ -164,6 +175,17 @@ QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id); QDF_STATUS cm_disconnect_complete(struct cnx_mgr *cm_ctx, struct wlan_cm_discon_rsp *resp); +/** + * cm_add_disconnect_req_to_list() - add disconnect req to the connection + * manager req list + * @vdev: vdev on which connect is received + * @req: Disconnection req provided + * + * Return: QDF status + */ +QDF_STATUS cm_add_disconnect_req_to_list(struct cnx_mgr *cm_ctx, + struct cm_disconnect_req *req); + /** * cm_disconnect_start_req() - Disconnect start req from the requester * @vdev: vdev on which connect is received @@ -219,15 +241,19 @@ bool cm_check_cmid_match_list_head(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id); QDF_STATUS cm_delete_req_from_list(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id); /** - * cm_add_req_to_list() - Add the request to request list in cm ctx + * cm_add_req_to_list_and_indicate_osif() - Add the request to request list in + * cm ctx and indicate same to osif * @cm_ctx: connection manager context * @cm_req: cm request + * @source: source of request * * Context: Can be called from any context. * * Return: QDF_STATUS */ -QDF_STATUS cm_add_req_to_list(struct cnx_mgr *cm_ctx, struct cm_req *cm_req); +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); /** * cm_get_req_by_cm_id() - Get cm req matching the 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 13dfebfe3f5f..c9bb1596f04f 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_sm.c @@ -91,12 +91,19 @@ static bool cm_state_init_event(void *ctx, uint16_t event, { struct cnx_mgr *cm_ctx = ctx; bool status; + QDF_STATUS qdf_status; switch (event) { case WLAN_CM_SM_EV_CONNECT_REQ: + qdf_status = cm_add_connect_req_to_list(cm_ctx, data); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + /* if fail to add req return failure */ + status = false; + break; + } cm_sm_transition_to(cm_ctx, WLAN_CM_S_CONNECTING); - cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_CONNECT_START, - data_len, data); + cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_START, + data_len, data); status = true; break; case WLAN_CM_SM_EV_CONNECT_FAILURE: @@ -162,7 +169,7 @@ static bool cm_state_connecting_event(void *ctx, uint16_t event, switch (event) { case WLAN_CM_SM_EV_CONNECT_START: cm_sm_transition_to(cm_ctx, WLAN_CM_SS_JOIN_PENDING); - cm_sm_deliver_event(cm_ctx, event, data_len, data); + cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); status = true; break; default: @@ -216,6 +223,7 @@ static bool cm_state_connected_event(void *ctx, uint16_t event, { struct cnx_mgr *cm_ctx = ctx; bool status; + QDF_STATUS qdf_status; switch (event) { case WLAN_CM_SM_EV_CONNECT_SUCCESS: @@ -223,9 +231,15 @@ static bool cm_state_connected_event(void *ctx, uint16_t event, status = true; break; case WLAN_CM_SM_EV_DISCONNECT_REQ: + qdf_status = cm_add_disconnect_req_to_list(cm_ctx, data); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + /* if fail to add req return failure */ + status = false; + break; + } cm_sm_transition_to(cm_ctx, WLAN_CM_S_DISCONNECTING); - cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_DISCONNECT_START, - data_len, data); + cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_DISCONNECT_START, + data_len, data); status = true; break; default: @@ -291,7 +305,7 @@ static bool cm_state_disconnecting_event(void *ctx, uint16_t event, break; case WLAN_CM_SM_EV_DISCONNECT_DONE: cm_sm_transition_to(cm_ctx, WLAN_CM_S_INIT); - cm_sm_deliver_event(cm_ctx, event, data_len, data); + cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); status = true; break; default: @@ -357,12 +371,12 @@ static bool cm_subst_join_pending_event(void *ctx, uint16_t event, break; case WLAN_CM_SM_EV_CONNECT_ACTIVE: cm_sm_transition_to(cm_ctx, WLAN_CM_SS_JOIN_ACTIVE); - cm_sm_deliver_event(cm_ctx, event, data_len, data); + cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); status = true; break; case WLAN_CM_SM_EV_SCAN: cm_sm_transition_to(cm_ctx, WLAN_CM_SS_SCAN); - cm_sm_deliver_event(cm_ctx, event, data_len, data); + cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); status = true; break; case WLAN_CM_SM_EV_SCAN_FAILURE: @@ -374,7 +388,7 @@ static bool cm_subst_join_pending_event(void *ctx, uint16_t event, break; case WLAN_CM_SM_EV_CONNECT_FAILURE: cm_sm_transition_to(cm_ctx, WLAN_CM_S_INIT); - cm_sm_deliver_event(cm_ctx, event, data_len, data); + cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); status = true; break; default: @@ -440,7 +454,7 @@ static bool cm_subst_scan_event(void *ctx, uint16_t event, case WLAN_CM_SM_EV_SCAN_SUCCESS: case WLAN_CM_SM_EV_SCAN_FAILURE: cm_sm_transition_to(cm_ctx, WLAN_CM_SS_JOIN_PENDING); - cm_sm_deliver_event(cm_ctx, event, data_len, data); + cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); status = true; break; default: @@ -505,7 +519,7 @@ static bool cm_subst_join_active_event(void *ctx, uint16_t event, break; case WLAN_CM_SM_EV_CONNECT_SUCCESS: cm_sm_transition_to(cm_ctx, WLAN_CM_S_CONNECTED); - cm_sm_deliver_event(cm_ctx, event, data_len, data); + cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); status = true; break; case WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE: @@ -514,7 +528,7 @@ static bool cm_subst_join_active_event(void *ctx, uint16_t event, break; case WLAN_CM_SM_EV_CONNECT_FAILURE: cm_sm_transition_to(cm_ctx, WLAN_CM_S_INIT); - cm_sm_deliver_event(cm_ctx, event, data_len, data); + cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); status = true; break; default: @@ -761,11 +775,10 @@ static void cm_sm_print_state(struct cnx_mgr *cm_ctx) cm_sm_info[state].name, cm_sm_info[substate].name); } -QDF_STATUS wlan_cm_sm_deliver_evt(struct wlan_objmgr_vdev *vdev, - enum wlan_cm_sm_evt event, - uint16_t data_len, void *data) +QDF_STATUS cm_sm_deliver_event(struct wlan_objmgr_vdev *vdev, + enum wlan_cm_sm_evt event, + uint16_t data_len, void *data) { - struct vdev_mlme_obj *vdev_mlme; QDF_STATUS status; enum wlan_cm_sm_state state_entry, state_exit; enum wlan_cm_sm_state substate_entry, substate_exit; @@ -777,12 +790,11 @@ QDF_STATUS wlan_cm_sm_deliver_evt(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_NOSUPPORT; } - vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); - if (!vdev_mlme || !vdev_mlme->cnx_mgr_ctx) { - mlme_err("vdev mlme or cm ctx is NULL"); + cm_ctx = cm_get_cm_ctx(vdev); + if (!cm_ctx) { + mlme_err("cm_ctx is NULL"); return QDF_STATUS_E_FAILURE; } - cm_ctx = vdev_mlme->cnx_mgr_ctx; cm_lock_acquire(cm_ctx); /* store entry state and sub state for prints */ @@ -790,7 +802,7 @@ QDF_STATUS wlan_cm_sm_deliver_evt(struct wlan_objmgr_vdev *vdev, substate_entry = cm_get_sub_state(cm_ctx); cm_sm_print_state_event(cm_ctx, event); - status = cm_sm_deliver_event(cm_ctx, event, data_len, data); + status = cm_sm_deliver_event_sync(cm_ctx, event, data_len, data); /* Take exit state, exit substate for prints */ state_exit = cm_get_state(cm_ctx); substate_exit = cm_get_sub_state(cm_ctx); 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 2d9177d67cb0..c3a4f51d0622 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_sm.h @@ -274,40 +274,52 @@ void cm_sm_state_update(struct cnx_mgr *cm_ctx, enum wlan_cm_sm_state substate); /** - * cm_sm_deliver_event() - Delivers event to connection manager SM + * cm_sm_deliver_event_sync() - Delivers event to connection manager SM while + * holding lock * @cm_ctx: cm ctx * @event: CM event * @data_len: data size * @data: event data * - * API to dispatch event to VDEV MLME SM without lock + * API to dispatch event to VDEV MLME SM without lock, in case lock is already + * held. + * + * Context: Can be called from any context, This should be called in case + * SM lock is already taken. If lock is not taken use cm_sm_deliver_event API + * instead. * * Return: SUCCESS: on handling event - * FAILURE: on ignoring the event + * FAILURE: If event not handled */ static inline -QDF_STATUS cm_sm_deliver_event(struct cnx_mgr *cm_ctx, - enum wlan_cm_sm_evt event, - uint16_t data_len, void *data) +QDF_STATUS cm_sm_deliver_event_sync(struct cnx_mgr *cm_ctx, + enum wlan_cm_sm_evt event, + uint16_t data_len, void *data) { return wlan_sm_dispatch(cm_ctx->sm.sm_hdl, event, data_len, data); } /** - * wlan_cm_sm_deliver_evt() - Delivers event to CM SM + * cm_sm_deliver_event() - Delivers event to connection manager SM * @vdev: Object manager VDEV object * @event: CM event * @data_len: data size * @data: event data * - * API to dispatch event to VDEV MLME SM with lock acquired + * API to dispatch event to VDEV MLME SM with lock. To be used while paosting + * events from API called from publick API. i.e. indication/response/request + * from any other moudle or NB/SB. + * + * Context: Can be called from any context, This should be called in case + * SM lock is not taken, the API will take the lock before posting to SM. + * If lock is already taken use cm_sm_deliver_event_sync API instead. * * Return: SUCCESS: on handling event - * FAILURE: on ignoring the event + * FAILURE: If event not handled */ -QDF_STATUS wlan_cm_sm_deliver_evt(struct wlan_objmgr_vdev *vdev, - enum wlan_cm_sm_evt event, - uint16_t data_len, void *data); +QDF_STATUS cm_sm_deliver_event(struct wlan_objmgr_vdev *vdev, + enum wlan_cm_sm_evt event, + uint16_t data_len, void *data); #endif /* FEATURE_CM_ENABLE */ #endif /* __WLAN_CM_SM_H__ */ 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 cce5a9b7ad9c..88dcea8afaed 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_util.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_util.c @@ -147,7 +147,9 @@ struct cm_req *cm_get_req_by_cm_id(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id) return NULL; } -QDF_STATUS cm_add_req_to_list(struct cnx_mgr *cm_ctx, struct cm_req *cm_req) +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) { uint32_t prefix = CM_ID_GET_PREFIX(cm_req->cm_id); @@ -165,6 +167,8 @@ QDF_STATUS cm_add_req_to_list(struct cnx_mgr *cm_ctx, struct cm_req *cm_req) cm_ctx->disconnect_count++; cm_req_lock_release(cm_ctx); + mlme_cm_osif_update_id_and_src(cm_ctx->vdev, source, cm_req->cm_id); + return QDF_STATUS_SUCCESS; }