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

Commit 73dbb11d authored by Gidon Studinski's avatar Gidon Studinski
Browse files

msm: ipa3: add an API to unlock PCIe memory regions



TZ now locks all PCIe accesses by default, This API allows to
dynamically unlock specific memory regions over PCIe bus. The unlock
mechanism is required by MHI and WLAN drivers.

Change-Id: Ia44fe2ad4b7b6fe4efef7807e60f24b6f12e4398
Signed-off-by: default avatarGidon Studinski <gidons@codeaurora.org>
parent f6a9d356
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -2758,6 +2758,18 @@ int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul,
	return ret;
}

/**
 * ipa_tz_unlock_reg() - Allow AP access to memory regions controlled by TZ
 */
int ipa_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_tz_unlock_reg, reg_info, num_regs);

	return ret;
}

static const struct dev_pm_ops ipa_pm_ops = {
	.suspend_noirq = ipa_ap_suspend,
	.resume_noirq = ipa_ap_resume,
+3 −0
Original line number Diff line number Diff line
@@ -365,6 +365,9 @@ struct ipa_api_controller {

	int (*ipa_tear_down_uc_offload_pipes)(int ipa_ep_idx_ul,
		int ipa_ep_idx_dl);

	int (*ipa_tz_unlock_reg)(struct ipa_tz_unlock_reg_info *reg_info,
		u16 num_regs);
};

#ifdef CONFIG_IPA
+52 −38
Original line number Diff line number Diff line
@@ -4210,30 +4210,41 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf,
	return count;
}

static int ipa3_tz_unlock_reg(struct ipa3_context *ipa3_ctx)
/**
 * ipa3_tz_unlock_reg - Unlocks memory regions so that they become accessible
 *	from AP.
 * @reg_info - Pointer to array of memory regions to unlock
 * @num_regs - Number of elements in the array
 *
 * Converts the input array of regions to a struct that TZ understands and
 * issues an SCM call.
 * Also flushes the memory cache to DDR in order to make sure that TZ sees the
 * correct data structure.
 *
 * Returns: 0 on success, negative on failure
 */
int ipa3_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs)
{
	int i, size, ret, resp;
	struct tz_smmu_ipa_protect_region_iovec_s *ipa_tz_unlock_vec;
	struct tz_smmu_ipa_protect_region_s cmd_buf;

	if (ipa3_ctx && ipa3_ctx->ipa_tz_unlock_reg_num > 0) {
		size = ipa3_ctx->ipa_tz_unlock_reg_num *
			sizeof(struct tz_smmu_ipa_protect_region_iovec_s);
	if (reg_info ==  NULL || num_regs == 0) {
		IPAERR("Bad parameters\n");
		return -EFAULT;
	}

	size = num_regs * sizeof(struct tz_smmu_ipa_protect_region_iovec_s);
	ipa_tz_unlock_vec = kzalloc(PAGE_ALIGN(size), GFP_KERNEL);
	if (ipa_tz_unlock_vec == NULL)
		return -ENOMEM;

		for (i = 0; i < ipa3_ctx->ipa_tz_unlock_reg_num; i++) {
			ipa_tz_unlock_vec[i].input_addr =
				ipa3_ctx->ipa_tz_unlock_reg[i].reg_addr ^
				(ipa3_ctx->ipa_tz_unlock_reg[i].reg_addr &
				0xFFF);
			ipa_tz_unlock_vec[i].output_addr =
				ipa3_ctx->ipa_tz_unlock_reg[i].reg_addr ^
				(ipa3_ctx->ipa_tz_unlock_reg[i].reg_addr &
				0xFFF);
			ipa_tz_unlock_vec[i].size =
				ipa3_ctx->ipa_tz_unlock_reg[i].size;
	for (i = 0; i < num_regs; i++) {
		ipa_tz_unlock_vec[i].input_addr = reg_info[i].reg_addr ^
			(reg_info[i].reg_addr & 0xFFF);
		ipa_tz_unlock_vec[i].output_addr = reg_info[i].reg_addr ^
			(reg_info[i].reg_addr & 0xFFF);
		ipa_tz_unlock_vec[i].size = reg_info[i].size;
		ipa_tz_unlock_vec[i].attr = IPA_TZ_UNLOCK_ATTRIBUTE;
	}

@@ -4253,7 +4264,7 @@ static int ipa3_tz_unlock_reg(struct ipa3_context *ipa3_ctx)
		return -EFAULT;
	}
	kfree(ipa_tz_unlock_vec);
	}

	return 0;
}

@@ -4361,7 +4372,10 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	}

	/* unlock registers for uc */
	ipa3_tz_unlock_reg(ipa3_ctx);
	result = ipa3_tz_unlock_reg(ipa3_ctx->ipa_tz_unlock_reg,
				    ipa3_ctx->ipa_tz_unlock_reg_num);
	if (result)
		IPAERR("Failed to unlock memory region using TZ\n");

	/* default aggregation parameters */
	ipa3_ctx->aggregation_type = IPA_MBIM_16;
@@ -5118,7 +5132,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
				ipa_tz_unlock_reg[pos++];
			ipa_drv_res->ipa_tz_unlock_reg[i].size =
				ipa_tz_unlock_reg[pos++];
			IPADBG("tz unlock reg %d: addr 0x%pa size %d\n", i,
			IPADBG("tz unlock reg %d: addr 0x%pa size %llu\n", i,
				&ipa_drv_res->ipa_tz_unlock_reg[i].reg_addr,
				ipa_drv_res->ipa_tz_unlock_reg[i].size);
		}
+1 −5
Original line number Diff line number Diff line
@@ -1066,11 +1066,6 @@ struct ipa3_ready_cb_info {
	void *user_data;
};

struct ipa_tz_unlock_reg_info {
	u64 reg_addr;
	u32 size;
};

/**
 * struct ipa3_context - IPA context
 * @class: pointer to the struct class
@@ -2020,4 +2015,5 @@ int ipa3_smmu_map_peer_buff(u64 iova, phys_addr_t phys_addr,
	u32 size, bool map);
struct dentry *ipa_debugfs_get_root(void);
bool ipa3_is_msm_device(void);
int ipa3_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs);
#endif /* _IPA3_I_H_ */
+1 −0
Original line number Diff line number Diff line
@@ -4698,6 +4698,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type,
	api_ctrl->ipa_setup_uc_ntn_pipes = ipa3_setup_uc_ntn_pipes;
	api_ctrl->ipa_tear_down_uc_offload_pipes =
		ipa3_tear_down_uc_offload_pipes;
	api_ctrl->ipa_tz_unlock_reg = ipa3_tz_unlock_reg;

	return 0;
}
Loading