Эх сурвалжийг харах

qcacld-3.0: Update LFR2 self reassoc failure processing

Update LFR2 self reassoc failure processing:
1. remove lim_send_switch_chnl_params() from
lim_restore_pre_reassoc_state() when self reassoc failure
to avoid this race condition: one one hand host let FW do
restart, and on the other hand VDEV sm transition to stop
state. Otherwise VDEV sm cannot handle EV_START_RESP event
correcly.
2. register .mlme_vdev_sta_disconn_start callback with
cleanupTrigger eLIM_HOST_DISASSOC.
3. when self reassoc fail, notify reassoc failure reason
to CM SM so that CM SM can trigger CM_DISCONNECT_REQ, then
invoke .mlme_vdev_sta_disconn_start doing cleanup action.

Change-Id: Icb68202e9f72fcbe3e0e4d3e9006a65a73123692
CRs-Fixed: 3109987
Qun Zhang 3 жил өмнө
parent
commit
eed1953b12

+ 24 - 0
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -347,6 +347,27 @@ static QDF_STATUS sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
 	return lim_sta_mlme_vdev_stop_send(vdev_mlme, data_len, data);
 }
 
+/**
+ * sta_mlme_vdev_sta_disconnect_start() - MLME vdev disconnect send callback
+ * @vdev_mlme: vdev mlme object
+ * @event_data_len: event data length
+ * @event_data: event data
+ *
+ * This function is called to trigger the vdev stop to firmware when
+ * reassoc failure
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+sta_mlme_vdev_sta_disconnect_start(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_sta_disconnect_start(vdev_mlme, data_len,
+						      data);
+}
+
 /**
  * vdevmgr_mlme_stop_continue() - MLME vdev stop send callback
  * @vdev_mlme: vdev mlme object
@@ -1812,6 +1833,8 @@ static QDF_STATUS ap_mlme_vdev_csa_complete(struct vdev_mlme_obj *vdev_mlme)
  *                                      MLME down operation
  * @mlme_vdev_notify_down_complete:     callback to notify VDEV MLME on moving
  *                                      to INIT state
+ * @mlme_vdev_sta_disconn_start         callback to trigger vdev stop to
+ *                                      firmware when resaaoc failure
  */
 static struct vdev_mlme_ops sta_mlme_ops = {
 	.mlme_vdev_start_send = sta_mlme_vdev_start_send,
@@ -1829,6 +1852,7 @@ static struct vdev_mlme_ops sta_mlme_ops = {
 	.mlme_vdev_notify_down_complete = vdevmgr_notify_down_complete,
 	.mlme_vdev_ext_stop_rsp = vdevmgr_vdev_stop_rsp_handle,
 	.mlme_vdev_ext_start_rsp = vdevmgr_vdev_start_rsp_handle,
+	.mlme_vdev_sta_disconn_start = sta_mlme_vdev_sta_disconnect_start,
 };
 
 /**

+ 2 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c

@@ -1141,7 +1141,8 @@ QDF_STATUS wlan_cm_send_connect_rsp(struct scheduler_msg *msg)
 	}
 
 	/*  check and delete bss peer in case of failure */
-	if (QDF_IS_STATUS_ERROR(rsp->connect_rsp.connect_status)) {
+	if (QDF_IS_STATUS_ERROR(rsp->connect_rsp.connect_status) &&
+	    (wlan_vdev_mlme_is_init_state(vdev) == QDF_STATUS_SUCCESS)) {
 		peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
 							WLAN_MLME_CM_ID);
 		if (peer) {

+ 18 - 4
core/mac/src/pe/lim/lim_process_mlm_host_roam.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -229,6 +230,7 @@ void lim_process_mlm_reassoc_cnf(struct mac_context *mac_ctx, uint32_t *msg_buf)
 	tLimMlmReassocCnf *lim_mlm_reassoc_cnf;
 	struct reassoc_params param;
 	QDF_STATUS status;
+	enum wlan_vdev_state sub_state;
 
 	if (!msg_buf) {
 		pe_err("Buffer is Pointing to NULL");
@@ -279,8 +281,9 @@ void lim_process_mlm_reassoc_cnf(struct mac_context *mac_ctx, uint32_t *msg_buf)
 	}
 #endif
 
-	pe_debug("Rcv MLM_REASSOC_CNF with result code: %d",
-		 lim_mlm_reassoc_cnf->resultCode);
+	sub_state = wlan_vdev_mlme_get_substate(session->vdev);
+	pe_debug("Rcv MLM_REASSOC_CNF with result code: %d vdev SS %d",
+		 lim_mlm_reassoc_cnf->resultCode, sub_state);
 	if (lim_mlm_reassoc_cnf->resultCode == eSIR_SME_SUCCESS) {
 		/* Successful Reassociation */
 		pe_debug("*** Reassociated with new BSS ***");
@@ -300,6 +303,18 @@ void lim_process_mlm_reassoc_cnf(struct mac_context *mac_ctx, uint32_t *msg_buf)
 					lim_mlm_reassoc_cnf->resultCode,
 					lim_mlm_reassoc_cnf->protStatusCode,
 					session, session->smeSessionId);
+	} else if (sub_state == WLAN_VDEV_SS_START_CONN_PROGRESS ||
+		   sub_state == WLAN_VDEV_SS_START_RESTART_PROGRESS) {
+		session->limSmeState = eLIM_SME_LINK_EST_STATE;
+		/*
+		 * Need to send Reassoc rsp with re-Assoc failure to CM
+		 * so that disconnect can be initiated.
+		 */
+		lim_send_sme_join_reassoc_rsp(
+					mac_ctx, eWNI_SME_REASSOC_RSP,
+					lim_mlm_reassoc_cnf->resultCode,
+					lim_mlm_reassoc_cnf->protStatusCode,
+					session, session->smeSessionId);
 	} else {
 		param.result_code = lim_mlm_reassoc_cnf->resultCode;
 		param.prot_status_code = lim_mlm_reassoc_cnf->protStatusCode;
@@ -307,8 +322,7 @@ void lim_process_mlm_reassoc_cnf(struct mac_context *mac_ctx, uint32_t *msg_buf)
 
 		mlme_set_connection_fail(session->vdev, true);
 
-		if (wlan_vdev_mlme_get_substate(session->vdev) ==
-		    WLAN_VDEV_SS_START_START_PROGRESS)
+		if (sub_state == WLAN_VDEV_SS_START_START_PROGRESS)
 			status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
 						WLAN_VDEV_SM_EV_START_REQ_FAIL,
 						sizeof(param), &param);

+ 1 - 2
core/mac/src/pe/lim/lim_reassoc_utils.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -469,8 +470,6 @@ lim_restore_pre_reassoc_state(struct mac_context *mac,
 	/* 'Change' timer for future activations */
 	lim_deactivate_and_change_timer(mac, eLIM_REASSOC_FAIL_TIMER);
 
-	lim_send_switch_chnl_params(mac, pe_session);
-
 	/* @ToDo:Need to Integrate the STOP the Dataxfer to AP from 11H code */
 
 	mlmReassocCnf.resultCode = resultCode;

+ 39 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -9272,6 +9272,45 @@ QDF_STATUS lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
 	return status;
 }
 
+QDF_STATUS
+lim_sta_mlme_vdev_sta_disconnect_start(struct vdev_mlme_obj *vdev_mlme,
+				       uint16_t data_len, void *data)
+{
+	tpDphHashNode stads;
+	struct pe_session *session;
+	struct mac_context *mac_ctx;
+	uint8_t vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
+
+	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
+	if (!mac_ctx)
+		return QDF_STATUS_E_INVAL;
+
+	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
+	if (!session) {
+		pe_err("session is NULL for vdevid %d", vdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+	stads = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+				   &session->dph.dphHashTable);
+	if (!stads)
+		return QDF_STATUS_E_INVAL;
+	mlme_set_connection_fail(vdev_mlme->vdev, false);
+
+	session->limPrevSmeState = session->limSmeState;
+	session->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
+
+	stads->mlmStaContext.disassocReason = REASON_UNSPEC_FAILURE;
+	stads->mlmStaContext.cleanupTrigger = eLIM_HOST_DISASSOC;
+
+	stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
+
+	wlan_vdev_mlme_sm_deliver_evt(session->vdev,
+				      WLAN_VDEV_SM_EV_CONNECTION_FAIL,
+				      sizeof(*session), session);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS lim_sta_mlme_vdev_req_fail(struct vdev_mlme_obj *vdev_mlme,
 				      uint16_t data_len, void *data)
 {

+ 15 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -2598,6 +2598,21 @@ QDF_STATUS lim_ap_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
 QDF_STATUS lim_ap_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
 					 uint16_t data_len, void *data);
 
+/**
+ * lim_ap_mlme_vdev_restart_send - Invokes VDEV sta disconnect operation
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ * @data_len: data size
+ * @data: event data
+ *
+ * API invokes VDEV sta disconnect operation
+ *
+ * Return: SUCCESS on successful completion of sta disconnect operation
+ *         FAILURE, if it fails due to any
+ */
+QDF_STATUS
+lim_sta_mlme_vdev_sta_disconnect_start(struct vdev_mlme_obj *vdev_mlme,
+				       uint16_t data_len, void *data);
+
 /**
  * lim_ap_mlme_vdev_start_req_failed - handle vdev start req failure
  * @vdev_mlme_obj:  VDEV MLME comp object

+ 9 - 1
core/wma/src/wma_utils.c

@@ -4479,11 +4479,19 @@ wma_mlme_vdev_notify_down_complete(struct vdev_mlme_obj *vdev_mlme,
 	status = mlme_get_vdev_stop_type(wma->interfaces[resp->vdev_id].vdev,
 					 &vdev_stop_type);
 	if (QDF_IS_STATUS_ERROR(status)) {
-		wma_err("Failed to get msg_type");
+		wma_err("Failed to get vdev stop type for vdev_id: %d",
+			resp->vdev_id);
 		status = QDF_STATUS_E_INVAL;
 		goto end;
 	}
 
+	/*
+	 * Need reset vdev_stop_type to 0 here, otherwise the vdev_stop_type
+	 * would be taken to next BSS stop in some stress test, then cause
+	 * unexpected behavior.
+	 */
+	mlme_set_vdev_stop_type(wma->interfaces[resp->vdev_id].vdev, 0);
+
 	if (vdev_stop_type == WMA_DELETE_BSS_HO_FAIL_REQ) {
 		resp->status = QDF_STATUS_SUCCESS;
 		wma_send_msg_high_priority(wma, WMA_DELETE_BSS_HO_FAIL_RSP,