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

Commit 6db7eb5f authored by Benjamin Chan's avatar Benjamin Chan Committed by Alan Kwong
Browse files

msm: sde: Add mutex lock for debug buffer access in rotator



Adding mutex lock access protection to debug buffer for SDE rotator. The
buffer can be shared between multiple processes, and it is possible that
one process try to free the buffer while another process is still
accessing it.

CRs-Fixed: 2003129
Change-Id: Ib20767f02ba7f14fb972d5c50ab264b2309a1ec2
Signed-off-by: default avatarBenjamin Chan <bkchan@codeaurora.org>
parent e2101f10
Loading
Loading
Loading
Loading
+34 −5
Original line number Diff line number Diff line
@@ -996,11 +996,14 @@ static int sde_rotator_debug_base_release(struct inode *inode,
{
	struct sde_rotator_debug_base *dbg = file->private_data;

	if (dbg && dbg->buf) {
	if (dbg) {
		mutex_lock(&dbg->buflock);
		kfree(dbg->buf);
		dbg->buf_len = 0;
		dbg->buf = NULL;
		mutex_unlock(&dbg->buflock);
	}

	return 0;
}

@@ -1032,8 +1035,10 @@ static ssize_t sde_rotator_debug_base_offset_write(struct file *file,
	if (cnt > (dbg->max_offset - off))
		cnt = dbg->max_offset - off;

	mutex_lock(&dbg->buflock);
	dbg->off = off;
	dbg->cnt = cnt;
	mutex_unlock(&dbg->buflock);

	SDEROT_DBG("offset=%x cnt=%x\n", off, cnt);

@@ -1053,7 +1058,10 @@ static ssize_t sde_rotator_debug_base_offset_read(struct file *file,
	if (*ppos)
		return 0;	/* the end */

	mutex_lock(&dbg->buflock);
	len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt);
	mutex_unlock(&dbg->buflock);

	if (len < 0 || len >= sizeof(buf))
		return 0;

@@ -1092,6 +1100,8 @@ static ssize_t sde_rotator_debug_base_reg_write(struct file *file,
	if (off >= dbg->max_offset)
		return -EFAULT;

	mutex_lock(&dbg->buflock);

	/* Enable Clock for register access */
	sde_rotator_clk_ctrl(dbg->mgr, true);

@@ -1100,6 +1110,8 @@ static ssize_t sde_rotator_debug_base_reg_write(struct file *file,
	/* Disable Clock after register access */
	sde_rotator_clk_ctrl(dbg->mgr, false);

	mutex_unlock(&dbg->buflock);

	SDEROT_DBG("addr=%zx data=%x\n", off, data);

	return count;
@@ -1110,12 +1122,14 @@ static ssize_t sde_rotator_debug_base_reg_read(struct file *file,
{
	struct sde_rotator_debug_base *dbg = file->private_data;
	size_t len;
	int rc = 0;

	if (!dbg) {
		SDEROT_ERR("invalid handle\n");
		return -ENODEV;
	}

	mutex_lock(&dbg->buflock);
	if (!dbg->buf) {
		char dump_buf[64];
		char *ptr;
@@ -1127,7 +1141,8 @@ static ssize_t sde_rotator_debug_base_reg_read(struct file *file,

		if (!dbg->buf) {
			SDEROT_ERR("not enough memory to hold reg dump\n");
			return -ENOMEM;
			rc = -ENOMEM;
			goto debug_read_error;
		}

		ptr = dbg->base + dbg->off;
@@ -1157,18 +1172,26 @@ static ssize_t sde_rotator_debug_base_reg_read(struct file *file,
		dbg->buf_len = tot;
	}

	if (*ppos >= dbg->buf_len)
		return 0; /* done reading */
	if (*ppos >= dbg->buf_len) {
		rc = 0; /* done reading */
		goto debug_read_error;
	}

	len = min(count, dbg->buf_len - (size_t) *ppos);
	if (copy_to_user(user_buf, dbg->buf + *ppos, len)) {
		SDEROT_ERR("failed to copy to user\n");
		return -EFAULT;
		rc = -EFAULT;
		goto debug_read_error;
	}

	*ppos += len; /* increase offset */

	mutex_unlock(&dbg->buflock);
	return len;

debug_read_error:
	mutex_unlock(&dbg->buflock);
	return rc;
}

static const struct file_operations sde_rotator_off_fops = {
@@ -1202,6 +1225,9 @@ int sde_rotator_debug_register_base(struct sde_rotator_device *rot_dev,
	if (!dbg)
		return -ENOMEM;

	mutex_init(&dbg->buflock);
	mutex_lock(&dbg->buflock);

	if (name)
		strlcpy(dbg->name, name, sizeof(dbg->name));
	dbg->base = io_data->base;
@@ -1223,6 +1249,7 @@ int sde_rotator_debug_register_base(struct sde_rotator_device *rot_dev,
			dbg->base += rot_dev->mdata->regdump ?
				rot_dev->mdata->regdump[0].offset : 0;
	}
	mutex_unlock(&dbg->buflock);

	strlcpy(dbgname + prefix_len, "off", sizeof(dbgname) - prefix_len);
	ent_off = debugfs_create_file(dbgname, 0644, debugfs_root, dbg,
@@ -1240,7 +1267,9 @@ int sde_rotator_debug_register_base(struct sde_rotator_device *rot_dev,
		goto reg_fail;
	}

	mutex_lock(&dbg->buflock);
	dbg->mgr = rot_dev->mgr;
	mutex_unlock(&dbg->buflock);

	return 0;
reg_fail:
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2017, 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
@@ -53,6 +53,7 @@ struct sde_rotator_debug_base {
	char *buf;
	size_t buf_len;
	struct sde_rot_mgr *mgr;
	struct mutex buflock;
};

#if defined(CONFIG_DEBUG_FS)