summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/power/supply/qcom/fg-core.h1
-rw-r--r--drivers/power/supply/qcom/fg-util.c24
2 files changed, 20 insertions, 5 deletions
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 07bde30524ac..d71e3afd8d42 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -369,6 +369,7 @@ struct fg_log_buffer {
/* transaction parameters */
struct fg_trans {
struct fg_chip *chip;
+ struct mutex fg_dfs_lock; /* Prevent thread concurrency */
struct fg_log_buffer *log;
u32 cnt;
u16 addr;
diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c
index 41d2af0fbdc6..d5c4f8ffaac3 100644
--- a/drivers/power/supply/qcom/fg-util.c
+++ b/drivers/power/supply/qcom/fg-util.c
@@ -486,6 +486,7 @@ static int fg_sram_dfs_open(struct inode *inode, struct file *file)
trans->addr = dbgfs_data.addr;
trans->chip = dbgfs_data.chip;
trans->offset = trans->addr;
+ mutex_init(&trans->fg_dfs_lock);
file->private_data = trans;
return 0;
@@ -497,6 +498,7 @@ static int fg_sram_dfs_close(struct inode *inode, struct file *file)
if (trans && trans->log && trans->data) {
file->private_data = NULL;
+ mutex_destroy(&trans->fg_dfs_lock);
devm_kfree(trans->chip->dev, trans->log);
devm_kfree(trans->chip->dev, trans->data);
devm_kfree(trans->chip->dev, trans);
@@ -648,10 +650,13 @@ static ssize_t fg_sram_dfs_reg_read(struct file *file, char __user *buf,
size_t ret;
size_t len;
+ mutex_lock(&trans->fg_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);
@@ -659,7 +664,8 @@ static ssize_t fg_sram_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 sram register values to user\n");
- return -EFAULT;
+ len = -EFAULT;
+ goto unlock_mutex;
}
/* 'ret' is the number of bytes not copied */
@@ -667,6 +673,9 @@ static ssize_t fg_sram_dfs_reg_read(struct file *file, char __user *buf,
*ppos += len;
log->rpos += len;
+
+unlock_mutex:
+ mutex_unlock(&trans->fg_dfs_lock);
return len;
}
@@ -691,10 +700,13 @@ static ssize_t fg_sram_dfs_reg_write(struct file *file, const char __user *buf,
struct fg_trans *trans = file->private_data;
u32 address = trans->addr;
+ mutex_lock(&trans->fg_dfs_lock);
/* Make a copy of the user data */
kbuf = kmalloc(count + 1, GFP_KERNEL);
- if (!kbuf)
- return -ENOMEM;
+ if (!kbuf) {
+ ret = -ENOMEM;
+ goto unlock_mutex;
+ }
ret = copy_from_user(kbuf, buf, count);
if (ret == count) {
@@ -744,6 +756,8 @@ static ssize_t fg_sram_dfs_reg_write(struct file *file, const char __user *buf,
free_buf:
kfree(kbuf);
+unlock_mutex:
+ mutex_unlock(&trans->fg_dfs_lock);
return ret;
}