diff --git a/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h b/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h index b86d1852d664..f58e39709801 100644 --- a/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h +++ b/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h @@ -32,11 +32,13 @@ * @hidden_ssid_restart_in_progress: flag to indicate hidden ssid restart is * in progress * @vdev_start_failed: flag to indicate that vdev start failed. + * @connection_fail: flag to indicate connection failed */ struct mlme_legacy_priv { bool chan_switch_in_progress; bool hidden_ssid_restart_in_progress; bool vdev_start_failed; + bool connection_fail; }; /** @@ -107,6 +109,24 @@ bool ap_mlme_is_hidden_ssid_restart_in_progress(struct wlan_objmgr_vdev *vdev); QDF_STATUS mlme_set_vdev_start_failed(struct wlan_objmgr_vdev *vdev, bool val); +/** + * mlme_is_connection_fail() - get connection fail flag + * @vdev: vdev pointer + * + * Return: value of vdev connection failure flag + */ +bool mlme_is_connection_fail(struct wlan_objmgr_vdev *vdev); + +/** + * mlme_set_connection_fail() - set connection failure flag + * @vdev: vdev pointer + * @val: value to be set + * + * Return: QDF_STATUS + */ +QDF_STATUS +mlme_set_connection_fail(struct wlan_objmgr_vdev *vdev, bool val); + /** * mlme_get_vdev_start_failed() - get mlme priv vdev restart fail flag * @vdev: vdev pointer 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 c08655bcaa6b..694bc27b1540 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -382,7 +382,7 @@ static QDF_STATUS vdevmgr_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme, static QDF_STATUS vdevmgr_notify_down_complete(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data) { - return wma_ap_mlme_vdev_notify_down_complete(vdev_mlme, data_len, data); + return wma_mlme_vdev_notify_down_complete(vdev_mlme, data_len, data); } /** @@ -507,6 +507,40 @@ bool ap_mlme_is_hidden_ssid_restart_in_progress(struct wlan_objmgr_vdev *vdev) return mlme_priv->hidden_ssid_restart_in_progress; } +QDF_STATUS mlme_set_connection_fail(struct wlan_objmgr_vdev *vdev, bool val) +{ + struct vdev_mlme_obj *vdev_mlme; + struct mlme_legacy_priv *mlme_priv; + + vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); + if (!vdev_mlme) { + mlme_err("vdev component object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + mlme_priv = (struct mlme_legacy_priv *)vdev_mlme->legacy_vdev_ptr; + + mlme_priv->connection_fail = val; + + return QDF_STATUS_SUCCESS; +} + +bool mlme_is_connection_fail(struct wlan_objmgr_vdev *vdev) +{ + struct vdev_mlme_obj *vdev_mlme; + struct mlme_legacy_priv *mlme_priv; + + vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); + if (!vdev_mlme) { + mlme_err("vdev component object is NULL"); + return false; + } + + mlme_priv = (struct mlme_legacy_priv *)vdev_mlme->legacy_vdev_ptr; + + return mlme_priv->connection_fail; +} + QDF_STATUS mlme_set_vdev_start_failed(struct wlan_objmgr_vdev *vdev, bool val) { 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 2e1916cf2c90..30f50242106f 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 @@ -1277,6 +1277,96 @@ static void lim_join_result_callback(tpAniSirGlobal mac, void *param, qdf_mem_free(link_state_params); } +#ifdef CONFIG_VDEV_SM +QDF_STATUS lim_sta_send_down_link(join_params *param) +{ + tpPESession session; + tpAniSirGlobal mac_ctx; + tpDphHashNode sta_ds = NULL; + + if (!param) { + pe_err("param is NULL"); + return QDF_STATUS_E_INVAL; + } + + mac_ctx = cds_get_context(QDF_MODULE_ID_PE); + if (!mac_ctx) { + pe_err("Mac context is NULL"); + return QDF_STATUS_E_INVAL; + } + session = pe_find_session_by_session_id(mac_ctx, param->pe_session_id); + if (!session) { + pe_err("session is NULL"); + return QDF_STATUS_E_INVAL; + } + + sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session->dph.dphHashTable); + if (sta_ds) { + sta_ds->mlmStaContext.disassocReason = + eSIR_MAC_UNSPEC_FAILURE_REASON; + sta_ds->mlmStaContext.cleanupTrigger = + eLIM_JOIN_FAILURE; + sta_ds->mlmStaContext.resultCode = param->result_code; + sta_ds->mlmStaContext.protStatusCode = param->prot_status_code; + /* + * FIX_ME: at the end of lim_cleanup_rx_path, + * make sure PE is sending eWNI_SME_JOIN_RSP + * to SME + */ + lim_cleanup_rx_path(mac_ctx, sta_ds, session); + qdf_mem_free(session->pLimJoinReq); + session->pLimJoinReq = NULL; + /* Cleanup if add bss failed */ + if (session->add_bss_failed) { + dph_delete_hash_entry(mac_ctx, + sta_ds->staAddr, sta_ds->assocId, + &session->dph.dphHashTable); + goto error; + } + return QDF_STATUS_SUCCESS; + } + qdf_mem_free(session->pLimJoinReq); + session->pLimJoinReq = NULL; + +error: + /* + * Delete the session if JOIN failure occurred. + * if the peer is not created, then there is no + * need to send down the set link state which will + * try to delete the peer. Instead a join response + * failure should be sent to the upper layers. + */ + if (param->result_code != eSIR_SME_PEER_CREATE_FAILED) { + join_params *link_state_arg; + + link_state_arg = qdf_mem_malloc(sizeof(*link_state_arg)); + if (link_state_arg) { + link_state_arg->result_code = param->result_code; + link_state_arg->prot_status_code = + param->prot_status_code; + link_state_arg->pe_session_id = session->peSessionId; + } + if (lim_set_link_state(mac_ctx, eSIR_LINK_DOWN_STATE, + session->bssId, + session->selfMacAddr, + lim_join_result_callback, + link_state_arg) != QDF_STATUS_SUCCESS) { + qdf_mem_free(link_state_arg); + pe_err("Failed to set the LinkState"); + } + return QDF_STATUS_SUCCESS; + } + + + lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_JOIN_RSP, + param->result_code, + param->prot_status_code, + session, session->smeSessionId, + session->transactionId); + return QDF_STATUS_SUCCESS; +} + /** * lim_handle_sme_join_result() - Handles sme join result * @mac_ctx: Pointer to Global MAC structure @@ -1291,6 +1381,35 @@ static void lim_join_result_callback(tpAniSirGlobal mac, void *param, * * Return: None */ +void lim_handle_sme_join_result(tpAniSirGlobal mac_ctx, + tSirResultCodes result_code, uint16_t prot_status_code, + tpPESession session) +{ + join_params param; + QDF_STATUS status; + + if (!session) { + pe_err("session is NULL"); + return; + } + if (result_code == eSIR_SME_SUCCESS) + return lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_JOIN_RSP, + result_code, + prot_status_code, session, + session->smeSessionId, + session->transactionId); + + param.result_code = result_code; + param.prot_status_code = prot_status_code; + param.pe_session_id = session->peSessionId; + + 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); + return; +} +#else void lim_handle_sme_join_result(tpAniSirGlobal mac_ctx, tSirResultCodes result_code, uint16_t prot_status_code, tpPESession session_entry) @@ -1356,10 +1475,11 @@ error: param->prot_status_code = prot_status_code; param->pe_session_id = session_entry->peSessionId; } - if (lim_set_link_state - (mac_ctx, eSIR_LINK_DOWN_STATE, session_entry->bssId, - session_entry->selfMacAddr, lim_join_result_callback, - param) != QDF_STATUS_SUCCESS) { + if (lim_set_link_state(mac_ctx, eSIR_LINK_DOWN_STATE, + session_entry->bssId, + session_entry->selfMacAddr, + lim_join_result_callback, + param) != QDF_STATUS_SUCCESS) { qdf_mem_free(param); pe_err("Failed to set the LinkState"); } @@ -1369,6 +1489,8 @@ error: lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_JOIN_RSP, result_code, prot_status_code, session_entry, sme_session_id, sme_trans_id); } +#endif + /** * lim_process_mlm_add_sta_rsp() diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 57d5adfafb59..6f0b3712521f 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -775,6 +775,7 @@ void lim_covert_channel_scan_type(tpAniSirGlobal pMac, uint8_t channelNum, void lim_set_dfs_channel_list(tpAniSirGlobal pMac, uint8_t channelNum, tSirDFSChannelList *dfsChannelList); void limContinueChannelLearn(tpAniSirGlobal); +QDF_STATUS lim_sta_send_down_link(join_params *param); #ifdef WLAN_FEATURE_11W /* 11w send SA query request action frame */ diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 560643a2bd90..3ed43822e41c 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -8435,7 +8435,24 @@ QDF_STATUS lim_sta_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme, QDF_STATUS lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data) { - return lim_sta_send_del_bss((tpPESession)data); + QDF_STATUS status; + bool connection_fail; + + if (!data) { + pe_err("event_data is NULL"); + return QDF_STATUS_E_INVAL; + } + + connection_fail = mlme_is_connection_fail(vdev_mlme->vdev); + pe_info("Send vdev stop, connection_fail %d", connection_fail); + if (connection_fail) { + status = lim_sta_send_down_link((join_params *)data); + mlme_set_connection_fail(vdev_mlme->vdev, false); + } else { + status = lim_sta_send_del_bss((tpPESession)data); + } + + return status; } void lim_send_beacon(tpAniSirGlobal mac_ctx, tpPESession session) diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 44013dbc9f40..7308b3ee7f9b 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -504,7 +504,7 @@ QDF_STATUS wma_ap_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data); /** - * wma_ap_mlme_vdev_notify_down_complete - VDEV init state transition + * wma_mlme_vdev_notify_down_complete - VDEV init state transition * notification * @vdev_mlme_obj: VDEV MLME comp object * @data_len: data size @@ -516,8 +516,8 @@ QDF_STATUS wma_ap_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme, * FAILURE, if it fails due to any */ QDF_STATUS -wma_ap_mlme_vdev_notify_down_complete(struct vdev_mlme_obj *vdev_mlme, - uint16_t data_len, void *data); +wma_mlme_vdev_notify_down_complete(struct vdev_mlme_obj *vdev_mlme, + uint16_t data_len, void *data); /** * wma_ap_mlme_vdev_stop_start_send - handle vdev stop during start req diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index cee104dc0ca6..64ddf0eb7d4d 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -549,6 +549,15 @@ QDF_STATUS wma_create_peer(tp_wma_handle wma, struct cdp_pdev *pdev, */ void wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req); +/** + * wma_send_set_link_response() - send set link response + * @wma: wma handle + * @req: target request + * + * Return: none + */ +void wma_send_set_link_response(tp_wma_handle wma, struct wma_target_req *req); + /** * __wma_vdev_stop_resp_handler() - vdev stop response handler * @handle: wma handle diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index e61bf984fdcd..8109d882a5f5 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -2026,6 +2026,13 @@ wma_check_and_find_mcc_ap(tp_wma_handle wma, uint8_t vdev_id) {} #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ +void wma_send_set_link_response(tp_wma_handle wma, struct wma_target_req *req) +{ + tpLinkStateParams params = (tpLinkStateParams) req->user_data; + + wma_send_msg(wma, WMA_SET_LINK_STATE_RSP, (void *)params, 0); +} + void wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req) { struct wma_txrx_node *iface; @@ -2248,12 +2255,18 @@ __wma_vdev_stop_resp_handler(wmi_vdev_stopped_event_fixed_param *resp_event) } } } +#ifdef CONFIG_VDEV_SM + wlan_vdev_mlme_sm_deliver_evt(iface->vdev, + WLAN_VDEV_SM_EV_MLME_DOWN_REQ, + sizeof(*req_msg), req_msg); +#else if (wma_send_vdev_down_to_fw(wma, req_msg->vdev_id) != QDF_STATUS_SUCCESS) { WMA_LOGE("Failed to send vdev down cmd: vdev %d", req_msg->vdev_id); } - wma_send_msg(wma, WMA_SET_LINK_STATE_RSP, (void *)params, 0); + wma_send_set_link_response(wma, req_msg); +#endif } free_req_msg: @@ -3207,14 +3220,21 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info, data->generate_rsp); qdf_mem_free(data); } else if (req_msg->type == WMA_SET_LINK_PEER_RSP) { - tpLinkStateParams params = - (tpLinkStateParams) req_msg->user_data; +#ifdef CONFIG_VDEV_SM + struct wma_txrx_node *iface = + &wma->interfaces[req_msg->vdev_id]; + + wlan_vdev_mlme_sm_deliver_evt(iface->vdev, + WLAN_VDEV_SM_EV_MLME_DOWN_REQ, + sizeof(*req_msg), req_msg); +#else if (wma_send_vdev_down_to_fw(wma, req_msg->vdev_id) != QDF_STATUS_SUCCESS) { WMA_LOGE("Failed to send vdev down cmd: vdev %d", req_msg->vdev_id); } - wma_send_msg(wma, WMA_SET_LINK_STATE_RSP, (void *)params, 0); + wma_send_set_link_response(wma, req_msg); +#endif } else if (req_msg->type == WMA_DELETE_PEER_RSP) { #ifdef CONFIG_VDEV_SM struct wma_txrx_node *iface = diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 343ac3e14b5c..d440ceb0a122 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -4880,13 +4880,18 @@ QDF_STATUS wma_ap_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme, } QDF_STATUS -wma_ap_mlme_vdev_notify_down_complete(struct vdev_mlme_obj *vdev_mlme, - uint16_t data_len, void *data) +wma_mlme_vdev_notify_down_complete(struct vdev_mlme_obj *vdev_mlme, + uint16_t data_len, void *data) { tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); + struct wma_target_req *req = (struct wma_target_req *)data; if (!mlme_get_vdev_start_failed(vdev_mlme->vdev)) - wma_send_del_bss_response(wma, (struct wma_target_req *)data); + if (req->msg_type == WMA_SET_LINK_STATE || + req->type == WMA_SET_LINK_PEER_RSP) + wma_send_set_link_response(wma, req); + else + wma_send_del_bss_response(wma, req); else mlme_set_vdev_start_failed(vdev_mlme->vdev, false);