Browse Source

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
Abhishek Singh 5 years ago
parent
commit
8586573201

+ 20 - 0
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,

+ 10 - 4
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), &param);
+
+		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), &param);
+		else
+			status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
+						WLAN_VDEV_SM_EV_CONNECTION_FAIL,
+						sizeof(param), &param);
 	}
 
 	if (session->pLimReAssocReq) {

+ 13 - 2
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), &param);
+	else
+		status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
 					       WLAN_VDEV_SM_EV_CONNECTION_FAIL,
 					       sizeof(param), &param);
+
 	return;
 }
 

+ 7 - 1
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);

+ 36 - 1
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) ==

+ 14 - 0
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

+ 6 - 0
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__);