From 67dfd3a65336e0b3f55ee83d6312321dc5f2a6f9 Mon Sep 17 00:00:00 2001 From: Padmanabhan Komanduru Date: Wed, 25 Jan 2017 16:38:48 +0530 Subject: msm: mdss: handle synchronization issues during DSI debugfs read/write Handle race condition during read/write operations to DSI debugfs nodes related to DSI panel ON/OFF commands. Change-Id: I29c4ad74bf21d4cb5362565e902a682fe7263147 Signed-off-by: Padmanabhan Komanduru --- drivers/video/msm/mdss/mdss_dsi.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index 885d132..e6d9edc 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -625,6 +625,7 @@ struct buf_data { char *string_buf; /* cmd buf as string, 3 bytes per number */ int sblen; /* string buffer length */ int sync_flag; + struct mutex dbg_mutex; /* mutex to synchronize read/write/flush */ }; struct mdss_dsi_debugfs_info { @@ -714,6 +715,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, char *bp; ssize_t ret = 0; + mutex_lock(&pcmds->dbg_mutex); if (*ppos == 0) { kfree(pcmds->string_buf); pcmds->string_buf = NULL; @@ -732,6 +734,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, buffer = kmalloc(bsize, GFP_KERNEL); if (!buffer) { pr_err("%s: Failed to allocate memory\n", __func__); + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -767,10 +770,12 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, kfree(pcmds->string_buf); pcmds->string_buf = NULL; pcmds->sblen = 0; + mutex_unlock(&pcmds->dbg_mutex); return 0; /* the end */ } ret = simple_read_from_buffer(buf, count, ppos, pcmds->string_buf, pcmds->sblen); + mutex_unlock(&pcmds->dbg_mutex); return ret; } @@ -782,6 +787,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, int blen = 0; char *string_buf; + mutex_lock(&pcmds->dbg_mutex); if (*ppos == 0) { kfree(pcmds->string_buf); pcmds->string_buf = NULL; @@ -793,6 +799,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, string_buf = krealloc(pcmds->string_buf, blen + 1, GFP_KERNEL); if (!string_buf) { pr_err("%s: Failed to allocate memory\n", __func__); + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -802,6 +809,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, string_buf[blen] = '\0'; pcmds->string_buf = string_buf; pcmds->sblen = blen; + mutex_unlock(&pcmds->dbg_mutex); return ret; } @@ -812,8 +820,12 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) char *buf, *bufp, *bp; struct dsi_ctrl_hdr *dchdr; - if (!pcmds->string_buf) + mutex_lock(&pcmds->dbg_mutex); + + if (!pcmds->string_buf) { + mutex_unlock(&pcmds->dbg_mutex); return 0; + } /* * Allocate memory for command buffer @@ -826,6 +838,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) kfree(pcmds->string_buf); pcmds->string_buf = NULL; pcmds->sblen = 0; + mutex_unlock(&pcmds->dbg_mutex); return -ENOMEM; } @@ -850,6 +863,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pr_err("%s: dtsi cmd=%x error, len=%d\n", __func__, dchdr->dtype, dchdr->dlen); kfree(buf); + mutex_unlock(&pcmds->dbg_mutex); return -EINVAL; } bp += sizeof(*dchdr); @@ -861,6 +875,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pr_err("%s: dcs_cmd=%x len=%d error!\n", __func__, bp[0], len); kfree(buf); + mutex_unlock(&pcmds->dbg_mutex); return -EINVAL; } @@ -873,6 +888,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) pcmds->buf = buf; pcmds->blen = blen; } + mutex_unlock(&pcmds->dbg_mutex); return 0; } @@ -887,6 +903,7 @@ struct dentry *dsi_debugfs_create_dcs_cmd(const char *name, umode_t mode, struct dentry *parent, struct buf_data *cmd, struct dsi_panel_cmds ctrl_cmds) { + mutex_init(&cmd->dbg_mutex); cmd->buf = ctrl_cmds.buf; cmd->blen = ctrl_cmds.blen; cmd->string_buf = NULL; -- cgit v1.1