From c0954d33d7f8383dcaba10114ea7e0c9734a33ac Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Thu, 24 Dec 2020 11:56:31 +0530 Subject: [PATCH] qcacld-3.0: Allow switch to RSO STOP State while roam in progress Problem scenario: 1) Host gets roam event from FW and RSO state is switched to ROAM_IN_PROGRESS. 2) Host gets reassoc response followed by FW down indication. 3) Host processes reassoc response in HDD and sends disassoc to FW as FW down indication received. 4) As a part of disassoc host tries to switch RSO state to STOP. But as present RSO state is ROAM_IN_PROGRESS and FW is down, host fails to send RSO stop command to FW and doesn't switch RSO state to STOP. 5) Lim disassoc send fails due to FW is down and host proceeds with lim_send_disassoc_cnf and lim_cleanup_rx_path. 6) In lim_cleanup_rx_path() host checks for present RSO state is ROAM_IN_PROGRESS and returns without calling lim_del_sta(); 7) Thus peer delete and vdev delete is not send to FW and host vdev State machine stuck at SP-SUSPEND_DOWN which leads to peer and vdev reference leaks. Fix: Allow switch to RSO stop state while present RSO state is ROAM_IN_PROGRESS. Change-Id: I4a838ecd98a7ca377cd557d7a01a93ac53449595 CRs-Fixed: 2844647 --- .../core/src/wlan_cm_roam_offload.c | 45 ++++++++++--------- core/mac/src/pe/lim/lim_api.c | 2 +- core/mac/src/pe/lim/lim_assoc_utils.c | 43 +++--------------- core/mac/src/pe/lim/lim_assoc_utils.h | 24 +++++++++- .../src/pe/lim/lim_process_assoc_rsp_frame.c | 4 +- .../src/pe/lim/lim_process_mlm_host_roam.c | 2 +- .../src/pe/lim/lim_process_mlm_req_messages.c | 2 +- .../src/pe/lim/lim_process_mlm_rsp_messages.c | 2 +- .../src/pe/lim/lim_process_sme_req_messages.c | 2 +- .../src/pe/lim/lim_send_management_frames.c | 4 +- 10 files changed, 61 insertions(+), 69 deletions(-) diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c index 9841f99ba09e..cac8abaefa7c 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c @@ -556,6 +556,25 @@ cm_roam_stop_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, struct wlan_roam_stop_config *stop_req; QDF_STATUS status; + cm_roam_set_roam_reason_better_ap(psoc, vdev_id, false); + stop_req = qdf_mem_malloc(sizeof(*stop_req)); + if (!stop_req) + return QDF_STATUS_E_NOMEM; + + stop_req->btm_config.vdev_id = vdev_id; + stop_req->disconnect_params.vdev_id = vdev_id; + stop_req->idle_params.vdev_id = vdev_id; + stop_req->roam_triggers.vdev_id = vdev_id; + stop_req->rssi_params.vdev_id = vdev_id; + + /* do the filling as csr_post_rso_stop */ + status = wlan_cm_roam_fill_stop_req(psoc, vdev_id, stop_req, reason); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_debug("fail to fill stop config req"); + qdf_mem_free(stop_req); + return status; + } + /* * If roam synch propagation is in progress and an user space * disconnect is requested, then there is no need to send the @@ -577,29 +596,11 @@ cm_roam_stop_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, * and clean up. */ if (MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc, vdev_id) && - reason == REASON_ROAM_STOP_ALL) { + stop_req->reason == REASON_ROAM_STOP_ALL) { mlme_info("vdev_id:%d : Drop RSO stop during roam sync", vdev_id); - return QDF_STATUS_E_FAILURE; - } - - cm_roam_set_roam_reason_better_ap(psoc, vdev_id, false); - - stop_req = qdf_mem_malloc(sizeof(*stop_req)); - if (!stop_req) - return QDF_STATUS_E_NOMEM; - - stop_req->btm_config.vdev_id = vdev_id; - stop_req->disconnect_params.vdev_id = vdev_id; - stop_req->idle_params.vdev_id = vdev_id; - stop_req->roam_triggers.vdev_id = vdev_id; - stop_req->rssi_params.vdev_id = vdev_id; - - /* do the filling as csr_post_rso_stop */ - status = wlan_cm_roam_fill_stop_req(psoc, vdev_id, stop_req, reason); - if (QDF_IS_STATUS_ERROR(status)) { - mlme_debug("fail to fill stop config req"); - return status; + qdf_mem_free(stop_req); + return QDF_STATUS_SUCCESS; } status = wlan_cm_tgt_send_roam_stop_req(psoc, vdev_id, stop_req); @@ -613,7 +614,7 @@ cm_roam_stop_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, qdf_mem_free(stop_req); - return status; + return QDF_STATUS_SUCCESS; } /** diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index c7780922fdee..7fc32122a25f 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -2554,7 +2554,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, return status; } session_ptr->limSmeState = eLIM_SME_IDLE_STATE; - lim_cleanup_rx_path(mac_ctx, curr_sta_ds, session_ptr); + lim_cleanup_rx_path(mac_ctx, curr_sta_ds, session_ptr, false); lim_delete_dph_hash_entry(mac_ctx, curr_sta_ds->staAddr, aid, session_ptr); pe_delete_session(mac_ctx, session_ptr); diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index 8e0839af8ee5..7fa3a894ad44 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -378,46 +378,15 @@ QDF_STATUS lim_del_sta_all(struct mac_context *mac, return status; } -/** - * lim_cleanup_rx_path() - * - ***FUNCTION: - * This function is called to cleanup STA state at SP & RFP. - * - ***LOGIC: - * To circumvent RFP's handling of dummy packet when it does not - * have an incomplete packet for the STA to be deleted, a packet - * with 'more framgents' bit set will be queued to RFP's WQ before - * queuing 'dummy packet'. - * A 'dummy' BD is pushed into RFP's WQ with type=00, subtype=1010 - * (Disassociation frame) and routing flags in BD set to eCPU's - * Low Priority WQ. - * RFP cleans up its local context for the STA id mentioned in the - * BD and then pushes BD to eCPU's low priority WQ. - * - ***ASSUMPTIONS: - * NA - * - ***NOTE: - * NA - * - * @param mac Pointer to Global MAC structure - * @param sta Pointer to the per STA data structure - * initialized by LIM and maintained at DPH - * - * @return None - */ - QDF_STATUS lim_cleanup_rx_path(struct mac_context *mac, tpDphHashNode sta, - struct pe_session *pe_session) + struct pe_session *pe_session, bool delete_peer) { QDF_STATUS retCode = QDF_STATUS_SUCCESS; - pe_debug("Cleanup Rx Path for AID: %d" - "pe_session->limSmeState: %d, mlmState: %d", - sta->assocId, pe_session->limSmeState, - sta->mlmStaContext.mlmState); + pe_debug("Cleanup Rx Path for AID: %d limSmeState: %d, mlmState: %d, delete_peer %d", + sta->assocId, pe_session->limSmeState, + sta->mlmStaContext.mlmState, delete_peer); pe_session->isCiscoVendorAP = false; @@ -461,7 +430,7 @@ lim_cleanup_rx_path(struct mac_context *mac, tpDphHashNode sta, sta->valid = 0; lim_send_sme_tsm_ie_ind(mac, pe_session, 0, 0, 0); /* Any roaming related changes should be above this line */ - if (lim_is_roam_synch_in_progress(mac->psoc, pe_session)) + if (!delete_peer) return QDF_STATUS_SUCCESS; sta->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; @@ -743,7 +712,7 @@ lim_reject_association(struct mac_context *mac_ctx, tSirMacAddr peer_addr, sta_ds->mlmStaContext.cleanupTrigger = eLIM_REASSOC_REJECT; /* Receive path cleanup */ - lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry); + lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry, true); /* * Send Re/Association Response with diff --git a/core/mac/src/pe/lim/lim_assoc_utils.h b/core/mac/src/pe/lim/lim_assoc_utils.h index ee1dce6701f4..46af7218793e 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.h +++ b/core/mac/src/pe/lim/lim_assoc_utils.h @@ -44,8 +44,30 @@ uint8_t lim_compare_capabilities(struct mac_context *, tSirMacCapabilityInfo *, struct pe_session *); uint8_t lim_check_rx_basic_rates(struct mac_context *, tSirMacRateSet, struct pe_session *); uint8_t lim_check_mcs_set(struct mac_context *mac, uint8_t *supportedMCSSet); + +/** + * lim_cleanup_rx_path() - Called to cleanup STA state at SP & RFP. + * @mac: Pointer to Global MAC structure + * @sta: Pointer to the per STA data structure initialized by LIM + * and maintained at DPH + * @pe_session: pointer to pe session + * @delete_peer: is peer delete allowed + * + * To circumvent RFP's handling of dummy packet when it does not + * have an incomplete packet for the STA to be deleted, a packet + * with 'more framgents' bit set will be queued to RFP's WQ before + * queuing 'dummy packet'. + * A 'dummy' BD is pushed into RFP's WQ with type=00, subtype=1010 + * (Disassociation frame) and routing flags in BD set to eCPU's + * Low Priority WQ. + * RFP cleans up its local context for the STA id mentioned in the + * BD and then pushes BD to eCPU's low priority WQ. + * + * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE. + */ QDF_STATUS lim_cleanup_rx_path(struct mac_context *, tpDphHashNode, - struct pe_session *); + struct pe_session *, bool delete_peer); + void lim_reject_association(struct mac_context *, tSirMacAddr, uint8_t, uint8_t, tAniAuthType, uint16_t, uint8_t, enum wlan_status_code, struct pe_session *); diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index 95aba8b700e9..43358121c345 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -1017,8 +1017,8 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, session_entry->gUapsdPerAcDeliveryEnableMask = 0; session_entry->gUapsdPerAcTriggerEnableMask = 0; - if (lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry) - != QDF_STATUS_SUCCESS) { + if (lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry, + true) != QDF_STATUS_SUCCESS) { pe_err("Could not cleanup the rx path"); goto assocReject; } 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 567681f38577..47b8d0d9027c 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 @@ -187,7 +187,7 @@ static void lim_handle_sme_reaasoc_result(struct mac_context *mac, eLIM_JOIN_FAILURE; sta->mlmStaContext.resultCode = resultCode; sta->mlmStaContext.protStatusCode = protStatusCode; - lim_cleanup_rx_path(mac, sta, pe_session); + lim_cleanup_rx_path(mac, sta, pe_session, true); /* Cleanup if add bss failed */ if (pe_session->add_bss_failed) { dph_delete_hash_entry(mac, diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index c774642d382c..9445e6fe3084 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1088,7 +1088,7 @@ lim_process_mlm_disassoc_req_ntf(struct mac_context *mac_ctx, send_disassoc_frame = 1; /* Receive path cleanup with dummy packet */ if (QDF_STATUS_SUCCESS != - lim_cleanup_rx_path(mac_ctx, stads, session)) { + lim_cleanup_rx_path(mac_ctx, stads, session, true)) { mlm_disassoccnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; 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 be58ca2a859e..03cc94dad287 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 @@ -1281,7 +1281,7 @@ QDF_STATUS lim_sta_handle_connect_fail(join_params *param) * make sure PE is sending eWNI_SME_JOIN_RSP * to SME */ - lim_cleanup_rx_path(mac_ctx, sta_ds, session); + lim_cleanup_rx_path(mac_ctx, sta_ds, session, true); qdf_mem_free(session->lim_join_req); session->lim_join_req = NULL; /* Cleanup if add bss failed */ diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 7dcf96cdca25..476e91d05438 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2306,7 +2306,7 @@ void __lim_process_sme_disassoc_cnf(struct mac_context *mac, uint32_t *msg_buf) /* Delete FT session if there exists one */ lim_ft_cleanup_pre_auth_info(mac, pe_session); - lim_cleanup_rx_path(mac, sta, pe_session); + lim_cleanup_rx_path(mac, sta, pe_session, true); lim_clean_up_disassoc_deauth_req(mac, (char *)&smeDisassocCnf.peer_macaddr, 0); diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 456eacd6be23..6059e3e5797c 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -3178,7 +3178,7 @@ QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac_ctx) /* / Receive path cleanup with dummy packet */ lim_ft_cleanup_pre_auth_info(mac_ctx, session_entry); - lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry); + lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry, true); if ((session_entry->limSystemRole == eLIM_STA_ROLE) && ( #ifdef FEATURE_WLAN_ESE @@ -3282,7 +3282,7 @@ QDF_STATUS lim_send_disassoc_cnf(struct mac_context *mac_ctx) } /* Receive path cleanup with dummy packet */ if (QDF_STATUS_SUCCESS != - lim_cleanup_rx_path(mac_ctx, sta_ds, pe_session)) { + lim_cleanup_rx_path(mac_ctx, sta_ds, pe_session, true)) { disassoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; pe_err("cleanup_rx_path error");