soc: qcom: msm_bus: add mutex lock for cllist data

Cldata needed to be protected by lock since crash
happened when synchronous update and free.

Extend original patch to include missing "found" guards.

FPIIM-1552

CRs-Fixed: 2034222
Change-Id: Ied86461b784d69d9758dc3fc793a8a0de86e7f9c
Signed-off-by: Maria Yu <aiquny@codeaurora.org>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
index 001c733..13feed6 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -19,6 +19,7 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
+#include <linux/rtmutex.h>
 #include <linux/string.h>
 #include <linux/uaccess.h>
 #include <linux/hrtimer.h>
@@ -32,6 +33,7 @@
 static struct dentry *clients;
 static struct dentry *dir;
 static DEFINE_MUTEX(msm_bus_dbg_fablist_lock);
+static DEFINE_RT_MUTEX(msm_bus_dbg_cllist_lock);
 struct msm_bus_dbg_state {
 	uint32_t cl;
 	uint8_t enable;
@@ -277,14 +279,28 @@
 	int bsize = 0;
 	uint32_t cl = (uint32_t)file->private_data;
 	struct msm_bus_cldata *cldata = NULL;
+	int found = 0;
+	ssize_t ret;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
-		if (cldata->clid == cl)
+		if (cldata->clid == cl) {
+			found = 1;
 			break;
+		}
 	}
+
+	if (!found) {
+		rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+		return 0;
+	}
+
 	bsize = cldata->size;
-	return simple_read_from_buffer(buf, count, ppos,
-		cldata->buffer, bsize);
+	ret = simple_read_from_buffer(buf, count, ppos,
+			cldata->buffer, bsize);
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+
+	return ret;
 }
 
 static int client_data_open(struct inode *inode, struct file *file)
@@ -324,7 +340,9 @@
 	cldata->clid = clid;
 	cldata->file = file;
 	cldata->size = 0;
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_add_tail(&cldata->list, &cl_list);
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 	return 0;
 }
 
@@ -332,6 +350,7 @@
 {
 	struct msm_bus_cldata *cldata = NULL;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (cldata->clid == clid) {
 			debugfs_remove(cldata->file);
@@ -340,6 +359,7 @@
 			break;
 		}
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 }
 
 static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata,
@@ -349,13 +369,24 @@
 	char *buf = NULL;
 	struct msm_bus_cldata *cldata = NULL;
 	struct timespec ts;
+	int found = 0;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
-		if (cldata->clid == clid)
+		if (cldata->clid == clid) {
+			found = 1;
 			break;
+		}
 	}
+
+	if (!found) {
+		rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+		return -ENOENT;
+	}
+
 	if (cldata->file == NULL) {
 		if (pdata->name == NULL) {
+			rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 			MSM_BUS_DBG("Client doesn't have a name\n");
 			return -EINVAL;
 		}
@@ -394,21 +425,11 @@
 	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n");
 
 	cldata->size = i;
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+
 	return i;
 }
 
-static int msm_bus_dbg_update_request(struct msm_bus_cldata *cldata, int index)
-{
-	int ret = 0;
-
-	if ((index < 0) || (index > cldata->pdata->num_usecases)) {
-		MSM_BUS_DBG("Invalid index!\n");
-		return -EINVAL;
-	}
-	ret = msm_bus_scale_client_update_request(cldata->clid, index);
-	return ret;
-}
-
 static ssize_t  msm_bus_dbg_update_request_write(struct file *file,
 	const char __user *ubuf, size_t cnt, loff_t *ppos)
 {
@@ -417,21 +438,30 @@
 	int ret = 0;
 	char *chid;
 	char *buf = kmalloc((sizeof(char) * (cnt + 1)), GFP_KERNEL);
+	int found = 0;
+	uint32_t clid;
+	ssize_t res = cnt;
 
 	if (!buf || IS_ERR(buf)) {
 		MSM_BUS_ERR("Memory allocation for buffer failed\n");
 		return -ENOMEM;
 	}
-	if (cnt == 0)
-		return 0;
-	if (copy_from_user(buf, ubuf, cnt))
-		return -EFAULT;
+	if (cnt == 0) {
+		res = 0;
+		goto out;
+	}
+	if (copy_from_user(buf, ubuf, cnt)) {
+		res = -EFAULT;
+		goto out;
+	}
 	buf[cnt] = '\0';
 	chid = buf;
 	MSM_BUS_DBG("buffer: %s\n size: %d\n", buf, sizeof(ubuf));
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (strstr(chid, cldata->pdata->name)) {
+			found = 1;
 			cldata = cldata;
 			strsep(&chid, " ");
 			if (chid) {
@@ -439,18 +469,34 @@
 				if (ret) {
 					MSM_BUS_DBG("Index conversion"
 						" failed\n");
-					return -EFAULT;
+					rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+					res = -EFAULT;
+					goto out;
 				}
-			} else
+			} else {
 				MSM_BUS_DBG("Error parsing input. Index not"
 					" found\n");
+				found = 0;
+			}
+			if ((index < 0) ||
+					(index > cldata->pdata->num_usecases)) {
+				MSM_BUS_DBG("Invalid index!\n");
+				rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+				res = -EINVAL;
+				goto out;
+			}
+			clid = cldata->clid;
 			break;
 		}
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 
-	msm_bus_dbg_update_request(cldata, index);
+	if (found)
+		msm_bus_scale_client_update_request(clid, index);
+
+out:
 	kfree(buf);
-	return cnt;
+	return res;
 }
 
 /**
@@ -464,11 +510,18 @@
 	int bsize = 0;
 	ssize_t ret;
 	const char *name = file->private_data;
+	int found = 0;
 
 	mutex_lock(&msm_bus_dbg_fablist_lock);
 	list_for_each_entry(fablist, &fabdata_list, list) {
-		if (strcmp(fablist->name, name) == 0)
+		if (strcmp(fablist->name, name) == 0) {
+			found = 1;
 			break;
+		}
+	}
+	if (!found) {
+		mutex_unlock(&msm_bus_dbg_fablist_lock);
+		return -ENOENT;
 	}
 	bsize = fablist->size;
 	ret = simple_read_from_buffer(buf, count, ppos,
@@ -527,12 +580,20 @@
 	char *buf = NULL;
 	struct msm_bus_fab_list *fablist = NULL;
 	struct timespec ts;
+	int found = 0;
 
 	mutex_lock(&msm_bus_dbg_fablist_lock);
 	list_for_each_entry(fablist, &fabdata_list, list) {
-		if (strcmp(fablist->name, fabname) == 0)
+		if (strcmp(fablist->name, fabname) == 0) {
+			found = 1;
 			break;
+		}
 	}
+	if (!found) {
+		mutex_unlock(&msm_bus_dbg_fablist_lock);
+		return -ENOENT;
+	}
+
 	if (fablist->file == NULL) {
 		MSM_BUS_DBG("Fabric dbg entry does not exist\n");
 		mutex_unlock(&msm_bus_dbg_fablist_lock);
@@ -664,6 +725,7 @@
 		clients, NULL, &msm_bus_dbg_update_request_fops) == NULL)
 		goto err;
 
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry(cldata, &cl_list, list) {
 		if (cldata->pdata->name == NULL) {
 			MSM_BUS_DBG("Client name not found\n");
@@ -672,6 +734,7 @@
 		cldata->file = msm_bus_dbg_create(cldata->
 			pdata->name, S_IRUGO, clients, cldata->clid);
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
 
 	mutex_lock(&msm_bus_dbg_fablist_lock);
 	list_for_each_entry(fablist, &fabdata_list, list) {
@@ -679,6 +742,7 @@
 			commit, (void *)fablist->name, &fabric_data_fops);
 		if (fablist->file == NULL) {
 			MSM_BUS_DBG("Cannot create files for commit data\n");
+			mutex_unlock(&msm_bus_dbg_fablist_lock);
 			goto err;
 		}
 	}
@@ -698,10 +762,14 @@
 	struct msm_bus_cldata *cldata = NULL, *cldata_temp;
 
 	debugfs_remove_recursive(dir);
+
+	rt_mutex_lock(&msm_bus_dbg_cllist_lock);
 	list_for_each_entry_safe(cldata, cldata_temp, &cl_list, list) {
 		list_del(&cldata->list);
 		kfree(cldata);
 	}
+	rt_mutex_unlock(&msm_bus_dbg_cllist_lock);
+
 	mutex_lock(&msm_bus_dbg_fablist_lock);
 	list_for_each_entry_safe(fablist, fablist_temp, &fabdata_list, list) {
 		list_del(&fablist->list);