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

Commit 48afa058 authored by Skylar Chang's avatar Skylar Chang
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>
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
parent 1cc4edf0
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -3056,6 +3056,18 @@ int ipa_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
	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
@@ -398,6 +398,9 @@ struct ipa_api_controller {

	int (*ipa_disable_wdi3_pipes)(int ipa_ep_idx_tx,
		int ipa_ep_idx_rx);

	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
@@ -4492,30 +4492,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;
	}

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

	return 0;
}

@@ -4687,7 +4698,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;
@@ -5465,7 +5479,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
@@ -1034,11 +1034,6 @@ struct ipa3_ready_cb_info {
	void *user_data;
};

struct ipa_tz_unlock_reg_info {
	u64 reg_addr;
	u32 size;
};

struct ipa_dma_task_info {
	struct ipa_mem_buffer mem;
	struct ipahal_imm_cmd_pyld *cmd_pyld;
@@ -2249,4 +2244,5 @@ int ipa3_allocate_dma_task_for_gsi(void);
void ipa3_free_dma_task_for_gsi(void);
int ipa3_set_clock_plan_from_pm(int idx);
void __ipa_gsi_irq_rx_scedule_poll(struct ipa3_sys_context *sys);
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
@@ -4501,6 +4501,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type,
	api_ctrl->ipa_disconn_wdi3_pipes = ipa3_disconn_wdi3_pipes;
	api_ctrl->ipa_enable_wdi3_pipes = ipa3_enable_wdi3_pipes;
	api_ctrl->ipa_disable_wdi3_pipes = ipa3_disable_wdi3_pipes;
	api_ctrl->ipa_tz_unlock_reg = ipa3_tz_unlock_reg;

	return 0;
}
Loading