Browse Source

msm: ipa3: add v2x ethernet support

Add the v2x ethernet pipe connect support
for offloading v2x traffic.

Change-Id: I5e84f7e1d07722eeb5a7b9fbfbccb69451c72934
Signed-off-by: Pooja Kumari <[email protected]>
Pooja Kumari 3 years ago
parent
commit
9861c7b45a

+ 47 - 11
drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/ipa_uc_offload.h>
@@ -121,7 +121,11 @@ static int ipa_uc_offload_ntn_register_pm_client(
 	struct ipa_pm_register_params params;
 
 	memset(&params, 0, sizeof(params));
-	params.name = "ETH";
+
+	if (ntn_ctx->proto == IPA_UC_NTN_V2X)
+		params.name = "ETH_v2x";
+	else
+		params.name = "ETH";
 	params.callback = ipa_uc_offload_ntn_pm_cb;
 	params.user_data = ntn_ctx;
 	params.group = IPA_PM_GROUP_DEFAULT;
@@ -130,11 +134,15 @@ static int ipa_uc_offload_ntn_register_pm_client(
 		IPA_UC_OFFLOAD_ERR("fail to register with PM %d\n", res);
 		return res;
 	}
-
-	res = ipa_pm_associate_ipa_cons_to_client(ntn_ctx->pm_hdl,
-		IPA_CLIENT_ETHERNET_CONS);
+	if (ntn_ctx->proto == IPA_UC_NTN_V2X)
+		res = ipa_pm_associate_ipa_cons_to_client(ntn_ctx->pm_hdl,
+			IPA_CLIENT_ETHERNET2_CONS);
+	else
+		res = ipa_pm_associate_ipa_cons_to_client(ntn_ctx->pm_hdl,
+			IPA_CLIENT_ETHERNET_CONS);
 	if (res) {
-		IPA_UC_OFFLOAD_ERR("fail to associate cons with PM %d\n", res);
+		IPA_UC_OFFLOAD_ERR("fail to associate. PM (%d) Prot: %d\n",
+			res, ntn_ctx->proto);
 		ipa_pm_deregister(ntn_ctx->pm_hdl);
 		ntn_ctx->pm_hdl = ~0;
 		return res;
@@ -322,12 +330,28 @@ static int ipa_uc_offload_reg_intf_internal(
 		return -EINVAL;
 	}
 
+	/* only register IPA properties for uc_ntn */
 	if (ctx->proto == IPA_UC_NTN) {
 		ret = ipa_uc_offload_ntn_reg_intf(inp, outp, ctx);
 		if (!ret)
 			outp->clnt_hndl = IPA_UC_NTN;
 	}
 
+	/* only register IPA-pm for uc_ntn_v2x */
+	if (ctx->proto == IPA_UC_NTN_V2X) {
+		/* always in vlan mode */
+		IPA_UC_OFFLOAD_INFO("v2x hdr_len %d\n",
+			inp->hdr_info[0].hdr_len);
+		ctx->hdr_len = inp->hdr_info[0].hdr_len;
+		ret = ipa_uc_offload_ntn_register_pm_client(ctx);
+		if (!ret)
+			outp->clnt_hndl = IPA_UC_NTN_V2X;
+		else
+			IPA_UC_OFFLOAD_ERR("fail to create pm resource\n");
+		/* set to initialized state */
+		ctx->state = IPA_UC_OFFLOAD_STATE_INITIALIZED;
+	}
+
 	return ret;
 }
 
@@ -461,7 +485,7 @@ static int ipa_uc_offload_conn_pipes_internal(struct ipa_uc_offload_conn_in_para
 
 	offload_ctx = ipa_uc_offload_ctx[inp->clnt_hndl];
 	if (!offload_ctx) {
-		IPA_UC_OFFLOAD_ERR("Invalid Handle\n");
+		IPA_UC_OFFLOAD_ERR("Invalid ctx %d\n", inp->clnt_hndl);
 		return -EINVAL;
 	}
 
@@ -471,6 +495,7 @@ static int ipa_uc_offload_conn_pipes_internal(struct ipa_uc_offload_conn_in_para
 	}
 
 	switch (offload_ctx->proto) {
+	case IPA_UC_NTN_V2X:
 	case IPA_UC_NTN:
 		ret = ipa_uc_ntn_conn_pipes(&inp->u.ntn, &outp->u.ntn,
 						offload_ctx);
@@ -503,8 +528,13 @@ static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx)
 		return -EFAULT;
 	}
 
-	ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD);
-	ipa_ep_idx_dl = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_CONS);
+	if (ntn_ctx->proto == IPA_UC_NTN_V2X) {
+		ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET2_PROD);
+		ipa_ep_idx_dl = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET2_CONS);
+	} else {
+		ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD);
+		ipa_ep_idx_dl = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_CONS);
+	}
 	ret = ipa3_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl,
 		&ntn_ctx->conn);
 	if (ret) {
@@ -543,6 +573,7 @@ static int ipa_uc_offload_disconn_pipes_internal(u32 clnt_hdl)
 	}
 
 	switch (offload_ctx->proto) {
+	case IPA_UC_NTN_V2X:
 	case IPA_UC_NTN:
 		ret = ipa_uc_ntn_disconn_pipes(offload_ctx);
 		break;
@@ -617,6 +648,11 @@ static int ipa_uc_offload_cleanup_internal(u32 clnt_hdl)
 		ret = ipa_uc_ntn_cleanup(offload_ctx);
 		break;
 
+	case IPA_UC_NTN_V2X:
+		/* only clean-up pm_handle */
+		ipa_uc_offload_ntn_deregister_pm_client(offload_ctx);
+		break;
+
 	default:
 		IPA_UC_OFFLOAD_ERR("Invalid Proto :%d\n", clnt_hdl);
 		ret = -EINVAL;
@@ -650,7 +686,7 @@ int ipa_uc_offload_reg_rdyCB_internal(struct ipa_uc_ready_params *inp)
 		return -EINVAL;
 	}
 
-	if (inp->proto == IPA_UC_NTN)
+	if (inp->proto == IPA_UC_NTN || inp->proto == IPA_UC_NTN_V2X)
 		ret = ipa3_ntn_uc_reg_rdyCB(inp->notify, inp->priv);
 
 	if (ret == -EEXIST) {
@@ -664,7 +700,7 @@ int ipa_uc_offload_reg_rdyCB_internal(struct ipa_uc_ready_params *inp)
 
 void ipa_uc_offload_dereg_rdyCB_internal(enum ipa_uc_offload_proto proto)
 {
-	if (proto == IPA_UC_NTN)
+	if (proto == IPA_UC_NTN || proto == IPA_UC_NTN_V2X)
 		ipa3_ntn_uc_dereg_rdyCB();
 }
 

+ 1 - 1
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -8822,7 +8822,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 	}
 
 	IPADBG(
-	    "base(0x%x)+offset(0x%x)=(0x%x) mapped to (%pK) with len (0x%x)\n",
+	    "base(0x%x)+offset(0x%x)=(0x%x) mapped to (%0x%x) with len (0x%x)\n",
 	    resource_p->ipa_mem_base,
 	    ipa3_ctx->ctrl->ipa_reg_base_ofst,
 	    resource_p->ipa_mem_base + ipa3_ctx->ctrl->ipa_reg_base_ofst,

+ 72 - 65
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c

@@ -1832,76 +1832,83 @@ nxt_clnt_cons:
 static ssize_t ipa3_read_ntn(struct file *file, char __user *ubuf,
 		size_t count, loff_t *ppos)
 {
-#define TX_STATS(y) \
-	stats.tx_ch_stats[0].y
-#define RX_STATS(y) \
-	stats.rx_ch_stats[0].y
+#define TX_STATS(x, y) \
+	stats.tx_ch_stats[x].y
+#define RX_STATS(x, y) \
+	stats.rx_ch_stats[x].y
 
 	struct Ipa3HwStatsNTNInfoData_t stats;
 	int nbytes;
-	int cnt = 0;
+	int cnt = 0, i = 0;
 
 	if (!ipa3_get_ntn_stats(&stats)) {
-		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
-			"TX num_pkts_processed=%u\n"
-			"TX ringFull=%u\n"
-			"TX ringEmpty=%u\n"
-			"TX ringUsageHigh=%u\n"
-			"TX ringUsageLow=%u\n"
-			"TX RingUtilCount=%u\n"
-			"TX bamFifoFull=%u\n"
-			"TX bamFifoEmpty=%u\n"
-			"TX bamFifoUsageHigh=%u\n"
-			"TX bamFifoUsageLow=%u\n"
-			"TX bamUtilCount=%u\n"
-			"TX num_db=%u\n"
-			"TX num_qmb_int_handled=%u\n"
-			"TX ipa_pipe_number=%u\n",
-			TX_STATS(num_pkts_processed),
-			TX_STATS(ring_stats.ringFull),
-			TX_STATS(ring_stats.ringEmpty),
-			TX_STATS(ring_stats.ringUsageHigh),
-			TX_STATS(ring_stats.ringUsageLow),
-			TX_STATS(ring_stats.RingUtilCount),
-			TX_STATS(gsi_stats.bamFifoFull),
-			TX_STATS(gsi_stats.bamFifoEmpty),
-			TX_STATS(gsi_stats.bamFifoUsageHigh),
-			TX_STATS(gsi_stats.bamFifoUsageLow),
-			TX_STATS(gsi_stats.bamUtilCount),
-			TX_STATS(num_db),
-			TX_STATS(num_qmb_int_handled),
-			TX_STATS(ipa_pipe_number));
-		cnt += nbytes;
-		nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
-			"RX num_pkts_processed=%u\n"
-			"RX ringFull=%u\n"
-			"RX ringEmpty=%u\n"
-			"RX ringUsageHigh=%u\n"
-			"RX ringUsageLow=%u\n"
-			"RX RingUtilCount=%u\n"
-			"RX bamFifoFull=%u\n"
-			"RX bamFifoEmpty=%u\n"
-			"RX bamFifoUsageHigh=%u\n"
-			"RX bamFifoUsageLow=%u\n"
-			"RX bamUtilCount=%u\n"
-			"RX num_db=%u\n"
-			"RX num_qmb_int_handled=%u\n"
-			"RX ipa_pipe_number=%u\n",
-			RX_STATS(num_pkts_processed),
-			RX_STATS(ring_stats.ringFull),
-			RX_STATS(ring_stats.ringEmpty),
-			RX_STATS(ring_stats.ringUsageHigh),
-			RX_STATS(ring_stats.ringUsageLow),
-			RX_STATS(ring_stats.RingUtilCount),
-			RX_STATS(gsi_stats.bamFifoFull),
-			RX_STATS(gsi_stats.bamFifoEmpty),
-			RX_STATS(gsi_stats.bamFifoUsageHigh),
-			RX_STATS(gsi_stats.bamFifoUsageLow),
-			RX_STATS(gsi_stats.bamUtilCount),
-			RX_STATS(num_db),
-			RX_STATS(num_qmb_int_handled),
-			RX_STATS(ipa_pipe_number));
-		cnt += nbytes;
+		for (i = 0; i < IPA_UC_MAX_NTN_TX_CHANNELS; i++) {
+			nbytes = scnprintf(dbg_buff + cnt,
+				IPA_MAX_MSG_LEN - cnt,
+				"TX%d num_pkts_psr=%u\n"
+				"TX%d ringFull=%u\n"
+				"TX%d ringEmpty=%u\n"
+				"TX%d ringUsageHigh=%u\n"
+				"TX%d ringUsageLow=%u\n"
+				"TX%d RingUtilCount=%u\n"
+				"TX%d bamFifoFull=%u\n"
+				"TX%d bamFifoEmpty=%u\n"
+				"TX%d bamFifoUsageHigh=%u\n"
+				"TX%d bamFifoUsageLow=%u\n"
+				"TX%d bamUtilCount=%u\n"
+				"TX%d num_db=%u\n"
+				"TX%d num_qmb_int_handled=%u\n"
+				"TX%d ipa_pipe_number=%u\n",
+				i, TX_STATS(i, num_pkts_processed),
+				i, TX_STATS(i, ring_stats.ringFull),
+				i, TX_STATS(i, ring_stats.ringEmpty),
+				i, TX_STATS(i, ring_stats.ringUsageHigh),
+				i, TX_STATS(i, ring_stats.ringUsageLow),
+				i, TX_STATS(i, ring_stats.RingUtilCount),
+				i, TX_STATS(i, gsi_stats.bamFifoFull),
+				i, TX_STATS(i, gsi_stats.bamFifoEmpty),
+				i, TX_STATS(i, gsi_stats.bamFifoUsageHigh),
+				i, TX_STATS(i, gsi_stats.bamFifoUsageLow),
+				i, TX_STATS(i, gsi_stats.bamUtilCount),
+				i, TX_STATS(i, num_db),
+				i, TX_STATS(i, num_qmb_int_handled),
+				i, TX_STATS(i, ipa_pipe_number));
+			cnt += nbytes;
+		}
+
+		for (i = 0; i < IPA_UC_MAX_NTN_RX_CHANNELS; i++) {
+			nbytes = scnprintf(dbg_buff + cnt,
+				IPA_MAX_MSG_LEN - cnt,
+				"RX%d num_pkts_psr=%u\n"
+				"RX%d ringFull=%u\n"
+				"RX%d ringEmpty=%u\n"
+				"RX%d ringUsageHigh=%u\n"
+				"RX%d ringUsageLow=%u\n"
+				"RX%d RingUtilCount=%u\n"
+				"RX%d bamFifoFull=%u\n"
+				"RX%d bamFifoEmpty=%u\n"
+				"RX%d bamFifoUsageHigh=%u\n"
+				"RX%d bamFifoUsageLow=%u\n"
+				"RX%d bamUtilCount=%u\n"
+				"RX%d num_db=%u\n"
+				"RX%d num_qmb_int_handled=%u\n"
+				"RX%d ipa_pipe_number=%u\n",
+				i, RX_STATS(i, num_pkts_processed),
+				i, RX_STATS(i, ring_stats.ringFull),
+				i, RX_STATS(i, ring_stats.ringEmpty),
+				i, RX_STATS(i, ring_stats.ringUsageHigh),
+				i, RX_STATS(i, ring_stats.ringUsageLow),
+				i, RX_STATS(i, ring_stats.RingUtilCount),
+				i, RX_STATS(i, gsi_stats.bamFifoFull),
+				i, RX_STATS(i, gsi_stats.bamFifoEmpty),
+				i, RX_STATS(i, gsi_stats.bamFifoUsageHigh),
+				i, RX_STATS(i, gsi_stats.bamFifoUsageLow),
+				i, RX_STATS(i, gsi_stats.bamUtilCount),
+				i, RX_STATS(i, num_db),
+				i, RX_STATS(i, num_qmb_int_handled),
+				i, RX_STATS(i, ipa_pipe_number));
+			cnt += nbytes;
+		}
 	} else {
 		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
 				"Fail to read NTN stats\n");

+ 112 - 42
drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
 #include "ipa_i.h"
@@ -63,10 +63,12 @@ struct IpaHwEventLogInfoData_t *uc_event_top_mmio)
  */
 int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats)
 {
-#define TX_STATS(y) stats->tx_ch_stats[0].y = \
+#define TX_STATS(x, y) stats->tx_ch_stats[x].y = \
 	ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio->tx_ch_stats[0].y
-#define RX_STATS(y) stats->rx_ch_stats[0].y = \
-	ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio->rx_ch_stats[0].y
+#define RX_STATS(x, y) stats->rx_ch_stats[x].y = \
+	ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio->rx_ch_stats[x].y
+
+	int i = 0;
 
 	if (unlikely(!ipa3_ctx)) {
 		IPAERR("IPA driver was not initialized\n");
@@ -82,35 +84,39 @@ int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats)
 
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 
-	TX_STATS(num_pkts_processed);
-	TX_STATS(ring_stats.ringFull);
-	TX_STATS(ring_stats.ringEmpty);
-	TX_STATS(ring_stats.ringUsageHigh);
-	TX_STATS(ring_stats.ringUsageLow);
-	TX_STATS(ring_stats.RingUtilCount);
-	TX_STATS(gsi_stats.bamFifoFull);
-	TX_STATS(gsi_stats.bamFifoEmpty);
-	TX_STATS(gsi_stats.bamFifoUsageHigh);
-	TX_STATS(gsi_stats.bamFifoUsageLow);
-	TX_STATS(gsi_stats.bamUtilCount);
-	TX_STATS(num_db);
-	TX_STATS(num_qmb_int_handled);
-	TX_STATS(ipa_pipe_number);
-
-	RX_STATS(num_pkts_processed);
-	RX_STATS(ring_stats.ringFull);
-	RX_STATS(ring_stats.ringEmpty);
-	RX_STATS(ring_stats.ringUsageHigh);
-	RX_STATS(ring_stats.ringUsageLow);
-	RX_STATS(ring_stats.RingUtilCount);
-	RX_STATS(gsi_stats.bamFifoFull);
-	RX_STATS(gsi_stats.bamFifoEmpty);
-	RX_STATS(gsi_stats.bamFifoUsageHigh);
-	RX_STATS(gsi_stats.bamFifoUsageLow);
-	RX_STATS(gsi_stats.bamUtilCount);
-	RX_STATS(num_db);
-	RX_STATS(num_qmb_int_handled);
-	RX_STATS(ipa_pipe_number);
+	for (i = 0; i < IPA_UC_MAX_NTN_TX_CHANNELS; i++) {
+		TX_STATS(i, num_pkts_processed);
+		TX_STATS(i, ring_stats.ringFull);
+		TX_STATS(i, ring_stats.ringEmpty);
+		TX_STATS(i, ring_stats.ringUsageHigh);
+		TX_STATS(i, ring_stats.ringUsageLow);
+		TX_STATS(i, ring_stats.RingUtilCount);
+		TX_STATS(i, gsi_stats.bamFifoFull);
+		TX_STATS(i, gsi_stats.bamFifoEmpty);
+		TX_STATS(i, gsi_stats.bamFifoUsageHigh);
+		TX_STATS(i, gsi_stats.bamFifoUsageLow);
+		TX_STATS(i, gsi_stats.bamUtilCount);
+		TX_STATS(i, num_db);
+		TX_STATS(i, num_qmb_int_handled);
+		TX_STATS(i, ipa_pipe_number);
+	}
+
+	for (i = 0; i < IPA_UC_MAX_NTN_RX_CHANNELS; i++) {
+		RX_STATS(i, num_pkts_processed);
+		RX_STATS(i, ring_stats.ringFull);
+		RX_STATS(i, ring_stats.ringEmpty);
+		RX_STATS(i, ring_stats.ringUsageHigh);
+		RX_STATS(i, ring_stats.ringUsageLow);
+		RX_STATS(i, ring_stats.RingUtilCount);
+		RX_STATS(i, gsi_stats.bamFifoFull);
+		RX_STATS(i, gsi_stats.bamFifoEmpty);
+		RX_STATS(i, gsi_stats.bamFifoUsageHigh);
+		RX_STATS(i, gsi_stats.bamFifoUsageLow);
+		RX_STATS(i, gsi_stats.bamUtilCount);
+		RX_STATS(i, num_db);
+		RX_STATS(i, num_qmb_int_handled);
+		RX_STATS(i, ipa_pipe_number);
+	}
 
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 
@@ -173,6 +179,12 @@ int ipa3_ntn_init(void)
 
 	ipa3_uc_register_handlers(IPA_HW_FEATURE_NTN, &uc_ntn_cbs);
 
+	/* ntn_init */
+	ipa3_ctx->uc_ntn_ctx.uc_ready_cb = NULL;
+	ipa3_ctx->uc_ntn_ctx.priv = NULL;
+	ipa3_ctx->uc_ntn_ctx.ntn_reg_base_ptr_pa_rd = 0x0;
+	ipa3_ctx->uc_ntn_ctx.smmu_mapped = 0;
+
 	return 0;
 }
 
@@ -209,6 +221,7 @@ static int ipa3_uc_send_ntn_setup_pipe_cmd(
 	IPADBG("num_buffers = %d\n", ntn_info->num_buffers);
 	IPADBG("data_buff_size = %d\n", ntn_info->data_buff_size);
 	IPADBG("tail_ptr_base_pa = 0x%pa\n", &ntn_info->ntn_reg_base_ptr_pa);
+	IPADBG("db_mode = %d\n", ntn_info->db_mode);
 	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
 		cmd.size = sizeof(*cmd_data_v4_0);
 	else
@@ -244,6 +257,7 @@ static int ipa3_uc_send_ntn_setup_pipe_cmd(
 	Ntn_params->num_buffers = ntn_info->num_buffers;
 	Ntn_params->ntn_reg_base_ptr_pa = ntn_info->ntn_reg_base_ptr_pa;
 	Ntn_params->data_buff_size = ntn_info->data_buff_size;
+	Ntn_params->db_mode = ntn_info->db_mode;
 	Ntn_params->ipa_pipe_number = ipa_ep_idx;
 	Ntn_params->dir = dir;
 
@@ -262,25 +276,61 @@ static int ipa3_smmu_map_uc_ntn_pipes(struct ipa_ntn_setup_info *params,
 	bool map)
 {
 	struct iommu_domain *smmu_domain;
-	int result;
+	int result = 0;
 	int i;
 	u64 iova;
 	phys_addr_t pa;
 	u64 iova_p;
 	phys_addr_t pa_p;
 	u32 size_p;
+	bool map_unmap_once;
 
 	if (params->data_buff_size > PAGE_SIZE) {
 		IPAERR("invalid data buff size\n");
 		return -EINVAL;
 	}
 
-	result = ipa3_smmu_map_peer_reg(rounddown(params->ntn_reg_base_ptr_pa,
-		PAGE_SIZE), map, IPA_SMMU_CB_UC);
-	if (result) {
-		IPAERR("failed to %s uC regs %d\n",
-			map ? "map" : "unmap", result);
-		goto fail;
+	/* only map/unmap once the ntn_reg_base_ptr_pa */
+	map_unmap_once = (map && ipa3_ctx->uc_ntn_ctx.smmu_mapped == 0)
+	|| (!map && ipa3_ctx->uc_ntn_ctx.smmu_mapped == 1);
+
+	IPADBG(" %s uC regs, smmu_mapped %d\n",
+		map ? "map" : "unmap", ipa3_ctx->uc_ntn_ctx.smmu_mapped);
+
+	if (map_unmap_once) {
+		result = ipa3_smmu_map_peer_reg(rounddown(
+				params->ntn_reg_base_ptr_pa, PAGE_SIZE),
+				map, IPA_SMMU_CB_UC);
+		if (result) {
+			IPAERR("failed to %s uC regs %d\n",
+				map ? "map" : "unmap", result);
+			goto fail;
+		}
+		/* backup the ntn_reg_base_ptr_pa_r */
+		ipa3_ctx->uc_ntn_ctx.ntn_reg_base_ptr_pa_rd =
+			rounddown(params->ntn_reg_base_ptr_pa,
+			PAGE_SIZE);
+		IPADBG(" %s ntn_reg_base_ptr_pa regs 0X%0x smmu_mapped %d\n",
+			map ? "map" : "unmap",
+			(unsigned long long)
+			ipa3_ctx->uc_ntn_ctx.ntn_reg_base_ptr_pa_rd,
+			ipa3_ctx->uc_ntn_ctx.smmu_mapped);
+	}
+	/* update smmu_mapped reference count */
+	if (map) {
+		ipa3_ctx->uc_ntn_ctx.smmu_mapped++;
+		IPADBG("uc_ntn_ctx.smmu_mapped %d\n",
+			ipa3_ctx->uc_ntn_ctx.smmu_mapped);
+	} else {
+		if (ipa3_ctx->uc_ntn_ctx.smmu_mapped == 0) {
+			IPAERR("Invalid smmu_mapped %d\n",
+				ipa3_ctx->uc_ntn_ctx.smmu_mapped);
+			goto fail;
+		} else {
+			ipa3_ctx->uc_ntn_ctx.smmu_mapped--;
+			IPADBG("uc_ntn_ctx.smmu_mapped %d\n",
+				ipa3_ctx->uc_ntn_ctx.smmu_mapped);
+		}
 	}
 
 	if (params->smmu_enabled) {
@@ -473,7 +523,10 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
 		goto fail_disable_dp_ul;
 	}
 	ipa3_install_dflt_flt_rules(ipa_ep_idx_ul);
-	outp->ul_uc_db_pa = IPA_UC_NTN_DB_PA_RX;
+	/* Rx: IPA_UC_MAILBOX_m_n m = 1, n =3 mmio*/
+	outp->ul_uc_db_iomem = ipa3_ctx->mmio +
+		ipahal_get_reg_mn_ofst(IPA_UC_MAILBOX_m_n,
+		1, 3);
 	ep_ul->uc_offload_state |= IPA_UC_OFFLOAD_CONNECTED;
 	IPADBG("client %d (ep: %d) connected\n", in->ul.client,
 		ipa_ep_idx_ul);
@@ -511,7 +564,10 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
 		result = -EFAULT;
 		goto fail_disable_dp_dl;
 	}
-	outp->dl_uc_db_pa = IPA_UC_NTN_DB_PA_TX;
+	/* Tx: IPA_UC_MAILBOX_m_n m = 1, n =4 mmio */
+	outp->dl_uc_db_iomem = ipa3_ctx->mmio +
+		ipahal_get_reg_mn_ofst(IPA_UC_MAILBOX_m_n,
+		1, 4);
 	ep_dl->uc_offload_state |= IPA_UC_OFFLOAD_CONNECTED;
 
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
@@ -551,6 +607,20 @@ int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul,
 	IPADBG("ep_ul = %d\n", ipa_ep_idx_ul);
 	IPADBG("ep_dl = %d\n", ipa_ep_idx_dl);
 
+	if (ipa_ep_idx_ul == IPA_EP_NOT_ALLOCATED ||
+		ipa_ep_idx_ul >= IPA3_MAX_NUM_PIPES) {
+		IPAERR("ipa_ep_idx_ul %d invalid\n",
+			ipa_ep_idx_ul);
+		return -EFAULT;
+	}
+
+	if (ipa_ep_idx_dl == IPA_EP_NOT_ALLOCATED ||
+		ipa_ep_idx_dl >= IPA3_MAX_NUM_PIPES) {
+		IPAERR("ep ipa_ep_idx_dl %d invalid\n",
+			ipa_ep_idx_dl);
+		return -EFAULT;
+	}
+
 	ep_ul = &ipa3_ctx->ep[ipa_ep_idx_ul];
 	ep_dl = &ipa3_ctx->ep[ipa_ep_idx_dl];
 

+ 8 - 3
drivers/platform/msm/ipa/ipa_v3/ipa_uc_offload_i.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _IPA_UC_OFFLOAD_I_H_
@@ -13,8 +13,8 @@
  * Neutrino protocol related data structures
  */
 
-#define IPA_UC_MAX_NTN_TX_CHANNELS 1
-#define IPA_UC_MAX_NTN_RX_CHANNELS 1
+#define IPA_UC_MAX_NTN_TX_CHANNELS 2
+#define IPA_UC_MAX_NTN_RX_CHANNELS 2
 
 #define IPA_NTN_TX_DIR 1
 #define IPA_NTN_RX_DIR 2
@@ -287,6 +287,8 @@ struct ipa3_uc_ntn_ctx {
 	struct Ipa3HwStatsNTNInfoData_t *ntn_uc_stats_mmio;
 	void *priv;
 	ipa_uc_ready_cb uc_ready_cb;
+	phys_addr_t ntn_reg_base_ptr_pa_rd;
+	u32 smmu_mapped;
 };
 
 /**
@@ -365,6 +367,9 @@ struct Ipa3HwNtnSetUpCmdData_t {
 	u8  ipa_pipe_number;
 	u8  dir;
 	u16 data_buff_size;
+	u8 db_mode;
+	u8 reserved1;
+	u16 reserved2;
 
 } __packed;