Browse Source

msm: ipa: add new TX pipe for wdi 2.4G interface

Make changes to add new TX pipe for 2.4G interface

Change-Id: If6879a0d4ad33aa21b447f7f70ff78f44802efc0
Signed-off-by: Michael Adisumarta <[email protected]>
Michael Adisumarta 4 years ago
parent
commit
3b01837536

+ 52 - 9
drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c

@@ -55,6 +55,7 @@ struct ipa_wdi_context {
 	u32 tx_pipe_hdl;
 	u32 rx_pipe_hdl;
 	u8 num_sys_pipe_needed;
+	bool is_tx1_used;
 	u32 sys_pipe_hdl[IPA_WDI_MAX_SUPPORTED_SYS_PIPE];
 	u32 ipa_pm_hdl;
 #ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
@@ -207,6 +208,12 @@ static int ipa_wdi_reg_intf_internal(struct ipa_wdi_reg_intf_in_params *in)
 			return 0;
 		}
 
+	if (ipa3_ctx->ipa_wdi3_over_gsi &&
+		in->is_tx1_used && !ipa3_ctx->is_wdi3_tx1_needed) {
+		IPA_WDI_DBG(
+			"tx1 reg intr not sprtd, adng it to default pipe\n");
+	}
+
 	IPA_WDI_DBG("intf was not added before, proceed.\n");
 	new_intf = kzalloc(sizeof(*new_intf), GFP_KERNEL);
 	if (new_intf == NULL) {
@@ -246,20 +253,30 @@ static int ipa_wdi_reg_intf_internal(struct ipa_wdi_reg_intf_in_params *in)
 
 	memset(tx_prop, 0, sizeof(tx_prop));
 	tx_prop[0].ip = IPA_IP_v4;
-	if (!ipa3_get_ctx()->ipa_wdi3_over_gsi)
-		tx_prop[0].dst_pipe = IPA_CLIENT_WLAN1_CONS;
+	if (ipa3_get_ctx()->ipa_wdi3_over_gsi &&
+		ipa3_ctx->is_wdi3_tx1_needed) {
+		if (in->is_tx1_used)
+			tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS1;
+		else
+			tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS;
+	}
 	else
-		tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS;
+		tx_prop[0].dst_pipe = IPA_CLIENT_WLAN1_CONS;
 	tx_prop[0].alt_dst_pipe = in->alt_dst_pipe;
 	tx_prop[0].hdr_l2_type = in->hdr_info[0].hdr_type;
 	strlcpy(tx_prop[0].hdr_name, hdr->hdr[IPA_IP_v4].name,
 		sizeof(tx_prop[0].hdr_name));
 
 	tx_prop[1].ip = IPA_IP_v6;
-	if (!ipa3_get_ctx()->ipa_wdi3_over_gsi)
-		tx_prop[1].dst_pipe = IPA_CLIENT_WLAN1_CONS;
+	if (ipa3_get_ctx()->ipa_wdi3_over_gsi &&
+		ipa3_ctx->is_wdi3_tx1_needed) {
+		if (in->is_tx1_used)
+			tx_prop[1].dst_pipe = IPA_CLIENT_WLAN2_CONS1;
+		else
+			tx_prop[1].dst_pipe = IPA_CLIENT_WLAN2_CONS;
+	}
 	else
-		tx_prop[1].dst_pipe = IPA_CLIENT_WLAN2_CONS;
+		tx_prop[1].dst_pipe = IPA_CLIENT_WLAN1_CONS;
 	tx_prop[1].alt_dst_pipe = in->alt_dst_pipe;
 	tx_prop[1].hdr_l2_type = in->hdr_info[1].hdr_type;
 	strlcpy(tx_prop[1].hdr_name, hdr->hdr[IPA_IP_v6].name,
@@ -390,6 +407,7 @@ static int ipa_wdi_conn_pipes_internal(struct ipa_wdi_conn_in_params *in,
 	struct ipa_wdi_in_params in_rx;
 	struct ipa_wdi_out_params out_tx;
 	struct ipa_wdi_out_params out_rx;
+	int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
 
 	if (!(in && out)) {
 		IPA_WDI_ERR("empty parameters. in=%pK out=%pK\n", in, out);
@@ -408,6 +426,16 @@ static int ipa_wdi_conn_pipes_internal(struct ipa_wdi_conn_in_params *in,
 	}
 	ipa_wdi_ctx->num_sys_pipe_needed = in->num_sys_pipe_needed;
 	IPA_WDI_DBG("number of sys pipe %d\n", in->num_sys_pipe_needed);
+	ipa_ep_idx_tx1 = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
+	if ((ipa_ep_idx_tx1 != IPA_EP_NOT_ALLOCATED) &&
+		(ipa_ep_idx_tx1 < IPA3_MAX_NUM_PIPES) &&
+		ipa3_ctx->is_wdi3_tx1_needed) {
+		ipa_wdi_ctx->is_tx1_used = in->is_tx1_used;
+	} else
+		ipa_wdi_ctx->is_tx1_used = false;
+	IPA_WDI_DBG("number of sys pipe %d,Tx1 asked=%d,Tx1 supported=%d\n",
+		in->num_sys_pipe_needed, in->is_tx1_used,
+		ipa3_ctx->is_wdi3_tx1_needed);
 
 	/* setup sys pipe when needed */
 	for (i = 0; i < ipa_wdi_ctx->num_sys_pipe_needed; i++) {
@@ -568,6 +596,7 @@ fail_setup_sys_pipe:
 static int ipa_wdi_disconn_pipes_internal(void)
 {
 	int i, ipa_ep_idx_rx, ipa_ep_idx_tx;
+	int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
 
 	if (!ipa_wdi_ctx) {
 		IPA_WDI_ERR("wdi ctx is not initialized\n");
@@ -588,10 +617,14 @@ static int ipa_wdi_disconn_pipes_internal(void)
 	} else {
 		ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
 		ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
+		if (ipa_wdi_ctx->is_tx1_used)
+			ipa_ep_idx_tx1 =
+				ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
 	}
 
 	if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
-		if (ipa3_disconn_wdi3_pipes(ipa_ep_idx_rx, ipa_ep_idx_tx)) {
+		if (ipa3_disconn_wdi3_pipes(
+			ipa_ep_idx_tx, ipa_ep_idx_rx, ipa_ep_idx_tx1)) {
 			IPA_WDI_ERR("fail to tear down wdi pipes\n");
 			return -EFAULT;
 		}
@@ -618,6 +651,7 @@ static int ipa_wdi_enable_pipes_internal(void)
 {
 	int ret;
 	int ipa_ep_idx_tx, ipa_ep_idx_rx;
+	int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
 
 	if (!ipa_wdi_ctx) {
 		IPA_WDI_ERR("wdi ctx is not initialized.\n");
@@ -630,6 +664,9 @@ static int ipa_wdi_enable_pipes_internal(void)
 	} else {
 		ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
 		ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
+		if (ipa_wdi_ctx->is_tx1_used)
+			ipa_ep_idx_tx1 =
+				ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
 	}
 
 	if (ipa_ep_idx_tx <= 0 || ipa_ep_idx_rx <= 0)
@@ -642,7 +679,8 @@ static int ipa_wdi_enable_pipes_internal(void)
 	}
 
 	if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
-		if (ipa3_enable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
+		if (ipa3_enable_wdi3_pipes(
+			ipa_ep_idx_tx, ipa_ep_idx_rx, ipa_ep_idx_tx1)) {
 			IPA_WDI_ERR("fail to enable wdi pipes\n");
 			return -EFAULT;
 		}
@@ -679,6 +717,7 @@ static int ipa_wdi_disable_pipes_internal(void)
 {
 	int ret;
 	int ipa_ep_idx_tx, ipa_ep_idx_rx;
+	int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
 
 	if (!ipa_wdi_ctx) {
 		IPA_WDI_ERR("wdi ctx is not initialized.\n");
@@ -691,10 +730,14 @@ static int ipa_wdi_disable_pipes_internal(void)
 	} else {
 		ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
 		ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
+		if (ipa_wdi_ctx->is_tx1_used)
+			ipa_ep_idx_tx1 =
+				ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
 	}
 
 	if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
-		if (ipa3_disable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
+		if (ipa3_disable_wdi3_pipes(
+			ipa_ep_idx_tx, ipa_ep_idx_rx, ipa_ep_idx_tx1)) {
 			IPA_WDI_ERR("fail to disable wdi pipes\n");
 			return -EFAULT;
 		}

+ 6 - 3
drivers/platform/msm/ipa/ipa_common_i.h

@@ -549,11 +549,14 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
 	struct ipa_wdi_conn_out_params *out,
 	ipa_wdi_meter_notifier_cb wdi_notify);
 
-int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
+	int ipa_ep_idx_tx1);
 
-int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
+	int ipa_ep_idx_tx1);
 
-int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
+	int ipa_ep_idx_tx1);
 
 const char *ipa_get_version_string(enum ipa_hw_type ver);
 int ipa3_start_gsi_channel(u32 clnt_hdl);

+ 31 - 2
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -7305,6 +7305,8 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf,
 		 */
 		if (!strcasecmp(dbg_buff, "MHI")) {
 			ipa3_ctx->ipa_config_is_mhi = true;
+		} else if(!strcmp(dbg_buff, "DBS")) {
+			ipa3_ctx->is_wdi3_tx1_needed = true;
 		} else if (strcmp(dbg_buff, "1")) {
 			IPAERR("got invalid string %s not loading FW\n",
 				dbg_buff);
@@ -7612,8 +7614,11 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 			resource_p->tx_wrapper_cache_max_size);
 	ipa3_ctx->ipa_config_is_auto = resource_p->ipa_config_is_auto;
 	ipa3_ctx->ipa_mhi_proxy = resource_p->ipa_mhi_proxy;
-	ipa3_ctx->max_num_smmu_cb = resource_p->max_num_smmu_cb;
-	ipa3_ctx->hw_type_index = ipa3_get_hw_type_index();
+	ipa3_ctx->ipa_wdi3_2g_holb_timeout =
+		resource_p->ipa_wdi3_2g_holb_timeout;
+	ipa3_ctx->ipa_wdi3_5g_holb_timeout =
+		resource_p->ipa_wdi3_5g_holb_timeout;
+	ipa3_ctx->is_wdi3_tx1_needed = false;
 
 	if (resource_p->gsi_fw_file_name) {
 		ipa3_ctx->gsi_fw_file_name =
@@ -8371,6 +8376,8 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
 	u32 ipa_wan_aggr_pkt_cnt;
 
 	/* initialize ipa3_res */
+	ipa_drv_res->ipa_wdi3_2g_holb_timeout = 0;
+	ipa_drv_res->ipa_wdi3_5g_holb_timeout = 0;
 	ipa_drv_res->ipa_pipe_mem_start_ofst = IPA_PIPE_MEM_START_OFST;
 	ipa_drv_res->ipa_pipe_mem_size = IPA_PIPE_MEM_SIZE;
 	ipa_drv_res->ipa_hw_type = 0;
@@ -8844,6 +8851,28 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
 		kfree(ipa_tz_unlock_reg);
 	}
 
+	/* get HOLB_TO numbers for wdi3 tx pipe */
+	result = of_property_read_u32(pdev->dev.of_node,
+			"qcom,ipa-wdi3-holb-2g",
+			&ipa_drv_res->ipa_wdi3_2g_holb_timeout);
+	if (result)
+		IPADBG("Not able to get the holb for 2g pipe = %u\n",
+			ipa_drv_res->ipa_wdi3_2g_holb_timeout);
+	else
+		IPADBG(": found ipa_drv_res->ipa_wdi3_2g_holb_timeout = %u",
+			ipa_drv_res->ipa_wdi3_2g_holb_timeout);
+
+	/* get HOLB_TO numbers for wdi3 tx1 pipe */
+	result = of_property_read_u32(pdev->dev.of_node,
+			"qcom,ipa-wdi3-holb-5g",
+			&ipa_drv_res->ipa_wdi3_5g_holb_timeout);
+	if (result)
+		IPADBG("Not able to get the holb for 5g pipe = %u\n",
+			ipa_drv_res->ipa_wdi3_5g_holb_timeout);
+	else
+		IPADBG(": found ipa_drv_res->ipa_wdi3_2g_holb_timeout = %u",
+			ipa_drv_res->ipa_wdi3_2g_holb_timeout);
+
 	/* get IPA PM related information */
 	result = get_ipa_dts_pm_info(pdev, ipa_drv_res);
 	if (result) {

+ 19 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c

@@ -1570,6 +1570,13 @@ nxt_clnt_cons:
 				cnt += nbytes;
 				continue;
 			case IPA_CLIENT_WLAN2_CONS:
+				client = IPA_CLIENT_WLAN2_CONS1;
+				nbytes = scnprintf(dbg_buff + cnt,
+					IPA_MAX_MSG_LEN - cnt, HEAD_FRMT_STR,
+					"Client IPA_CLIENT_WLAN2_CONS1 Stats:");
+				cnt += nbytes;
+				continue;
+			case IPA_CLIENT_WLAN2_CONS1:
 				client = IPA_CLIENT_WLAN3_CONS;
 				nbytes = scnprintf(dbg_buff + cnt,
 					IPA_MAX_MSG_LEN - cnt, HEAD_FRMT_STR,
@@ -2443,6 +2450,18 @@ static ssize_t ipa3_read_wdi3_gsi_stats(struct file *file,
 			stats.u.ring[1].ringUsageLow,
 			stats.u.ring[1].RingUtilCount);
 		cnt += nbytes;
+		nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
+			"TX1 ringFull=%u\n"
+			"TX1 ringEmpty=%u\n"
+			"TX1 ringUsageHigh=%u\n"
+			"TX1 ringUsageLow=%u\n"
+			"TX1 RingUtilCount=%u\n",
+			stats.u.ring[2].ringFull,
+			stats.u.ring[2].ringEmpty,
+			stats.u.ring[2].ringUsageHigh,
+			stats.u.ring[2].ringUsageLow,
+			stats.u.ring[2].RingUtilCount);
+		cnt += nbytes;
 		nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
 			"RX ringFull=%u\n"
 			"RX ringEmpty=%u\n"

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

@@ -249,7 +249,11 @@ enum {
 #define IPA_WDI_CE_RING_RES			5
 #define IPA_WDI_CE_DB_RES			6
 #define IPA_WDI_TX_DB_RES			7
-#define IPA_WDI_MAX_RES				8
+#define IPA_WDI_TX1_RING_RES		8
+#define IPA_WDI_CE1_RING_RES		9
+#define IPA_WDI_CE1_DB_RES			10
+#define IPA_WDI_TX1_DB_RES			11
+#define IPA_WDI_MAX_RES				12
 
 /* use QMAP header reserved bit to identify tethered traffic */
 #define IPA_QMAP_TETH_BIT (1 << 30)
@@ -2184,6 +2188,9 @@ struct ipa3_context {
 	bool ipa_mhi_proxy;
 	u32 num_smmu_cb_probed;
 	u32 max_num_smmu_cb;
+	u32 ipa_wdi3_2g_holb_timeout;
+	u32 ipa_wdi3_5g_holb_timeout;
+	bool is_wdi3_tx1_needed;
 };
 
 struct ipa3_plat_drv_res {
@@ -2253,6 +2260,8 @@ struct ipa3_plat_drv_res {
 	u32 ipa_wan_aggr_pkt_cnt;
 	bool ipa_mhi_proxy;
 	u32 max_num_smmu_cb;
+	u32 ipa_wdi3_2g_holb_timeout;
+	u32 ipa_wdi3_5g_holb_timeout;
 };
 
 /**

+ 1 - 1
drivers/platform/msm/ipa/ipa_v3/ipa_uc_offload_i.h

@@ -27,7 +27,7 @@
 #define MAX_RTK_CHANNELS 2
 #define MAX_11AD_CHANNELS 5
 #define MAX_WDI2_CHANNELS 2
-#define MAX_WDI3_CHANNELS 2
+#define MAX_WDI3_CHANNELS 3
 #define MAX_MHIP_CHANNELS 4
 #define MAX_USB_CHANNELS 2
 

+ 11 - 3
drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c

@@ -914,9 +914,12 @@ void ipa3_release_wdi3_gsi_smmu_mappings(u8 dir)
 	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
 	int i, j, start, end;
 
-	if (dir == IPA_WDI3_TX_DIR) {
-		start = IPA_WDI_TX_RING_RES;
-		end = IPA_WDI_TX_DB_RES;
+	if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
+		start = (dir == IPA_WDI3_TX_DIR) ?
+				IPA_WDI_TX_RING_RES :
+				IPA_WDI_TX1_RING_RES;
+		end = (dir == IPA_WDI3_TX_DIR) ?
+				IPA_WDI_TX_DB_RES : IPA_WDI_TX1_DB_RES;
 	} else {
 		start = IPA_WDI_RX_RING_RES;
 		end = IPA_WDI_RX_COMP_RING_WP_RES;
@@ -974,6 +977,9 @@ int ipa_create_gsi_smmu_mapping(int res_idx, bool wlan_smmu_en,
 		case IPA_WDI_RX_COMP_RING_WP_RES:
 		case IPA_WDI_CE_DB_RES:
 		case IPA_WDI_TX_DB_RES:
+		case IPA_WDI_CE1_DB_RES:
+		case IPA_WDI_TX1_DB_RES:
+
 			if (ipa_create_ap_smmu_mapping_pa(pa, len,
 				(res_idx == IPA_WDI_CE_DB_RES) ? true : false,
 						iova)) {
@@ -987,6 +993,8 @@ int ipa_create_gsi_smmu_mapping(int res_idx, bool wlan_smmu_en,
 		case IPA_WDI_RX_COMP_RING_RES:
 		case IPA_WDI_TX_RING_RES:
 		case IPA_WDI_CE_RING_RES:
+		case IPA_WDI_TX1_RING_RES:
+		case IPA_WDI_CE1_RING_RES:
 			if (ipa_create_ap_smmu_mapping_sgt(sgt, iova)) {
 				IPAERR("Fail to create mapping res %d\n",
 						res_idx);

+ 14 - 2
drivers/platform/msm/ipa/ipa_v3/ipa_utils.c

@@ -2464,13 +2464,18 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 11, 14, 8, 16, IPA_EE_AP }, IPA_TX_INSTANCE_NA },
-
 	[IPA_4_5][IPA_CLIENT_WLAN2_CONS]          = {
 			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 24, 3, 8, 14, IPA_EE_AP, GSI_SMART_PRE_FETCH, 3 }, IPA_TX_INSTANCE_NA },
+	[IPA_4_5][IPA_CLIENT_WLAN2_CONS1]          = {
+			true, IPA_v4_5_GROUP_UL_DL,
+			false,
+			IPA_DPS_HPS_SEQ_TYPE_INVALID,
+			QMB_MASTER_SELECT_DDR,
+			{ 27, 18, 8, 14, IPA_EE_AP, GSI_SMART_PRE_FETCH, 3 }, IPA_TX_INSTANCE_NA},
 	[IPA_4_5][IPA_CLIENT_USB_CONS]            = {
 			true, IPA_v4_5_GROUP_UL_DL,
 			false,
@@ -4154,7 +4159,7 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 			QMB_MASTER_SELECT_PCIE,
 			{ 27, 3 , 8 , 14, IPA_EE_AP, GSI_SMART_PRE_FETCH, 3},
 			IPA_TX_INSTANCE_DL },
-	[IPA_5_0][IPA_CLIENT_WLAN3_CONS] = {
+	[IPA_5_0][IPA_CLIENT_WLAN2_CONS1] = {
 			true,   IPA_v5_0_GROUP_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
@@ -5668,6 +5673,10 @@ const char *ipa_clients_strings[IPA_CLIENT_MAX] = {
 	__stringify(IPA_CLIENT_MHI2_CONS),
 	__stringify(IPA_CLIENT_Q6_CV2X_PROD),
 	__stringify(IPA_CLIENT_Q6_CV2X_CONS),
+	__stringify(IPA_CLIENT_ETHERNET2_PROD),
+	__stringify(IPA_CLIENT_ETHERNET2_CONS),
+	__stringify(RESERVERD_PROD_118),
+	__stringify(IPA_CLIENT_WLAN2_CONS1),
 };
 EXPORT_SYMBOL(ipa_clients_strings);
 
@@ -5786,6 +5795,7 @@ int ipa3_get_clients_from_rm_resource(
 		clients->names[i++] = IPA_CLIENT_WLAN1_CONS;
 		clients->names[i++] = IPA_CLIENT_WLAN2_CONS;
 		clients->names[i++] = IPA_CLIENT_WLAN3_CONS;
+		clients->names[i++] = IPA_CLIENT_WLAN2_CONS1;
 		break;
 	case IPA_RM_RESOURCE_MHI_CONS:
 		clients->names[i++] = IPA_CLIENT_MHI_CONS;
@@ -5864,6 +5874,7 @@ bool ipa3_should_pipe_be_suspended(enum ipa_client_type client)
 	    client == IPA_CLIENT_WLAN1_CONS   ||
 	    client == IPA_CLIENT_WLAN2_CONS   ||
 	    client == IPA_CLIENT_WLAN3_CONS   ||
+	    client == IPA_CLIENT_WLAN2_CONS1  ||
 	    client == IPA_CLIENT_WLAN4_CONS   ||
 	    client == IPA_CLIENT_ODU_EMB_CONS ||
 	    client == IPA_CLIENT_ODU_TETH_CONS ||
@@ -11543,6 +11554,7 @@ int ipa3_get_prot_id(enum ipa_client_type client)
 		break;
 	case IPA_CLIENT_WLAN2_PROD:
 	case IPA_CLIENT_WLAN2_CONS:
+	case IPA_CLIENT_WLAN2_CONS1:
 		prot_id = IPA_HW_PROTOCOL_WDI3;
 		break;
 	case IPA_CLIENT_USB_PROD:

+ 237 - 22
drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c

@@ -86,14 +86,14 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_9) {
 		gsi_evt_ring_props.intr = GSI_INTR_MSI;
 		/* 32 (for Tx) and 8 (for Rx) */
-		if (dir == IPA_WDI3_TX_DIR)
+		if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR))
 			gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_32B;
 		else
 			gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_8B;
 	} else {
 		gsi_evt_ring_props.intr = GSI_INTR_IRQ;
 		/* 16 (for Tx) and 8 (for Rx) */
-		if (dir == IPA_WDI3_TX_DIR)
+		if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR))
 			gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_16B;
 		else
 			gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_8B;
@@ -104,8 +104,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 			(u64)info->event_ring_base_pa;
 	} else {
 		len = info_smmu->event_ring_size;
-		if (dir == IPA_WDI3_TX_DIR) {
-			if (ipa_create_gsi_smmu_mapping(IPA_WDI_CE_RING_RES,
+		if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
+			if (ipa_create_gsi_smmu_mapping((
+				dir == IPA_WDI3_TX_DIR) ?
+				IPA_WDI_CE_RING_RES : IPA_WDI_CE1_RING_RES,
 				true, info->event_ring_base_pa,
 				&info_smmu->event_ring_base, len,
 				false, &va)) {
@@ -146,7 +148,7 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 	/* setup channel ring */
 	memset(&gsi_channel_props, 0, sizeof(gsi_channel_props));
 	gsi_channel_props.prot = GSI_CHAN_PROT_WDI3;
-	if (dir == IPA_WDI3_TX_DIR)
+	if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR))
 		gsi_channel_props.dir = GSI_CHAN_DIR_FROM_GSI;
 	else
 		gsi_channel_props.dir = GSI_CHAN_DIR_TO_GSI;
@@ -164,7 +166,7 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 	gsi_channel_props.evt_ring_hdl = ep->gsi_evt_ring_hdl;
 	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_9) {
 		/* 32 (for Tx) and 64 (for Rx) */
-		if (dir == IPA_WDI3_TX_DIR)
+		if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR))
 			gsi_channel_props.re_size = GSI_CHAN_RE_SIZE_32B;
 		else
 			gsi_channel_props.re_size = GSI_CHAN_RE_SIZE_64B;
@@ -186,8 +188,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 			(u64)info->transfer_ring_base_pa;
 	} else {
 		len = info_smmu->transfer_ring_size;
-		if (dir == IPA_WDI3_TX_DIR) {
-			if (ipa_create_gsi_smmu_mapping(IPA_WDI_TX_RING_RES,
+		if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
+			if (ipa_create_gsi_smmu_mapping((
+				dir == IPA_WDI3_TX_DIR) ?
+				IPA_WDI_TX_RING_RES : IPA_WDI_TX1_RING_RES,
 				true, info->transfer_ring_base_pa,
 				&info_smmu->transfer_ring_base, len,
 				false, &va)) {
@@ -255,8 +259,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 		addr_low = (u32)info->event_ring_doorbell_pa;
 		addr_high = (u32)((u64)info->event_ring_doorbell_pa >> 32);
 	} else {
-		if (dir == IPA_WDI3_TX_DIR) {
-			if (ipa_create_gsi_smmu_mapping(IPA_WDI_CE_DB_RES,
+		if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
+			if (ipa_create_gsi_smmu_mapping((
+				dir == IPA_WDI3_TX_DIR) ?
+				IPA_WDI_CE_DB_RES : IPA_WDI_CE1_DB_RES,
 				true, info_smmu->event_ring_doorbell_pa,
 				NULL, 4, true, &va)) {
 				IPAERR("failed to get smmu mapping\n");
@@ -361,8 +367,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 		ch_scratch.wdi3.wifi_rp_address_high =
 			(u32)((u64)info->transfer_ring_doorbell_pa >> 32);
 	} else {
-		if (dir == IPA_WDI3_TX_DIR) {
-			if (ipa_create_gsi_smmu_mapping(IPA_WDI_TX_DB_RES,
+		if ((dir == IPA_WDI3_TX_DIR) || (dir == IPA_WDI3_TX1_DIR)) {
+			if (ipa_create_gsi_smmu_mapping((
+				dir == IPA_WDI3_TX_DIR) ?
+				IPA_WDI_TX_DB_RES : IPA_WDI_TX1_DB_RES,
 				true, info_smmu->transfer_ring_doorbell_pa,
 				NULL, 4, true, &va)) {
 				IPAERR("failed to get smmu mapping\n");
@@ -452,10 +460,13 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
 {
 	enum ipa_client_type rx_client;
 	enum ipa_client_type tx_client;
+	enum ipa_client_type tx1_client;
 	struct ipa3_ep_context *ep_rx;
 	struct ipa3_ep_context *ep_tx;
+	struct ipa3_ep_context *ep_tx1;
 	int ipa_ep_idx_rx;
 	int ipa_ep_idx_tx;
+	int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
 	int result = 0;
 	u32 gsi_db_addr_low, gsi_db_addr_high;
 	void __iomem *db_addr;
@@ -505,6 +516,27 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
 	memset(ep_rx, 0, offsetof(struct ipa3_ep_context, sys));
 	memset(ep_tx, 0, offsetof(struct ipa3_ep_context, sys));
 
+	if (in->is_tx1_used &&
+		ipa3_ctx->is_wdi3_tx1_needed) {
+		tx1_client = (in->is_smmu_enabled) ?
+			in->u_tx1.tx_smmu.client : in->u_tx1.tx.client;
+		ipa_ep_idx_tx1 = ipa_get_ep_mapping(tx1_client);
+
+		if (ipa_ep_idx_tx1 == IPA_EP_NOT_ALLOCATED ||
+			ipa_ep_idx_tx1 >= IPA3_MAX_NUM_PIPES) {
+			IPAERR("fail to alloc ep2 tx clnt %d not supprtd %d",
+				tx1_client, ipa_ep_idx_tx1);
+			return -EINVAL;
+		} else {
+			ep_tx1 = &ipa3_ctx->ep[ipa_ep_idx_tx1];
+			if (ep_tx1->valid) {
+				IPAERR("EP already allocated.\n");
+				return -EFAULT;
+			}
+		}
+		memset(ep_tx1, 0, offsetof(struct ipa3_ep_context, sys));
+	}
+
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 
 #ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
@@ -635,11 +667,12 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
 		in->u_rx.rx.event_ring_size);
 	db_val += GSI_EVT_RING_RE_SIZE_8B;
 	iowrite32(db_val, db_addr);
-	gsi_query_evt_ring_db_addr(ep_tx->gsi_evt_ring_hdl,
-		&evt_ring_db_addr_low, &evt_ring_db_addr_high);
 	IPADBG("RX base_addr 0x%x evt wp val: 0x%x\n",
 		ep_rx->gsi_mem_info.evt_ring_base_addr, db_val);
 
+	gsi_query_evt_ring_db_addr(ep_tx->gsi_evt_ring_hdl,
+		&evt_ring_db_addr_low, &evt_ring_db_addr_high);
+
 	/* only 32 bit lsb is used */
 	db_addr = ioremap((phys_addr_t)(evt_ring_db_addr_low), 4);
 	/*
@@ -659,15 +692,96 @@ int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
 	IPADBG("db_addr %u  TX base_addr 0x%x evt wp val: 0x%x\n",
 		evt_ring_db_addr_low,
 		ep_tx->gsi_mem_info.evt_ring_base_addr, db_val);
+
+	/* setup tx1 ep cfg */
+	if (in->is_tx1_used &&
+		ipa3_ctx->is_wdi3_tx1_needed && (ipa_ep_idx_tx1 !=
+		IPA_EP_NOT_ALLOCATED) && (ipa_ep_idx_tx1 <
+		IPA3_MAX_NUM_PIPES)) {
+		ep_tx1->valid = 1;
+		ep_tx1->client = tx1_client;
+		result = ipa3_disable_data_path(ipa_ep_idx_tx1);
+		if (result) {
+			IPAERR("disable data path failed res=%d ep=%d.\n",
+				result, ipa_ep_idx_tx1);
+			result = -EFAULT;
+			goto fail;
+		}
+
+		if (in->is_smmu_enabled == false)
+			memcpy(&ep_tx1->cfg, &in->u_tx1.tx.ipa_ep_cfg,
+				sizeof(ep_tx1->cfg));
+		else
+			memcpy(&ep_tx1->cfg, &in->u_tx1.tx_smmu.ipa_ep_cfg,
+				sizeof(ep_tx1->cfg));
+
+		ep_tx1->cfg.aggr.aggr_en = IPA_ENABLE_AGGR;
+		ep_tx1->cfg.aggr.aggr = IPA_GENERIC;
+		ep_tx1->cfg.aggr.aggr_byte_limit = IPA_WLAN_AGGR_BYTE_LIMIT;
+		ep_tx1->cfg.aggr.aggr_pkt_limit = IPA_WLAN_AGGR_PKT_LIMIT;
+		ep_tx1->cfg.aggr.aggr_hard_byte_limit_en = IPA_ENABLE_AGGR;
+		if (ipa3_cfg_ep(ipa_ep_idx_tx1, &ep_tx1->cfg)) {
+			IPAERR("fail to setup tx pipe cfg\n");
+			result = -EFAULT;
+			goto fail;
+		}
+
+		/* setup TX1 gsi channel */
+		if (ipa3_setup_wdi3_gsi_channel(in->is_smmu_enabled,
+			&in->u_tx1.tx, &in->u_tx1.tx_smmu, IPA_WDI3_TX1_DIR,
+			ep_tx1)) {
+			IPAERR("fail to setup wdi3 gsi tx1 channel\n");
+			result = -EFAULT;
+			goto fail;
+		}
+
+		if (gsi_query_channel_db_addr(ep_tx1->gsi_chan_hdl,
+			&gsi_db_addr_low, &gsi_db_addr_high)) {
+			IPAERR("failed to query gsi tx1 db addr\n");
+			result = -EFAULT;
+			goto fail;
+		}
+
+		/* only 32 bit lsb is used */
+		out->tx1_uc_db_pa = (phys_addr_t)(gsi_db_addr_low);
+		IPADBG("out->tx1_uc_db_pa %llu\n", out->tx1_uc_db_pa);
+		IPADBG("client %d (ep: %d) connected\n", tx1_client,
+			ipa_ep_idx_tx1);
+
+		/* ring initial event ring dbs */
+		gsi_query_evt_ring_db_addr(ep_tx1->gsi_evt_ring_hdl,
+			&evt_ring_db_addr_low, &evt_ring_db_addr_high);
+		/* only 32 bit lsb is used */
+		db_addr = ioremap((phys_addr_t)(evt_ring_db_addr_low), 4);
+		/*
+		 * IPA/GSI driver should ring the event DB once after
+		 * initialization of the event, with a value that is
+		 * outside of the ring range. Eg: ring base = 0x1000,
+		 * ring size = 0x100 => AP can write value > 0x1100
+		 * into the doorbell address. Eg: 0x 1110
+		 * Use event ring base addr + event ring size + 1 element size.
+		 */
+		db_val = (u32)ep_tx1->gsi_mem_info.evt_ring_base_addr;
+		db_val += ((in->is_smmu_enabled) ?
+					in->u_tx1.tx_smmu.event_ring_size :
+					in->u_tx1.tx.event_ring_size);
+		db_val += GSI_EVT_RING_RE_SIZE_16B;
+		iowrite32(db_val, db_addr);
+		IPADBG("db_addr %u  TX1 base_addr 0x%x evt wp val: 0x%x\n",
+			evt_ring_db_addr_low,
+			ep_tx1->gsi_mem_info.evt_ring_base_addr, db_val);
+	}
+
 fail:
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 	return result;
 }
 EXPORT_SYMBOL(ipa3_conn_wdi3_pipes);
 
-int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
+	int ipa_ep_idx_tx1)
 {
-	struct ipa3_ep_context *ep_tx, *ep_rx;
+	struct ipa3_ep_context *ep_tx, *ep_rx, *ep_tx1;
 	int result = 0;
 
 	/* wdi3 only support over gsi */
@@ -679,6 +793,7 @@ int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 
 	IPADBG("ep_tx = %d\n", ipa_ep_idx_tx);
 	IPADBG("ep_rx = %d\n", ipa_ep_idx_rx);
+	IPADBG("ep_tx1 = %d\n", ipa_ep_idx_tx1);
 
 	if (ipa_ep_idx_tx < 0 || ipa_ep_idx_tx >= ipa3_get_max_num_pipes() ||
 		ipa_ep_idx_rx < 0 ||
@@ -691,6 +806,30 @@ int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 	ep_rx = &ipa3_ctx->ep[ipa_ep_idx_rx];
 
 	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(ipa_ep_idx_tx));
+	/* tear down tx1 pipe */
+	if (ipa_ep_idx_tx1 >= 0) {
+		ep_tx1 = &ipa3_ctx->ep[ipa_ep_idx_tx1];
+		result = ipa3_reset_gsi_channel(ipa_ep_idx_tx1);
+		if (result != GSI_STATUS_SUCCESS) {
+			IPAERR("failed to reset gsi channel: %d.\n", result);
+			goto exit;
+		}
+		result = gsi_reset_evt_ring(ep_tx1->gsi_evt_ring_hdl);
+		if (result != GSI_STATUS_SUCCESS) {
+			IPAERR("failed to reset evt ring: %d.\n", result);
+			goto exit;
+		}
+		result = ipa3_release_gsi_channel(ipa_ep_idx_tx1);
+		if (result) {
+			IPAERR("failed to release gsi channel: %d\n", result);
+			goto exit;
+		}
+		ipa3_release_wdi3_gsi_smmu_mappings(IPA_WDI3_TX1_DIR);
+
+		memset(ep_tx1, 0, sizeof(struct ipa3_ep_context));
+		IPADBG("tx client (ep: %d) disconnected\n", ipa_ep_idx_tx1);
+	}
+
 	/* tear down tx pipe */
 	result = ipa3_reset_gsi_channel(ipa_ep_idx_tx);
 	if (result != GSI_STATUS_SUCCESS) {
@@ -742,10 +881,13 @@ exit:
 }
 EXPORT_SYMBOL(ipa3_disconn_wdi3_pipes);
 
-int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
+	int ipa_ep_idx_tx1)
 {
 	struct ipa3_ep_context *ep_tx, *ep_rx;
+	struct ipa3_ep_context *ep_tx1 = NULL;
 	int result = 0;
+	struct ipa_ep_cfg_holb holb_cfg;
 	u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_wlan;
 
 	/* wdi3 only support over gsi */
@@ -757,9 +899,12 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 
 	IPADBG("ep_tx = %d\n", ipa_ep_idx_tx);
 	IPADBG("ep_rx = %d\n", ipa_ep_idx_rx);
+	IPADBG("ep_tx1 = %d\n", ipa_ep_idx_tx1);
 
 	ep_tx = &ipa3_ctx->ep[ipa_ep_idx_tx];
 	ep_rx = &ipa3_ctx->ep[ipa_ep_idx_rx];
+	if (ipa_ep_idx_tx1 >= 0)
+		ep_tx1 = &ipa3_ctx->ep[ipa_ep_idx_tx1];
 
 	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(ipa_ep_idx_tx));
 
@@ -792,11 +937,38 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 		goto fail_enable_path1;
 	}
 
+	/* Enable and config HOLB TO for both tx pipes */
+	if (ipa_ep_idx_tx1 >= 0) {
+		result = ipa3_enable_data_path(ipa_ep_idx_tx1);
+		if (result) {
+			IPAERR("enable data path failed res=%d clnt=%d\n",
+				result, ipa_ep_idx_tx1);
+			goto fail_enable_path2;
+		}
+		memset(&holb_cfg, 0, sizeof(holb_cfg));
+		holb_cfg.en = IPA_HOLB_TMR_EN;
+		holb_cfg.tmr_val = ipa3_ctx->ipa_wdi3_5g_holb_timeout;
+		IPADBG("Configuring HOLB TO on tx return = %d\n",
+			ipa3_cfg_ep_holb(ipa_ep_idx_tx, &holb_cfg));
+		holb_cfg.tmr_val = ipa3_ctx->ipa_wdi3_2g_holb_timeout;
+		IPADBG("Configuring HOLB TO on tx1 return = %d\n",
+			ipa3_cfg_ep_holb(ipa_ep_idx_tx1, &holb_cfg));
+	}
+
 	/* start gsi tx channel */
 	result = gsi_start_channel(ep_tx->gsi_chan_hdl);
 	if (result) {
 		IPAERR("failed to start gsi tx channel\n");
-		goto fail_enable_path2;
+		goto fail_start_channel1;
+	}
+
+	/* start gsi tx1 channel */
+	if (ipa_ep_idx_tx1 >= 0) {
+		result = gsi_start_channel(ep_tx1->gsi_chan_hdl);
+		if (result) {
+			IPAERR("failed to start gsi tx1 channel\n");
+			goto fail_start_channel2;
+		}
 	}
 
 	result = ipa3_uc_client_add_holb_monitor(ep_tx->gsi_chan_hdl,
@@ -810,7 +982,7 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 	result = gsi_start_channel(ep_rx->gsi_chan_hdl);
 	if (result) {
 		IPAERR("failed to start gsi rx channel\n");
-		goto fail_start_channel1;
+		goto fail_start_channel3;
 	}
 	/* start uC gsi dbg stats monitor */
 	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) {
@@ -822,13 +994,27 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 			= ep_tx->gsi_chan_hdl;
 		ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3].ch_id_info[1].dir
 			= DIR_CONSUMER;
+		if (ipa_ep_idx_tx1 >= 0) {
+			ipa3_ctx->gsi_info[
+				IPA_HW_PROTOCOL_WDI3].ch_id_info[2].ch_id
+				= ep_tx1->gsi_chan_hdl;
+			ipa3_ctx->gsi_info[
+				IPA_HW_PROTOCOL_WDI3].ch_id_info[2].dir
+				= DIR_CONSUMER;
+		}
 		ipa3_uc_debug_stats_alloc(
 			ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3]);
 	}
 	goto exit;
 
-fail_start_channel1:
+fail_start_channel3:
+	if (ipa_ep_idx_tx1 >= 0)
+		gsi_stop_channel(ep_tx1->gsi_chan_hdl);
+fail_start_channel2:
 	gsi_stop_channel(ep_tx->gsi_chan_hdl);
+fail_start_channel1:
+	if (ipa_ep_idx_tx1 >= 0)
+		ipa3_disable_data_path(ipa_ep_idx_tx1);
 fail_enable_path2:
 	ipa3_disable_data_path(ipa_ep_idx_tx);
 fail_enable_path1:
@@ -839,7 +1025,8 @@ exit:
 }
 EXPORT_SYMBOL(ipa3_enable_wdi3_pipes);
 
-int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx,
+	int ipa_ep_idx_tx1)
 {
 	int result = 0;
 	struct ipa3_ep_context *ep;
@@ -860,12 +1047,23 @@ int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 	/* disable tx data path */
 	result = ipa3_disable_data_path(ipa_ep_idx_tx);
 	if (result) {
-		IPAERR("enable data path failed res=%d clnt=%d.\n", result,
+		IPAERR("disable data path failed res=%d clnt=%d.\n", result,
 			ipa_ep_idx_tx);
 		result = -EFAULT;
 		goto fail;
 	}
 
+	/* disable tx1 data path */
+	if (ipa_ep_idx_tx1 >= 0) {
+		result = ipa3_disable_data_path(ipa_ep_idx_tx1);
+		if (result) {
+			IPAERR("disable data path failed res=%d clnt=%d.\n", result,
+				ipa_ep_idx_tx1);
+			result = -EFAULT;
+			goto fail;
+		}
+	}
+
 	/* disable rx data path */
 	result = ipa3_disable_data_path(ipa_ep_idx_rx);
 	if (result) {
@@ -916,6 +1114,15 @@ int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 		result = -EFAULT;
 		goto fail;
 	}
+	/* stop gsi tx1 channel */
+	if (ipa_ep_idx_tx1 >= 0) {
+		result = ipa3_stop_gsi_channel(ipa_ep_idx_tx1);
+		if (result) {
+			IPAERR("failed to stop gsi tx1 channel\n");
+			result = -EFAULT;
+			goto fail;
+		}
+	}
 	/* stop uC gsi dbg stats monitor */
 	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) {
 		ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3].ch_id_info[0].ch_id
@@ -926,6 +1133,14 @@ int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 			= 0xff;
 		ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3].ch_id_info[1].dir
 			= DIR_CONSUMER;
+		if (ipa_ep_idx_tx1 >= 0) {
+			ipa3_ctx->gsi_info[
+				IPA_HW_PROTOCOL_WDI3].ch_id_info[2].ch_id
+				= 0xff;
+			ipa3_ctx->gsi_info[
+				IPA_HW_PROTOCOL_WDI3].ch_id_info[2].dir
+				= DIR_CONSUMER;
+		}
 		ipa3_uc_debug_stats_alloc(
 			ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI3]);
 	}