From 85865732012b9b56d87fc3ea4c86ada35b75ef95 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 11 Jul 2019 13:37:20 +0530 Subject: [PATCH] qcacld-3.0: Handle bss peer add failure in vdev state machine In case bss peer add failure vdev state machine is in substate WLAN_VDEV_SS_START_START_PROGRESS and thus WLAN_VDEV_SM_EV_CONNECTION_FAIL will not be handled and thus vdev SM will not move to init state and pe session is not deleted. This lead to vdev ref leak for the ref taken by pe create session. Fix this by sending WLAN_VDEV_SM_EV_START_REQ_FAIL event when vdev SM is in WLAN_VDEV_SS_START_START_PROGRESS state and continue cleanup. Change-Id: I4c559333a6bd018e3382f9781883acf314434cf2 CRs-Fixed: 2502817 --- .../core/src/wlan_mlme_vdev_mgr_interface.c | 20 ++++++++++ .../src/pe/lim/lim_process_mlm_host_roam.c | 14 +++++-- .../src/pe/lim/lim_process_mlm_rsp_messages.c | 15 +++++++- core/mac/src/pe/lim/lim_types.h | 8 +++- core/mac/src/pe/lim/lim_utils.c | 37 ++++++++++++++++++- core/mac/src/pe/lim/lim_utils.h | 14 +++++++ core/wma/src/wma_utils.c | 6 +++ 7 files changed, 106 insertions(+), 8 deletions(-) diff --git a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c index 20a8c3024e61..caf626c02468 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -154,6 +154,25 @@ static QDF_STATUS sta_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme, event_data); } +/** + * sta_mlme_vdev_start_req_failed() - MLME start fail callback + * @vdev_mlme: vdev mlme object + * @event_data_len: event data length + * @event_data: event data + * + * This function is called to send the vdev stop to firmware + * + * Return: QDF_STATUS + */ +static QDF_STATUS sta_mlme_vdev_start_req_failed(struct vdev_mlme_obj *vdev_mlme, + uint16_t data_len, + void *data) +{ + mlme_legacy_debug("vdev id = %d ", + vdev_mlme->vdev->vdev_objmgr.vdev_id); + return lim_sta_mlme_vdev_req_fail(vdev_mlme, data_len, data); +} + /** * sta_mlme_vdev_start_connection() - MLME vdev start callback * @vdev_mlme: vdev mlme object @@ -962,6 +981,7 @@ static struct vdev_mlme_ops sta_mlme_ops = { .mlme_vdev_start_send = sta_mlme_vdev_start_send, .mlme_vdev_restart_send = sta_mlme_vdev_restart_send, .mlme_vdev_start_continue = sta_mlme_start_continue, + .mlme_vdev_start_req_failed = sta_mlme_vdev_start_req_failed, .mlme_vdev_sta_conn_start = sta_mlme_vdev_start_connection, .mlme_vdev_up_send = sta_mlme_vdev_up_send, .mlme_vdev_notify_up_complete = sta_mlme_vdev_notify_up_complete, diff --git a/core/mac/src/pe/lim/lim_process_mlm_host_roam.c b/core/mac/src/pe/lim/lim_process_mlm_host_roam.c index 5778ff595298..2292482647ea 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_host_roam.c +++ b/core/mac/src/pe/lim/lim_process_mlm_host_roam.c @@ -302,10 +302,16 @@ void lim_process_mlm_reassoc_cnf(struct mac_context *mac_ctx, uint32_t *msg_buf) param.session = session; mlme_set_connection_fail(session->vdev, true); - status = wlan_vdev_mlme_sm_deliver_evt( - session->vdev, - WLAN_VDEV_SM_EV_CONNECTION_FAIL, - sizeof(param), ¶m); + + if (wlan_vdev_mlme_get_substate(session->vdev) == + WLAN_VDEV_SS_START_START_PROGRESS) + status = wlan_vdev_mlme_sm_deliver_evt(session->vdev, + WLAN_VDEV_SM_EV_START_REQ_FAIL, + sizeof(param), ¶m); + else + status = wlan_vdev_mlme_sm_deliver_evt(session->vdev, + WLAN_VDEV_SM_EV_CONNECTION_FAIL, + sizeof(param), ¶m); } if (session->pLimReAssocReq) { diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 72d979dcb1ef..a46bdbc16831 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1225,7 +1225,7 @@ static void lim_join_result_callback(struct mac_context *mac, void *param, qdf_mem_free(link_state_params); } -QDF_STATUS lim_sta_send_down_link(join_params *param) +QDF_STATUS lim_sta_handle_connect_fail(join_params *param) { struct pe_session *session; struct mac_context *mac_ctx; @@ -1310,6 +1310,9 @@ error: param->result_code, param->prot_status_code, session, session->smeSessionId); + if (param->result_code == eSIR_SME_PEER_CREATE_FAILED) + pe_delete_session(mac_ctx, session); + return QDF_STATUS_SUCCESS; } @@ -1338,6 +1341,7 @@ void lim_handle_sme_join_result(struct mac_context *mac_ctx, pe_err("session is NULL"); return; } + if (result_code == eSIR_SME_SUCCESS) { wlan_vdev_mlme_sm_deliver_evt(session->vdev, WLAN_VDEV_SM_EV_START_SUCCESS, @@ -1353,9 +1357,16 @@ void lim_handle_sme_join_result(struct mac_context *mac_ctx, param.pe_session_id = session->peSessionId; mlme_set_connection_fail(session->vdev, true); - status = wlan_vdev_mlme_sm_deliver_evt(session->vdev, + if (wlan_vdev_mlme_get_substate(session->vdev) == + WLAN_VDEV_SS_START_START_PROGRESS) + status = wlan_vdev_mlme_sm_deliver_evt(session->vdev, + WLAN_VDEV_SM_EV_START_REQ_FAIL, + sizeof(param), ¶m); + else + status = wlan_vdev_mlme_sm_deliver_evt(session->vdev, WLAN_VDEV_SM_EV_CONNECTION_FAIL, sizeof(param), ¶m); + return; } diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index d0896ce6b226..c53cc399e487 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -739,7 +739,13 @@ void lim_process_mlm_set_bss_key_rsp(struct mac_context *mac, /* Function to process WMA_SWITCH_CHANNEL_RSP message */ void lim_process_switch_channel_rsp(struct mac_context *mac, void *); -QDF_STATUS lim_sta_send_down_link(join_params *param); +/** + * lim_sta_handle_connect_fail() - handle connect failure of STA + * @param - join params + * + * Return: QDF_STATUS + */ +QDF_STATUS lim_sta_handle_connect_fail(join_params *param); #ifdef WLAN_FEATURE_HOST_ROAM QDF_STATUS lim_sta_reassoc_error_handler(struct reassoc_params *param); diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 962c2446be8a..210650d67a47 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -7935,7 +7935,8 @@ QDF_STATUS lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme, assoc_type = mlme_get_assoc_type(vdev_mlme->vdev); switch (assoc_type) { case VDEV_ASSOC: - status = lim_sta_send_down_link((join_params *)data); + status = + lim_sta_handle_connect_fail((join_params *)data); break; case VDEV_REASSOC: case VDEV_FT_REASSOC: @@ -7955,6 +7956,40 @@ QDF_STATUS lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme, return status; } +QDF_STATUS lim_sta_mlme_vdev_req_fail(struct vdev_mlme_obj *vdev_mlme, + uint16_t data_len, void *data) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + enum vdev_assoc_type assoc_type; + + if (!vdev_mlme) { + pe_err("vdev_mlme is NULL"); + return QDF_STATUS_E_INVAL; + } + if (!data) { + pe_err("event_data is NULL"); + return QDF_STATUS_E_INVAL; + } + + assoc_type = mlme_get_assoc_type(vdev_mlme->vdev); + switch (assoc_type) { + case VDEV_ASSOC: + status = lim_sta_handle_connect_fail((join_params *)data); + break; + case VDEV_REASSOC: + case VDEV_FT_REASSOC: + status = lim_sta_reassoc_error_handler( + (struct reassoc_params *)data); + break; + default: + pe_info("Invalid assoc_type %d", assoc_type); + status = QDF_STATUS_E_INVAL; + break; + } + + return status; +} + void lim_send_beacon(struct mac_context *mac_ctx, struct pe_session *session) { if (wlan_vdev_mlme_get_state(session->vdev) == diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index c64e3a202996..c31748e31df7 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -1555,6 +1555,20 @@ void lim_disconnect_complete(struct pe_session *session, bool del_bss); QDF_STATUS lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data); +/** + * lim_sta_mlme_vdev_req_fail() - send VDEV start req failure + * @vdev_mlme_obj: VDEV MLME comp object + * @data_len: data size + * @data: event data + * + * API invokes vdev stop + * + * Return: SUCCESS on successful completion of req failure operation + * FAILURE, if it fails due to any + */ +QDF_STATUS lim_sta_mlme_vdev_req_fail(struct vdev_mlme_obj *vdev_mlme, + uint16_t data_len, void *data); + /** * lim_sta_mlme_vdev_start_send() - send VDEV start * @vdev_mlme_obj: VDEV MLME comp object diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 9b3fc730b9d2..2005dc9012c9 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -4167,6 +4167,12 @@ wma_mlme_vdev_notify_down_complete(struct vdev_mlme_obj *vdev_mlme, tp_wma_handle wma; struct wma_target_req *req = (struct wma_target_req *)data; + if (mlme_is_connection_fail(vdev_mlme->vdev)) { + WMA_LOGD("%s Vdev start req failed, no action required", + __func__); + mlme_set_connection_fail(vdev_mlme->vdev, false); + return QDF_STATUS_SUCCESS; + } wma = cds_get_context(QDF_MODULE_ID_WMA); if (!wma) { WMA_LOGE("%s wma handle is NULL", __func__);