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

Commit 6ed191c5 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "platform: msm: spmi: Fix possible race condition in debugfs"

parents 5e57c268 80decd63
Loading
Loading
Loading
Loading
+28 −9
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, 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
@@ -69,6 +69,7 @@ struct spmi_trans {
	u32 addr;	/* 20-bit address: SID + PID + Register offset */
	u32 offset;	/* Offset of last read data */
	bool raw_data;	/* Set to true for raw data dump */
	struct mutex spmi_dfs_lock; /* Prevent thread concurrency */
	struct spmi_controller *ctrl;
	struct spmi_log_buffer *log; /* log buffer */
};
@@ -168,6 +169,7 @@ static int spmi_dfs_open(struct spmi_ctrl_data *ctrl_data, struct file *file)
	trans->addr = ctrl_data->addr;
	trans->ctrl = ctrl_data->ctrl;
	trans->offset = trans->addr;
	mutex_init(&trans->spmi_dfs_lock);

	file->private_data = trans;
	return 0;
@@ -197,6 +199,7 @@ static int spmi_dfs_close(struct inode *inode, struct file *file)

	if (trans && trans->log) {
		file->private_data = NULL;
		mutex_destroy(&trans->spmi_dfs_lock);
		kfree(trans->log);
		kfree(trans);
	}
@@ -473,14 +476,21 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf,
	int cnt = 0;
	u8  *values;
	size_t ret = 0;

	u32 offset;
	char *kbuf;
	struct spmi_trans *trans = file->private_data;
	u32 offset = trans->offset;

	mutex_lock(&trans->spmi_dfs_lock);

	trans = file->private_data;
	offset = trans->offset;

	/* Make a copy of the user data */
	char *kbuf = kmalloc(count + 1, GFP_KERNEL);
	if (!kbuf)
		return -ENOMEM;
	kbuf = kmalloc(count + 1, GFP_KERNEL);
	if (!kbuf) {
		ret = -ENOMEM;
		goto unlock_mutex;
	}

	ret = copy_from_user(kbuf, buf, count);
	if (ret == count) {
@@ -517,6 +527,8 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf,

free_buf:
	kfree(kbuf);
unlock_mutex:
	mutex_unlock(&trans->spmi_dfs_lock);
	return ret;
}

@@ -537,10 +549,13 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf,
	size_t ret;
	size_t len;

	mutex_lock(&trans->spmi_dfs_lock);
	/* Is the the log buffer empty */
	if (log->rpos >= log->wpos) {
		if (get_log_data(trans) <= 0)
			return 0;
		if (get_log_data(trans) <= 0) {
			len = 0;
			goto unlock_mutex;
		}
	}

	len = min(count, log->wpos - log->rpos);
@@ -548,7 +563,8 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf,
	ret = copy_to_user(buf, &log->data[log->rpos], len);
	if (ret == len) {
		pr_err("error copy SPMI register values to user\n");
		return -EFAULT;
		len = -EFAULT;
		goto unlock_mutex;
	}

	/* 'ret' is the number of bytes not copied */
@@ -556,6 +572,9 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf,

	*ppos += len;
	log->rpos += len;

unlock_mutex:
	mutex_unlock(&trans->spmi_dfs_lock);
	return len;
}