Bläddra i källkod

qcacld-3.0: Handle error cases in ipa_uc_loaded_handler

In the scenario where ipa connect pipes fails in the
wlan_ipa_uc_loaded_handler API, uc_loaded flag is not
reset. As a result of this, in wlan_ipa_uc_ol_deinit,
ipa_tx_buf_smmu_unmap and ipa_wdi_disconn_pipes APIs are
invoked incorrectly.

Fix is to set the uc_loaded flag to true only if connect
pipes and tx_smmu mappings are successful in
wlan_ipa_uc_loaded_handler. Also, initialize the uc_op_work
in wlan_ipa_uc_ol_init prior to the uc_loaded check to
avoid a possible race condition which could also result
in the similar issue as above.

Change-Id: I119170413cb9b5e03ec476c9a69d9effaa460c01
CRs-Fixed: 2940833
Yeshwanth Sriram Guntuka 3 år sedan
förälder
incheckning
553ec8e0a4
1 ändrade filer med 23 tillägg och 11 borttagningar
  1. 23 11
      components/ipa/core/src/wlan_ipa_core.c

+ 23 - 11
components/ipa/core/src/wlan_ipa_core.c

@@ -3707,7 +3707,6 @@ static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
 		ipa_info("UC already loaded");
 		return;
 	}
-	ipa_ctx->uc_loaded = true;
 
 	if (!qdf_dev) {
 		ipa_err("qdf_dev is null");
@@ -3730,7 +3729,7 @@ static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
 	if (status) {
 		ipa_err("Failure to setup IPA pipes (status=%d)",
 			status);
-		return;
+		goto connect_pipe_fail;
 	}
 	/* Setup the Tx buffer SMMU mapings */
 	status = cdp_ipa_tx_buf_smmu_mapping(ipa_ctx->dp_soc,
@@ -3738,7 +3737,7 @@ static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
 	if (status) {
 		ipa_err("Failure to map Tx buffers for IPA(status=%d)",
 			status);
-		return;
+		goto smmu_map_fail;
 	}
 	ipa_info("TX buffers mapped to IPA");
 	cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id);
@@ -3758,6 +3757,19 @@ static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
 		ipa_debug("Client already connected, enable IPA/FW PIPEs");
 		wlan_ipa_uc_handle_first_con(ipa_ctx);
 	}
+
+	ipa_ctx->uc_loaded = true;
+
+	return;
+
+smmu_map_fail:
+	qdf_ipa_wdi_disconn_pipes();
+
+connect_pipe_fail:
+	if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
+		qdf_cancel_work(&ipa_ctx->mcc_work);
+		wlan_ipa_teardown_sys_pipe(ipa_ctx);
+	}
 }
 
 /**
@@ -3977,6 +3989,14 @@ QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
 		goto fail_return;
 	}
 
+	for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
+		ipa_ctx->uc_op_work[i].osdev = osdev;
+		ipa_ctx->uc_op_work[i].msg = NULL;
+		qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
+				wlan_ipa_uc_fw_op_event_handler,
+				&ipa_ctx->uc_op_work[i]);
+	}
+
 	if (true == ipa_ctx->uc_loaded) {
 		status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
 		if (status) {
@@ -4003,14 +4023,6 @@ QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
 			ipa_err("Failed to init perf level");
 	}
 
-	for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
-		ipa_ctx->uc_op_work[i].osdev = osdev;
-		qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
-				wlan_ipa_uc_fw_op_event_handler,
-				&ipa_ctx->uc_op_work[i]);
-		ipa_ctx->uc_op_work[i].msg = NULL;
-	}
-
 	cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id,
 			       wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
 fail_return: