Browse Source

msm: ipa: ulso wa fixes

ULSO WA cannot be used with full pipeline clear option in same chain.
Avoid using it as it can result in HW stalls.

Also make sure to use ULSO WA whenever we send force close
on coalescing pipe to avoid HW stalls.

Change-Id: Ie81d885f82b201d35cd1832a3a87313c37da76b8
Signed-off-by: Chaitanya Pratapa <[email protected]>
Chaitanya Pratapa 3 years ago
parent
commit
7cfc02d8c0

+ 8 - 10
drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c

@@ -451,8 +451,6 @@ static void ipa_close_coal_frame(struct ipahal_imm_cmd_pyld **coal_cmd_pyld)
 	struct ipahal_imm_cmd_register_write reg_write_coal_close;
 	u32 offset = 0;
 
-	if (ipa3_ctx->ulso_wa)
-		return;
 	i = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS);
 	reg_write_coal_close.skip_pipeline_clear = false;
 	reg_write_coal_close.pipeline_clear_options = IPAHAL_HPS_CLEAR;
@@ -547,7 +545,7 @@ int ipa_init_quota_stats(u32 *pipe_bitmask)
 
 	/* IC to close the coal frame before HPS Clear if coal is enabled */
 	ipa_ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS);
-	if (ipa_ep_idx != IPA_EP_NOT_ALLOCATED) {
+	if (ipa_ep_idx != IPA_EP_NOT_ALLOCATED && !ipa3_ctx->ulso_wa) {
 		ipa_close_coal_frame(&coal_cmd_pyld);
 		if (!coal_cmd_pyld) {
 			IPAERR("failed to construct coal close IC\n");
@@ -718,7 +716,7 @@ int ipa_get_quota_stats(struct ipa_quota_stats_all *out)
 
 	/* IC to close the coal frame before HPS Clear if coal is enabled */
 	if (ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS) !=
-		IPA_EP_NOT_ALLOCATED) {
+		IPA_EP_NOT_ALLOCATED && !ipa3_ctx->ulso_wa) {
 		ipa_close_coal_frame(&cmd_pyld[num_cmd]);
 		if (!cmd_pyld[num_cmd]) {
 			IPAERR("failed to construct coal close IC\n");
@@ -942,7 +940,7 @@ int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in)
 
 	/* IC to close the coal frame before HPS Clear if coal is enabled */
 	if (ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS) !=
-		IPA_EP_NOT_ALLOCATED) {
+		IPA_EP_NOT_ALLOCATED && !ipa3_ctx->ulso_wa) {
 		ipa_close_coal_frame(&coal_cmd_pyld);
 		if (!coal_cmd_pyld) {
 			IPAERR("failed to construct coal close IC\n");
@@ -1126,7 +1124,7 @@ int ipa_get_teth_stats(void)
 
 	/* IC to close the coal frame before HPS Clear if coal is enabled */
 	if (ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS) !=
-		IPA_EP_NOT_ALLOCATED) {
+		IPA_EP_NOT_ALLOCATED && !ipa3_ctx->ulso_wa) {
 		ipa_close_coal_frame(&cmd_pyld[num_cmd]);
 		if (!cmd_pyld[num_cmd]) {
 			IPAERR("failed to construct coal close IC\n");
@@ -1423,7 +1421,7 @@ int ipa_init_flt_rt_stats(void)
 
 	/* IC to close the coal frame before HPS Clear if coal is enabled */
 	if (ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS) !=
-		IPA_EP_NOT_ALLOCATED) {
+		IPA_EP_NOT_ALLOCATED && !ipa3_ctx->ulso_wa) {
 		ipa_close_coal_frame(&coal_cmd_pyld);
 		if (!coal_cmd_pyld) {
 			IPAERR("failed to construct coal close IC\n");
@@ -1622,7 +1620,7 @@ static int __ipa_get_flt_rt_stats(struct ipa_ioc_flt_rt_query *query)
 
 	/* IC to close the coal frame before HPS Clear if coal is enabled */
 	if (ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS) !=
-		IPA_EP_NOT_ALLOCATED) {
+		IPA_EP_NOT_ALLOCATED && !ipa3_ctx->ulso_wa) {
 		ipa_close_coal_frame(&cmd_pyld[num_cmd]);
 		if (!cmd_pyld[num_cmd]) {
 			IPAERR("failed to construct coal close IC\n");
@@ -1925,7 +1923,7 @@ int ipa_init_drop_stats(u32 *pipe_bitmask)
 
 	/* IC to close the coal frame before HPS Clear if coal is enabled */
 	if (ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS) !=
-		IPA_EP_NOT_ALLOCATED) {
+		IPA_EP_NOT_ALLOCATED && !ipa3_ctx->ulso_wa) {
 		ipa_close_coal_frame(&coal_cmd_pyld);
 		if (!coal_cmd_pyld) {
 			IPAERR("failed to construct coal close IC\n");
@@ -2097,7 +2095,7 @@ int ipa_get_drop_stats(struct ipa_drop_stats_all *out)
 
 	/* IC to close the coal frame before HPS Clear if coal is enabled */
 	if (ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS) !=
-		IPA_EP_NOT_ALLOCATED) {
+		IPA_EP_NOT_ALLOCATED && !ipa3_ctx->ulso_wa) {
 		ipa_close_coal_frame(&cmd_pyld[num_cmd]);
 		if (!cmd_pyld[num_cmd]) {
 			IPAERR("failed to construct coal close IC\n");

+ 2 - 1
drivers/platform/msm/ipa/ipa_v3/ipa_i.h

@@ -2290,7 +2290,8 @@ struct ipa3_context {
 	u32 icc_num_cases;
 	u32 icc_num_paths;
 	u32 icc_clk[IPA_ICC_LVL_MAX][IPA_ICC_PATH_MAX][IPA_ICC_TYPE_MAX];
-	struct ipahal_imm_cmd_pyld *coal_cmd_pyld;
+	struct ipahal_imm_cmd_pyld *coal_cmd_pyld[2];
+	struct ipa_mem_buffer ulso_wa_cmd;
 	u32 tx_wrapper_cache_max_size;
 	struct ipa3_app_clock_vote app_clock_vote;
 	bool clients_registered;

+ 75 - 24
drivers/platform/msm/ipa/ipa_v3/ipa_utils.c

@@ -9628,17 +9628,20 @@ int ipa3_tag_process(struct ipa3_desc desc[],
 	}
 
 	/* NO-OP IC for ensuring that IPA pipeline is empty */
-	cmd_pyld = ipahal_construct_nop_imm_cmd(
-		false, IPAHAL_FULL_PIPELINE_CLEAR, false);
-	if (!cmd_pyld) {
-		IPAERR("failed to construct NOP imm cmd\n");
-		res = -ENOMEM;
-		goto fail_free_desc;
+	if (!ipa3_ctx->ulso_wa)
+	{
+		cmd_pyld = ipahal_construct_nop_imm_cmd(
+			false, IPAHAL_FULL_PIPELINE_CLEAR, false);
+		if (!cmd_pyld) {
+			IPAERR("failed to construct NOP imm cmd\n");
+			res = -ENOMEM;
+			goto fail_free_desc;
+		}
+		ipa3_init_imm_cmd_desc(&tag_desc[desc_idx], cmd_pyld);
+		tag_desc[desc_idx].callback = ipa3_tag_destroy_imm;
+		tag_desc[desc_idx].user1 = cmd_pyld;
+		++desc_idx;
 	}
-	ipa3_init_imm_cmd_desc(&tag_desc[desc_idx], cmd_pyld);
-	tag_desc[desc_idx].callback = ipa3_tag_destroy_imm;
-	tag_desc[desc_idx].user1 = cmd_pyld;
-	++desc_idx;
 
 	/* IP_PACKET_INIT IC for tag status to be sent to apps */
 	pktinit_cmd.destination_pipe_index =
@@ -9803,6 +9806,10 @@ static int ipa3_tag_generate_force_close_desc(struct ipa3_desc desc[],
 		ipahal_read_reg_n_fields(IPA_ENDP_INIT_AGGR_n, i, &ep_aggr);
 		if (!ep_aggr.aggr_en)
 			continue;
+		/* Skip Coalescing pipe when ulso wa is enabled. */
+		if (ipa3_ctx->ulso_wa &&
+			(i == ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS)))
+			continue;
 		IPADBG("Force close ep: %d\n", i);
 		if (desc_idx + 1 > desc_size) {
 			IPAERR("Internal error - no descriptors\n");
@@ -9810,9 +9817,14 @@ static int ipa3_tag_generate_force_close_desc(struct ipa3_desc desc[],
 			goto fail_no_desc;
 		}
 
-		reg_write_agg_close.skip_pipeline_clear = false;
-		reg_write_agg_close.pipeline_clear_options =
-			IPAHAL_FULL_PIPELINE_CLEAR;
+		if (!ipa3_ctx->ulso_wa) {
+			reg_write_agg_close.skip_pipeline_clear = false;
+			reg_write_agg_close.pipeline_clear_options =
+				IPAHAL_FULL_PIPELINE_CLEAR;
+		} else {
+			reg_write_agg_close.skip_pipeline_clear = true;
+		}
+
 		if (ipa3_ctx->ipa_hw_type < IPA_HW_v5_0)
 			offset = ipahal_get_reg_ofst(
 				IPA_AGGR_FORCE_CLOSE);
@@ -11048,17 +11060,21 @@ static int _ipa_suspend_resume_pipe(enum ipa_client_type client, bool suspend)
 
 void ipa3_force_close_coal(void)
 {
-	struct ipa3_desc desc;
-	int ep_idx;
+	struct ipa3_desc desc[2];
+	int ep_idx, num_desc = 0;
 
 	ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS);
 	if (ep_idx == IPA_EP_NOT_ALLOCATED || (!ipa3_ctx->ep[ep_idx].valid))
 		return;
 
-	ipa3_init_imm_cmd_desc(&desc, ipa3_ctx->coal_cmd_pyld);
-
-	IPADBG("Sending 1 descriptor for coal force close\n");
-	if (ipa3_send_cmd(1, &desc))
+	ipa3_init_imm_cmd_desc(&desc[0], ipa3_ctx->coal_cmd_pyld[0]);
+	num_desc++;
+	if (ipa3_ctx->ulso_wa) {
+		ipa3_init_imm_cmd_desc(&desc[1], ipa3_ctx->coal_cmd_pyld[1]);
+		num_desc++;
+	}
+	IPADBG("Sending %d descriptor for coal force close\n", num_desc);
+	if (ipa3_send_cmd(num_desc, desc))
 		IPADBG("ipa3_send_cmd timedout\n");
 }
 
@@ -11231,6 +11247,7 @@ void ipa3_free_dma_task_for_gsi(void)
 int ipa3_allocate_coal_close_frame(void)
 {
 	struct ipahal_imm_cmd_register_write reg_write_cmd = { 0 };
+	struct ipahal_imm_cmd_register_read dummy_reg_read = { 0 };
 	struct ipahal_reg_valmask valmask;
 	int ep_idx;
 	u32 offset = 0;
@@ -11240,7 +11257,11 @@ int ipa3_allocate_coal_close_frame(void)
 		return 0;
 	IPADBG("Allocate coal close frame cmd\n");
 	reg_write_cmd.skip_pipeline_clear = false;
-	reg_write_cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
+	if (ipa3_ctx->ulso_wa) {
+		reg_write_cmd.pipeline_clear_options = IPAHAL_SRC_GRP_CLEAR;
+	} else {
+		reg_write_cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
+	}
 	if (ipa3_ctx->ipa_hw_type < IPA_HW_v5_0)
 		offset = ipahal_get_reg_ofst(
 			IPA_AGGR_FORCE_CLOSE);
@@ -11251,22 +11272,52 @@ int ipa3_allocate_coal_close_frame(void)
 	ipahal_get_aggr_force_close_valmask(ep_idx, &valmask);
 	reg_write_cmd.value = valmask.val;
 	reg_write_cmd.value_mask = valmask.mask;
-	ipa3_ctx->coal_cmd_pyld =
+	ipa3_ctx->coal_cmd_pyld[0] =
 		ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
 			&reg_write_cmd, false);
-	if (!ipa3_ctx->coal_cmd_pyld) {
+	if (!ipa3_ctx->coal_cmd_pyld[0]) {
 		IPAERR("fail construct register_write imm cmd\n");
 		ipa_assert();
 		return 0;
 	}
 
+	if (ipa3_ctx->ulso_wa) {
+		/* dummary regsiter read IC with HPS clear*/
+		ipa3_ctx->ulso_wa_cmd.size = 4;
+		ipa3_ctx->ulso_wa_cmd.base = dma_alloc_coherent(ipa3_ctx->pdev,
+			ipa3_ctx->ulso_wa_cmd.size,
+			&ipa3_ctx->ulso_wa_cmd.phys_base, GFP_KERNEL);
+		if (ipa3_ctx->ulso_wa_cmd.base == NULL) {
+			ipa_assert();
+		}
+		offset = ipahal_get_reg_n_ofst(IPA_STAT_QUOTA_BASE_n,
+			ipa3_ctx->ee);
+		dummy_reg_read.skip_pipeline_clear = false;
+		dummy_reg_read.pipeline_clear_options = IPAHAL_HPS_CLEAR;
+		dummy_reg_read.offset = offset;
+		dummy_reg_read.sys_addr = ipa3_ctx->ulso_wa_cmd.phys_base;
+		ipa3_ctx->coal_cmd_pyld[1] = ipahal_construct_imm_cmd(
+			IPA_IMM_CMD_REGISTER_READ,
+			&dummy_reg_read, false);
+		if (!ipa3_ctx->coal_cmd_pyld[1]) {
+			IPAERR("failed to construct DUMMY READ IC\n");
+			ipa_assert();
+		}
+	}
+
 	return 0;
 }
 
 void ipa3_free_coal_close_frame(void)
 {
-	if (ipa3_ctx->coal_cmd_pyld)
-		ipahal_destroy_imm_cmd(ipa3_ctx->coal_cmd_pyld);
+	if (ipa3_ctx->coal_cmd_pyld[0])
+		ipahal_destroy_imm_cmd(ipa3_ctx->coal_cmd_pyld[0]);
+
+	if (ipa3_ctx->coal_cmd_pyld[1]) {
+		ipahal_destroy_imm_cmd(ipa3_ctx->coal_cmd_pyld[1]);
+		dma_free_coherent(ipa3_ctx->pdev, ipa3_ctx->ulso_wa_cmd.size,
+			ipa3_ctx->ulso_wa_cmd.base, ipa3_ctx->ulso_wa_cmd.phys_base);
+	}
 }
 /**
  * ipa3_inject_dma_task_for_gsi()- Send DMA_TASK to IPA for GSI stop channel