xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *
3  * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15 
16 
17 
18 #include <linux/debugfs.h>
19 #include <linux/list.h>
20 #include <linux/mutex.h>
21 
22 #include "mali_kbase.h"
23 #include "mali_kbase_ipa.h"
24 #include "mali_kbase_ipa_debugfs.h"
25 
26 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
27 #define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
28 #endif
29 
30 struct kbase_ipa_model_param {
31 	char *name;
32 	union {
33 		void *voidp;
34 		s32 *s32p;
35 		char *str;
36 	} addr;
37 	size_t size;
38 	enum kbase_ipa_model_param_type type;
39 	struct kbase_ipa_model *model;
40 	struct list_head link;
41 };
42 
param_int_get(void * data,u64 * val)43 static int param_int_get(void *data, u64 *val)
44 {
45 	struct kbase_ipa_model_param *param = data;
46 
47 	mutex_lock(&param->model->kbdev->ipa.lock);
48 	*(s64 *) val = *param->addr.s32p;
49 	mutex_unlock(&param->model->kbdev->ipa.lock);
50 
51 	return 0;
52 }
53 
param_int_set(void * data,u64 val)54 static int param_int_set(void *data, u64 val)
55 {
56 	struct kbase_ipa_model_param *param = data;
57 	struct kbase_ipa_model *model = param->model;
58 	s64 sval = (s64) val;
59 	int err = 0;
60 
61 	if (sval < S32_MIN || sval > S32_MAX)
62 		return -ERANGE;
63 
64 	mutex_lock(&param->model->kbdev->ipa.lock);
65 	*param->addr.s32p = val;
66 	err = kbase_ipa_model_recalculate(model);
67 	mutex_unlock(&param->model->kbdev->ipa.lock);
68 
69 	return err;
70 }
71 
72 DEFINE_DEBUGFS_ATTRIBUTE(fops_s32, param_int_get, param_int_set, "%lld\n");
73 
param_string_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)74 static ssize_t param_string_get(struct file *file, char __user *user_buf,
75 				size_t count, loff_t *ppos)
76 {
77 	struct kbase_ipa_model_param *param = file->private_data;
78 	ssize_t ret;
79 	size_t len;
80 
81 	mutex_lock(&param->model->kbdev->ipa.lock);
82 	len = strnlen(param->addr.str, param->size - 1) + 1;
83 	ret = simple_read_from_buffer(user_buf, count, ppos,
84 				      param->addr.str, len);
85 	mutex_unlock(&param->model->kbdev->ipa.lock);
86 
87 	return ret;
88 }
89 
param_string_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)90 static ssize_t param_string_set(struct file *file, const char __user *user_buf,
91 				size_t count, loff_t *ppos)
92 {
93 	struct kbase_ipa_model_param *param = file->private_data;
94 	struct kbase_ipa_model *model = param->model;
95 	ssize_t ret = count;
96 	size_t buf_size;
97 	int err;
98 
99 	mutex_lock(&model->kbdev->ipa.lock);
100 
101 	if (count > param->size) {
102 		ret = -EINVAL;
103 		goto end;
104 	}
105 
106 	buf_size = min(param->size - 1, count);
107 	if (copy_from_user(param->addr.str, user_buf, buf_size)) {
108 		ret = -EFAULT;
109 		goto end;
110 	}
111 
112 	param->addr.str[buf_size] = '\0';
113 
114 	err = kbase_ipa_model_recalculate(model);
115 	if (err < 0)
116 		ret = err;
117 
118 end:
119 	mutex_unlock(&model->kbdev->ipa.lock);
120 
121 	return ret;
122 }
123 
124 static const struct file_operations fops_string = {
125 	.read = param_string_get,
126 	.write = param_string_set,
127 	.open = simple_open,
128 	.llseek = default_llseek,
129 };
130 
kbase_ipa_model_param_add(struct kbase_ipa_model * model,const char * name,void * addr,size_t size,enum kbase_ipa_model_param_type type)131 int kbase_ipa_model_param_add(struct kbase_ipa_model *model, const char *name,
132 			      void *addr, size_t size,
133 			      enum kbase_ipa_model_param_type type)
134 {
135 	struct kbase_ipa_model_param *param;
136 
137 	param = kzalloc(sizeof(*param), GFP_KERNEL);
138 
139 	if (!param)
140 		return -ENOMEM;
141 
142 	/* 'name' is stack-allocated for array elements, so copy it into
143 	 * heap-allocated storage */
144 	param->name = kstrdup(name, GFP_KERNEL);
145 	param->addr.voidp = addr;
146 	param->size = size;
147 	param->type = type;
148 	param->model = model;
149 
150 	list_add(&param->link, &model->params);
151 
152 	return 0;
153 }
154 
kbase_ipa_model_param_free_all(struct kbase_ipa_model * model)155 void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model)
156 {
157 	struct kbase_ipa_model_param *param_p, *param_n;
158 
159 	list_for_each_entry_safe(param_p, param_n, &model->params, link) {
160 		list_del(&param_p->link);
161 		kfree(param_p->name);
162 		kfree(param_p);
163 	}
164 }
165 
kbase_ipa_model_debugfs_init(struct kbase_ipa_model * model)166 static void kbase_ipa_model_debugfs_init(struct kbase_ipa_model *model)
167 {
168 	struct list_head *it;
169 	struct dentry *dir;
170 
171 	lockdep_assert_held(&model->kbdev->ipa.lock);
172 
173 	dir = debugfs_create_dir(model->ops->name,
174 				 model->kbdev->mali_debugfs_directory);
175 
176 	if (!dir) {
177 		dev_err(model->kbdev->dev,
178 			"Couldn't create mali debugfs %s directory",
179 			model->ops->name);
180 		return;
181 	}
182 
183 	list_for_each(it, &model->params) {
184 		struct kbase_ipa_model_param *param =
185 				list_entry(it,
186 					   struct kbase_ipa_model_param,
187 					   link);
188 		const struct file_operations *fops = NULL;
189 
190 		switch (param->type) {
191 		case PARAM_TYPE_S32:
192 			fops = &fops_s32;
193 			break;
194 		case PARAM_TYPE_STRING:
195 			fops = &fops_string;
196 			break;
197 		}
198 
199 		if (unlikely(!fops)) {
200 			dev_err(model->kbdev->dev,
201 				"Type not set for %s parameter %s\n",
202 				model->ops->name, param->name);
203 		} else {
204 			debugfs_create_file(param->name, S_IRUGO | S_IWUSR,
205 					    dir, param, fops);
206 		}
207 	}
208 }
209 
kbase_ipa_debugfs_init(struct kbase_device * kbdev)210 void kbase_ipa_debugfs_init(struct kbase_device *kbdev)
211 {
212 	mutex_lock(&kbdev->ipa.lock);
213 
214 	if (kbdev->ipa.configured_model != kbdev->ipa.fallback_model)
215 		kbase_ipa_model_debugfs_init(kbdev->ipa.configured_model);
216 	kbase_ipa_model_debugfs_init(kbdev->ipa.fallback_model);
217 
218 	mutex_unlock(&kbdev->ipa.lock);
219 }
220