Browse Source

qcacld-3.0: Cleanup VDEV SM on roam sync failure

Upon roam sync handling failure, host driver is expected
to do cleanup of the VDEV/CM SM and move it to INIT state.
However, if the roam sync handling fails in PE, then the
VDEV SM is not properly cleaned up and gets stuck in
SUSPEND-DOWN state.

This happens because the smestate of the new session that
has been created/attached to the VDEV is in IDLE state.
This leads to failure in the disassoc request handling.

To fix this, retain the old session/sta ds until the
PE roam sync handling is successful.
a) Delete the old session if handling is successful.
b) Delete the new session if handling is failure.

Change-Id: I68871890a40775afdd60be197aa53863f94926ba
CRs-Fixed: 3476826
Surya Prakash Sivaraj 1 year ago
parent
commit
fca1279b15
1 changed files with 36 additions and 19 deletions
  1. 36 19
      core/mac/src/pe/lim/lim_api.c

+ 36 - 19
core/mac/src/pe/lim/lim_api.c

@@ -2874,7 +2874,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx,
 	struct pe_session *ft_session_ptr;
 	uint8_t session_id;
 	uint8_t *reassoc_resp;
-	tpDphHashNode curr_sta_ds;
+	tpDphHashNode curr_sta_ds = NULL, sta_ds = NULL;
 	uint16_t aid;
 	struct bss_params *add_bss_params;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
@@ -3012,28 +3012,17 @@ pe_roam_synch_callback(struct mac_context *mac_ctx,
 	wlan_tdls_notify_sta_disconnect(vdev_id, true,
 					false, session_ptr->vdev);
 
-	curr_sta_ds = dph_lookup_hash_entry(mac_ctx, session_ptr->bssId, &aid,
-					    &session_ptr->dph.dphHashTable);
-	if (!curr_sta_ds && !is_multi_link_roam(roam_sync_ind_ptr)) {
+	sta_ds = dph_lookup_hash_entry(mac_ctx, session_ptr->bssId, &aid,
+				       &session_ptr->dph.dphHashTable);
+	if (!sta_ds && !is_multi_link_roam(roam_sync_ind_ptr)) {
 		pe_err("LFR3:failed to lookup hash entry");
 		ft_session_ptr->bRoamSynchInProgress = false;
-		return status;
-	}
-
-	session_ptr->limSmeState = eLIM_SME_IDLE_STATE;
-	if (curr_sta_ds) {
-		lim_mlo_notify_peer_disconn(session_ptr, curr_sta_ds);
-		lim_mlo_roam_delete_link_peer(session_ptr, curr_sta_ds);
-		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);
+		goto roam_sync_fail;
 	}
 
 	/* update OBSS scan param */
 	pe_roam_fill_obss_scan_param(session_ptr, ft_session_ptr);
 
-	pe_delete_session(mac_ctx, session_ptr);
-	session_ptr = NULL;
 	curr_sta_ds = dph_add_hash_entry(mac_ctx,
 					 bssid.bytes,
 					 DPH_STA_HASH_INDEX_PEER,
@@ -3042,7 +3031,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx,
 		pe_err("LFR3:failed to add hash entry for "QDF_MAC_ADDR_FMT,
 		       QDF_MAC_ADDR_REF(add_bss_params->staContext.staMac));
 		ft_session_ptr->bRoamSynchInProgress = false;
-		return status;
+		goto roam_sync_fail;
 	}
 
 	if (roam_sync_ind_ptr->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED)
@@ -3060,7 +3049,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx,
 						reassoc_resp,
 						roam_sync_ind_ptr->reassoc_resp_length);
 		if (QDF_IS_STATUS_ERROR(status))
-			return status;
+			goto roam_sync_fail;
 	}
 	else
 		lim_process_assoc_rsp_frame(mac_ctx, reassoc_resp,
@@ -3090,7 +3079,8 @@ pe_roam_synch_callback(struct mac_context *mac_ctx,
 				qdf_mem_malloc(ric_tspec_len);
 		if (!roam_sync_ind_ptr->ric_tspec_data) {
 			ft_session_ptr->bRoamSynchInProgress = false;
-			return QDF_STATUS_E_NOMEM;
+			status = QDF_STATUS_E_NOMEM;
+			goto roam_sync_fail;
 		}
 
 		if (ft_session_ptr->ricData) {
@@ -3122,7 +3112,34 @@ pe_roam_synch_callback(struct mac_context *mac_ctx,
 	ft_session_ptr->limSmeState = eLIM_SME_LINK_EST_STATE;
 	ft_session_ptr->limPrevSmeState = ft_session_ptr->limSmeState;
 	ft_session_ptr->bRoamSynchInProgress = false;
+
+	/* Cleanup the old session */
+	session_ptr->limSmeState = eLIM_SME_IDLE_STATE;
+	if (sta_ds) {
+		lim_mlo_notify_peer_disconn(session_ptr, sta_ds);
+		lim_mlo_roam_delete_link_peer(session_ptr, sta_ds);
+		lim_cleanup_rx_path(mac_ctx, sta_ds, session_ptr, false);
+		lim_delete_dph_hash_entry(mac_ctx, sta_ds->staAddr, aid,
+					  session_ptr);
+	}
+	pe_delete_session(mac_ctx, session_ptr);
 	return QDF_STATUS_SUCCESS;
+
+roam_sync_fail:
+	pe_err("Roam sync failure status %d session vdev %d", status,
+	       session_ptr->vdev_id);
+	/*
+	 * Cleanup the new session upon roam sync failure.
+	 * Retain the old session for graceful HO failure handling.
+	 */
+	if (curr_sta_ds) {
+		lim_cleanup_rx_path(mac_ctx, curr_sta_ds, ft_session_ptr,
+				    false);
+		lim_delete_dph_hash_entry(mac_ctx, curr_sta_ds->staAddr,
+					  curr_sta_ds->assocId, ft_session_ptr);
+	}
+	pe_delete_session(mac_ctx, ft_session_ptr);
+	return status;
 }
 #endif