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

Commit ad4df5cd authored by Neeti Desai's avatar Neeti Desai
Browse files

msm: ocmem: Call restore_sec_config() after every power collapse



As the QRIB is enabled, after every power collapse of ocmem, the
QRIB is reset to the maximum security state. Due to this the apps
processor cannot access the ocmem register space.

The restore_sec_config() scm call needs to be called before any
register is accessed after a power collapse to ensure that the
security configuration is restored. The clocks need to be turned
on before every call that is made into TZ to ensure that there
is no power collapse.

CRs-Fixed: 651324, 660089
Change-Id: Ieb6b635142057e219de29e811c93749f6500cec5
Signed-off-by: default avatarNeeti Desai <neetid@codeaurora.org>
parent 0b72362f
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -795,6 +795,7 @@ static int msm_ocmem_probe(struct platform_device *pdev)
	struct device   *dev = &pdev->dev;
	struct clk *ocmem_core_clk = NULL;
	struct clk *ocmem_iface_clk = NULL;
	int rc;

	ocmem_core_clk = devm_clk_get(dev, "core_clk");

@@ -835,10 +836,25 @@ static int msm_ocmem_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, ocmem_pdata);

	rc = ocmem_enable_core_clock();

	if (rc < 0)
		goto core_clk_fail;

	rc = ocmem_enable_iface_clock();

	if (rc < 0)
		goto iface_clk_fail;

	/* Parameter to be updated based on TZ */
	/* Allow the OCMEM CSR to be programmed */
	if (ocmem_enable_sec_program(OCMEM_SECURE_DEV_ID))
	if (ocmem_restore_sec_program(OCMEM_SECURE_DEV_ID)) {
		ocmem_disable_iface_clock();
		ocmem_disable_core_clock();
		return -EBUSY;
	}
	ocmem_disable_iface_clock();
	ocmem_disable_core_clock();

	if (ocmem_debugfs_init(pdev))
		dev_err(dev, "ocmem: No debugfs node available\n");
@@ -866,6 +882,11 @@ static int msm_ocmem_probe(struct platform_device *pdev)
	probe_done = true;
	dev_dbg(dev, "initialized successfully\n");
	return 0;

iface_clk_fail:
	ocmem_disable_core_clock();
core_clk_fail:
	return rc;
}

static int msm_ocmem_remove(struct platform_device *pdev)
+31 −13
Original line number Diff line number Diff line
@@ -583,7 +583,7 @@ static int do_unlock(enum ocmem_client id, unsigned long offset,
	return 0;
}

int ocmem_enable_sec_program(int sec_id)
int ocmem_restore_sec_program(int sec_id)
{
	return 0;
}
@@ -702,7 +702,7 @@ int ocmem_disable_dump(enum ocmem_client id, unsigned long offset,
	return rc;
}

int ocmem_enable_sec_program(int sec_id)
int ocmem_restore_sec_program(int sec_id)
{
	int rc, scm_ret = 0;
	struct msm_scm_sec_cfg {
@@ -953,7 +953,6 @@ static int switch_power_state(int id, unsigned long offset, unsigned long len,
	unsigned end_m = num_banks;
	unsigned long region_offset = 0;
	struct ocmem_hw_region *region;
	int rc = 0;

	if (offset < 0)
		return -EINVAL;
@@ -974,14 +973,6 @@ static int switch_power_state(int id, unsigned long offset, unsigned long len,
		(region_end >= num_regions))
			return -EINVAL;

	rc = ocmem_enable_core_clock();

	if (rc < 0) {
		pr_err("ocmem: Power transistion request for client %s (id: %d) failed\n",
				get_name(id), id);
		return rc;
	}

	mutex_lock(&region_ctrl_lock);

	for (i = region_start; i <= region_end; i++) {
@@ -1035,11 +1026,10 @@ static int switch_power_state(int id, unsigned long offset, unsigned long len,

	}
	mutex_unlock(&region_ctrl_lock);
	ocmem_disable_core_clock();

	return 0;
invalid_transition:
	mutex_unlock(&region_ctrl_lock);
	ocmem_disable_core_clock();
	pr_err("ocmem_core: Invalid state transition detected for %d\n", id);
	pr_err("ocmem_core: Offset %lx Len %lx curr_state %x new_state %x\n",
			offset, len, curr_state, new_state);
@@ -1122,9 +1112,37 @@ static int ocmem_power_show_hw_state(struct seq_file *f, void *dummy)

static int ocmem_power_show(struct seq_file *f, void *dummy)
{
	int rc = 0;

	rc = ocmem_enable_core_clock();

	if (rc < 0)
		goto core_clock_fail;

	rc = ocmem_enable_iface_clock();

	if (rc < 0)
		goto iface_clock_fail;

	rc = ocmem_restore_sec_program(OCMEM_SECURE_DEV_ID);
	if (rc < 0) {
		pr_err("ocmem: Failed to restore security programming\n");
		goto restore_config_fail;
	}
	ocmem_power_show_sw_state(f, dummy);
	ocmem_power_show_hw_state(f, dummy);

	ocmem_disable_iface_clock();
	ocmem_disable_core_clock();

	return 0;

restore_config_fail:
	ocmem_disable_iface_clock();
iface_clock_fail:
	ocmem_disable_core_clock();
core_clock_fail:
	return -EINVAL;
}

static int ocmem_power_open(struct inode *inode, struct file *file)
+1 −1
Original line number Diff line number Diff line
@@ -205,7 +205,7 @@ int ocmem_notifier_init(void);
int check_notifier(int);
const char *get_name(int);
int get_tz_id(int);
int ocmem_enable_sec_program(int);
int ocmem_restore_sec_program(int);
int ocmem_enable_dump(enum ocmem_client, unsigned long, unsigned long);
int ocmem_disable_dump(enum ocmem_client, unsigned long, unsigned long);
bool is_probe_done(void);
+70 −19
Original line number Diff line number Diff line
@@ -625,17 +625,11 @@ static int process_map(struct ocmem_req *req, unsigned long start,
{
	int rc = 0;

	rc = ocmem_enable_core_clock();

	if (rc < 0)
		goto core_clock_fail;

	rc = ocmem_restore_sec_program(OCMEM_SECURE_DEV_ID);

	if (is_iface_access(req->owner)) {
		rc = ocmem_enable_iface_clock();

		if (rc < 0)
			goto iface_clock_fail;
	if (rc < 0) {
		pr_err("ocmem: Failed to restore security programming\n");
		goto lock_failed;
	}

	rc = ocmem_lock(req->owner, phys_to_offset(req->req_start), req->req_sz,
@@ -661,11 +655,6 @@ static int process_map(struct ocmem_req *req, unsigned long start,
process_map_fail:
	ocmem_unlock(req->owner, phys_to_offset(req->req_start), req->req_sz);
lock_failed:
	if (is_iface_access(req->owner))
		ocmem_disable_iface_clock();
iface_clock_fail:
	ocmem_disable_core_clock();
core_clock_fail:
	pr_err("ocmem: Failed to map ocmem request\n");
	return rc;
}
@@ -689,9 +678,6 @@ static int process_unmap(struct ocmem_req *req, unsigned long start,
		goto unlock_failed;
	}

	if (is_iface_access(req->owner))
		ocmem_disable_iface_clock();
	ocmem_disable_core_clock();
	pr_debug("ocmem: Unmapped request %p\n", req);
	return 0;

@@ -1336,9 +1322,21 @@ static int process_grow(struct ocmem_req *req)
	if (rc < 0)
		return -EINVAL;

	rc = ocmem_enable_core_clock();

	if (rc < 0)
		goto core_clock_fail;

	if (is_iface_access(req->owner)) {
		rc = ocmem_enable_iface_clock();

		if (rc < 0)
			goto iface_clock_fail;
	}

	rc = process_map(req, req->req_start, req->req_end);
	if (rc < 0)
		return -EINVAL;
		goto map_error;

	offset = phys_to_offset(req->req_start);

@@ -1357,7 +1355,14 @@ static int process_grow(struct ocmem_req *req)
		BUG();
	}
	return 0;

power_ctl_error:
map_error:
if (is_iface_access(req->owner))
	ocmem_disable_iface_clock();
iface_clock_fail:
	ocmem_disable_core_clock();
core_clock_fail:
	return -EINVAL;
}

@@ -1527,6 +1532,10 @@ int process_free(int id, struct ocmem_handle *handle)
				}
			}

			if (is_iface_access(req->owner))
				ocmem_disable_iface_clock();
			ocmem_disable_core_clock();

			rc = do_free(req);
			if (rc < 0) {
				pr_err("ocmem: Failed to free %p\n", req);
@@ -1547,6 +1556,9 @@ int process_free(int id, struct ocmem_handle *handle)
				pr_err("Failed to switch OFF memory macros\n");
				goto free_fail;
			}
			if (is_iface_access(req->owner))
				ocmem_disable_iface_clock();
			ocmem_disable_core_clock();
		}

		/* free the allocation */
@@ -1649,6 +1661,10 @@ int process_drop(int id, struct ocmem_handle *handle,
		rc = process_unmap(req, req->req_start, req->req_end);
		if (rc < 0)
			return -EINVAL;

		if (is_iface_access(req->owner))
			ocmem_disable_iface_clock();
		ocmem_disable_core_clock();
	} else
		return -EINVAL;

@@ -1759,6 +1775,9 @@ int process_shrink(int id, struct ocmem_handle *handle, unsigned long size)
			rc = process_unmap(req, req->req_start, req->req_end);
			if (rc < 0)
				goto shrink_fail;
			if (is_iface_access(req->owner))
				ocmem_disable_iface_clock();
			ocmem_disable_core_clock();
		}
		rc = do_free(req);
		if (rc < 0)
@@ -2245,6 +2264,17 @@ int process_allocate(int id, struct ocmem_handle *handle,

	if (req->req_sz != 0) {

		rc = ocmem_enable_core_clock();

		if (rc < 0)
			goto core_clock_fail;

		if (is_iface_access(req->owner)) {
			rc = ocmem_enable_iface_clock();

			if (rc < 0)
				goto iface_clock_fail;
		}
		rc = process_map(req, req->req_start, req->req_end);
		if (rc < 0)
			goto map_error;
@@ -2266,6 +2296,11 @@ power_ctl_error:
map_error:
	handle->req = NULL;
	do_free(req);
	if (is_iface_access(req->owner))
		ocmem_disable_iface_clock();
iface_clock_fail:
	ocmem_disable_core_clock();
core_clock_fail:
do_allocate_error:
	ocmem_destroy_req(req);
	return -EINVAL;
@@ -2294,6 +2329,17 @@ int process_delayed_allocate(struct ocmem_req *req)
	inc_ocmem_stat(zone_of(req), NR_ASYNC_ALLOCATIONS);

	if (req->req_sz != 0) {
		rc = ocmem_enable_core_clock();

		if (rc < 0)
			goto core_clock_fail;

		if (is_iface_access(req->owner)) {
			rc = ocmem_enable_iface_clock();

			if (rc < 0)
				goto iface_clock_fail;
		}

		rc = process_map(req, req->req_start, req->req_end);
		if (rc < 0)
@@ -2324,6 +2370,11 @@ power_ctl_error:
map_error:
	handle->req = NULL;
	do_free(req);
	if (is_iface_access(req->owner))
		ocmem_disable_iface_clock();
iface_clock_fail:
	ocmem_disable_core_clock();
core_clock_fail:
do_allocate_error:
	ocmem_destroy_req(req);
	return -EINVAL;