Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 307064fb authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa3: add v2x ethernet support"

parents 79f65f43 bc888f07
Loading
Loading
Loading
Loading
+77 −16
Original line number Diff line number Diff line
@@ -130,6 +130,10 @@ static int ipa_uc_offload_ntn_register_pm_client(
	struct ipa_pm_register_params params;

	memset(&params, 0, sizeof(params));

	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;
@@ -139,11 +143,16 @@ static int ipa_uc_offload_ntn_register_pm_client(
		IPA_UC_OFFLOAD_ERR("fail to register with PM %d\n", res);
		return res;
	}

	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 assoc. PM (%d) Prot:%d\n",
			res, ntn_ctx->proto);
		ipa_pm_deregister(ntn_ctx->pm_hdl);
		ntn_ctx->pm_hdl = ~0;
		return res;
@@ -369,21 +378,43 @@ int ipa_uc_offload_reg_intf(
		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;
		if (ipa_pm_is_used())
			ret = ipa_uc_offload_ntn_register_pm_client(ctx);
		else
			IPA_UC_OFFLOAD_ERR("Not support uc_ntn_v2x ipa_rm\n");

		if (!ret)
			outp->clnt_hndl = IPA_UC_NTN_V2X;
		else
			IPA_UC_OFFLOAD_ERR("fail to create rm resource\n");
		/* set to initialized state */
		ctx->state = IPA_UC_OFFLOAD_STATE_INITIALIZED;
	}

	return ret;
}
EXPORT_SYMBOL(ipa_uc_offload_reg_intf);

/* only IPA_UC_NTN might use for ipa_rm */
static int ipa_uc_ntn_cons_release(void)
{
	return 0;
}

/* only IPA_UC_NTN might use for ipa_rm */
static int ipa_uc_ntn_cons_request(void)
{
	int ret = 0;
@@ -506,6 +537,12 @@ int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp,
			return result;
		}
	} else {
		/* not support v2x*/
		if (ntn_ctx->proto == IPA_UC_NTN_V2X) {
			IPA_UC_OFFLOAD_ERR("Not support uc_ntn_v2x ipa_rm\n");
			return -EINVAL;
		}

		result = ipa_rm_add_dependency(IPA_RM_RESOURCE_ETHERNET_PROD,
			IPA_RM_RESOURCE_APPS_CONS);
		if (result) {
@@ -579,7 +616,7 @@ int ipa_uc_offload_conn_pipes(struct ipa_uc_offload_conn_in_params *inp,

	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;
	}

@@ -593,6 +630,7 @@ int ipa_uc_offload_conn_pipes(struct ipa_uc_offload_conn_in_params *inp,
			sizeof(struct ipa_ntn_conn_in_params));

	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);
@@ -618,6 +656,17 @@ int ipa_set_perf_profile(struct ipa_perf_profile *profile)
		return -EINVAL;
	}

	if (ipa_pm_is_used()) {
		return ipa_pm_set_throughput(
				ipa_uc_offload_ctx[profile->proto]->pm_hdl,
				profile->max_supported_bw_mbps);
	} else {
		if (profile->proto == IPA_UC_NTN_V2X) {
			IPA_UC_OFFLOAD_ERR("not support NTN_v2x for ipa_rm\n");
			return -EFAULT;
		}
	}

	rm_profile.max_supported_bandwidth_mbps =
		profile->max_supported_bw_mbps;

@@ -629,17 +678,10 @@ int ipa_set_perf_profile(struct ipa_perf_profile *profile)
		IPA_UC_OFFLOAD_ERR("not supported\n");
		return -EINVAL;
	}

	if (ipa_pm_is_used())
		return ipa_pm_set_throughput(
			ipa_uc_offload_ctx[IPA_UC_NTN]->pm_hdl,
			profile->max_supported_bw_mbps);

	if (ipa_rm_set_perf_profile(resource_name, &rm_profile)) {
		IPA_UC_OFFLOAD_ERR("fail to setup rm perf profile\n");
		return -EFAULT;
	}

	return 0;
}
EXPORT_SYMBOL(ipa_set_perf_profile);
@@ -664,6 +706,12 @@ static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx)
			return -EFAULT;
		}
	} else {
		/* not support ntn_v2x to use rm */
		if (ntn_ctx->proto == IPA_UC_NTN_V2X) {
			IPA_UC_OFFLOAD_ERR("not support NTN_v2x for ipa_rm\n");
			return -EFAULT;
		}

		ret = ipa_rm_release_resource(IPA_RM_RESOURCE_ETHERNET_PROD);
		if (ret) {
			IPA_UC_OFFLOAD_ERR("fail release ETHERNET_PROD: %d\n",
@@ -679,8 +727,13 @@ static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx)
		}
	}

	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 = ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl,
		&ntn_ctx->conn);
	if (ret) {
@@ -719,6 +772,7 @@ int ipa_uc_offload_disconn_pipes(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;
@@ -805,6 +859,13 @@ int ipa_uc_offload_cleanup(u32 clnt_hdl)
	case IPA_UC_NTN:
		ret = ipa_uc_ntn_cleanup(offload_ctx);
		break;
	case IPA_UC_NTN_V2X:
		/* only clean-up pm_handle */
		if (ipa_pm_is_used())
			ipa_uc_offload_ntn_deregister_pm_client(offload_ctx);
		else
			IPA_UC_OFFLOAD_ERR("Not support uc_ntn_v2x ipa_rm\n");
		break;

	default:
		IPA_UC_OFFLOAD_ERR("Invalid Proto :%d\n", clnt_hdl);
@@ -840,7 +901,7 @@ int ipa_uc_offload_reg_rdyCB(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 = ipa_ntn_uc_reg_rdyCB(inp->notify, inp->priv);

	if (ret == -EEXIST) {
@@ -855,7 +916,7 @@ EXPORT_SYMBOL(ipa_uc_offload_reg_rdyCB);

void ipa_uc_offload_dereg_rdyCB(enum ipa_uc_offload_proto proto)
{
	if (proto == IPA_UC_NTN)
	if (proto == IPA_UC_NTN || proto == IPA_UC_NTN_V2X)
		ipa_ntn_uc_dereg_rdyCB();
}
EXPORT_SYMBOL(ipa_uc_offload_dereg_rdyCB);
+1 −1
Original line number Diff line number Diff line
@@ -7152,7 +7152,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
Original line number Diff line number Diff line
@@ -1397,76 +1397,83 @@ static ssize_t ipa3_read_wstats(struct file *file, char __user *ubuf,
static ssize_t ipa3_read_ntn(struct file *file, char __user *ubuf,
		size_t count, loff_t *ppos)
{
#define TX_STATS(y) \
	ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio->tx_ch_stats[0].y
#define RX_STATS(y) \
	ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio->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));
		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");
+110 −45
Original line number Diff line number Diff line
@@ -69,10 +69,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 = \
	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 TX_STATS(x, y) stats->tx_ch_stats[x].y = \
	ipa3_ctx->uc_ntn_ctx.ntn_uc_stats_mmio->tx_ch_stats[x].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");
@@ -87,36 +89,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();

@@ -177,6 +182,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;
}

@@ -213,6 +224,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
@@ -248,6 +260,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;

@@ -263,7 +276,7 @@ static int ipa3_uc_send_ntn_setup_pipe_cmd(
}

static int ipa3_smmu_map_uc_ntn_pipes(struct ipa_ntn_setup_info *params,
	bool map, bool map_unmap_once)
	bool map)
{
	struct iommu_domain *smmu_domain;
	int result;
@@ -273,12 +286,20 @@ static int ipa3_smmu_map_uc_ntn_pipes(struct ipa_ntn_setup_info *params,
	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;
	}

	/* 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),
@@ -288,7 +309,33 @@ static int ipa3_smmu_map_uc_ntn_pipes(struct ipa_ntn_setup_info *params,
					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) {
		IPADBG("smmu is enabled on EMAC\n");
		result = ipa3_smmu_map_peer_buff((u64)params->ring_base_iova,
@@ -397,7 +444,6 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
	int ipa_ep_idx_ul;
	int ipa_ep_idx_dl;
	int result = 0;
	bool unmapped = false;

	if (in == NULL) {
		IPAERR("invalid input\n");
@@ -451,7 +497,7 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
		goto fail;
	}

	result = ipa3_smmu_map_uc_ntn_pipes(&in->ul, true, true);
	result = ipa3_smmu_map_uc_ntn_pipes(&in->ul, true);
	if (result) {
		IPAERR("failed to map SMMU for UL %d\n", result);
		goto fail;
@@ -471,7 +517,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);
@@ -490,7 +539,7 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
		goto fail_disable_dp_ul;
	}

	result = ipa3_smmu_map_uc_ntn_pipes(&in->dl, true, false);
	result = ipa3_smmu_map_uc_ntn_pipes(&in->dl, true);
	if (result) {
		IPAERR("failed to map SMMU for DL %d\n", result);
		goto fail_disable_dp_ul;
@@ -509,7 +558,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();
@@ -521,12 +573,11 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
fail_disable_dp_dl:
	ipa3_disable_data_path(ipa_ep_idx_dl);
fail_smmu_unmap_dl:
	ipa3_smmu_map_uc_ntn_pipes(&in->dl, false, true);
	unmapped = true;
	ipa3_smmu_map_uc_ntn_pipes(&in->dl, false);
fail_disable_dp_ul:
	ipa3_disable_data_path(ipa_ep_idx_ul);
fail_smmu_unmap_ul:
	ipa3_smmu_map_uc_ntn_pipes(&in->ul, false, !unmapped);
	ipa3_smmu_map_uc_ntn_pipes(&in->ul, false);
fail:
	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
	return result;
@@ -549,6 +600,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];

@@ -606,7 +671,7 @@ int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul,
	}

	/* unmap the DL pipe */
	result = ipa3_smmu_map_uc_ntn_pipes(&params->dl, false, false);
	result = ipa3_smmu_map_uc_ntn_pipes(&params->dl, false);
	if (result) {
		IPAERR("failed to unmap SMMU for DL %d\n", result);
		goto fail;
@@ -627,7 +692,7 @@ int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul,
	}

	/* unmap the UL pipe */
	result = ipa3_smmu_map_uc_ntn_pipes(&params->ul, false, true);
	result = ipa3_smmu_map_uc_ntn_pipes(&params->ul, false);
	if (result) {
		IPAERR("failed to unmap SMMU for UL %d\n", result);
		goto fail;
+8 −4
Original line number Diff line number Diff line
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -20,8 +20,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
@@ -283,6 +283,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;
};

/**
@@ -361,7 +363,9 @@ struct Ipa3HwNtnSetUpCmdData_t {
	u8  ipa_pipe_number;
	u8  dir;
	u16 data_buff_size;

	u8 db_mode;
	u8 reserved1;
	u16 reserved2;
} __packed;

/**
Loading