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
This commit is contained in:
gaurank kathpalia 2020-09-14 12:46:33 +05:30 • committed by snandini
commit b35ff6577c
6 changed files with 141 additions and 69 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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__ */

View file

@ -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;
}