xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3  *
4  * (C) COPYRIGHT 2017-2022 ARM Limited. All rights reserved.
5  *
6  * This program is free software and is provided to you under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation, and any use by you of this program is subject to the terms
9  * of such GNU license.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you can access it online at
18  * http://www.gnu.org/licenses/gpl-2.0.html.
19  *
20  */
21 
22 #include <linux/debugfs.h>
23 #include <linux/list.h>
24 #include <linux/mutex.h>
25 
26 #include "mali_kbase.h"
27 #include "mali_kbase_ipa.h"
28 #include "mali_kbase_ipa_debugfs.h"
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 	s32 old_val;
60 	int err = 0;
61 
62 	if (sval < S32_MIN || sval > S32_MAX)
63 		return -ERANGE;
64 
65 	mutex_lock(&param->model->kbdev->ipa.lock);
66 	old_val = *param->addr.s32p;
67 	*param->addr.s32p = val;
68 	err = kbase_ipa_model_recalculate(model);
69 	if (err < 0)
70 		*param->addr.s32p = old_val;
71 	mutex_unlock(&param->model->kbdev->ipa.lock);
72 
73 	return err;
74 }
75 
76 DEFINE_DEBUGFS_ATTRIBUTE(fops_s32, param_int_get, param_int_set, "%lld\n");
77 
param_string_get(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)78 static ssize_t param_string_get(struct file *file, char __user *user_buf,
79 				size_t count, loff_t *ppos)
80 {
81 	struct kbase_ipa_model_param *param = file->private_data;
82 	ssize_t ret;
83 	size_t len;
84 
85 	mutex_lock(&param->model->kbdev->ipa.lock);
86 	len = strnlen(param->addr.str, param->size - 1) + 1;
87 	ret = simple_read_from_buffer(user_buf, count, ppos,
88 				      param->addr.str, len);
89 	mutex_unlock(&param->model->kbdev->ipa.lock);
90 
91 	return ret;
92 }
93 
param_string_set(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)94 static ssize_t param_string_set(struct file *file, const char __user *user_buf,
95 				size_t count, loff_t *ppos)
96 {
97 	struct kbase_ipa_model_param *param = file->private_data;
98 	struct kbase_ipa_model *model = param->model;
99 	char *old_str = NULL;
100 	ssize_t ret = count;
101 	size_t buf_size;
102 	int err;
103 
104 	mutex_lock(&model->kbdev->ipa.lock);
105 
106 	if (count > param->size) {
107 		ret = -EINVAL;
108 		goto end;
109 	}
110 
111 	old_str = kstrndup(param->addr.str, param->size, GFP_KERNEL);
112 	if (!old_str) {
113 		ret = -ENOMEM;
114 		goto end;
115 	}
116 
117 	buf_size = min(param->size - 1, count);
118 	if (copy_from_user(param->addr.str, user_buf, buf_size)) {
119 		ret = -EFAULT;
120 		goto end;
121 	}
122 
123 	param->addr.str[buf_size] = '\0';
124 
125 	err = kbase_ipa_model_recalculate(model);
126 	if (err < 0) {
127 		u32 string_len = strscpy(param->addr.str, old_str, param->size);
128 
129 		string_len += sizeof(char);
130 		/* Make sure that the source string fit into the buffer. */
131 		KBASE_DEBUG_ASSERT(string_len <= param->size);
132 		CSTD_UNUSED(string_len);
133 
134 		ret = err;
135 	}
136 
137 end:
138 	kfree(old_str);
139 	mutex_unlock(&model->kbdev->ipa.lock);
140 
141 	return ret;
142 }
143 
144 static const struct file_operations fops_string = {
145 	.owner = THIS_MODULE,
146 	.read = param_string_get,
147 	.write = param_string_set,
148 	.open = simple_open,
149 	.llseek = default_llseek,
150 };
151 
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)152 int kbase_ipa_model_param_add(struct kbase_ipa_model *model, const char *name,
153 			      void *addr, size_t size,
154 			      enum kbase_ipa_model_param_type type)
155 {
156 	struct kbase_ipa_model_param *param;
157 
158 	param = kzalloc(sizeof(*param), GFP_KERNEL);
159 
160 	if (!param)
161 		return -ENOMEM;
162 
163 	/* 'name' is stack-allocated for array elements, so copy it into
164 	 * heap-allocated storage
165 	 */
166 	param->name = kstrdup(name, GFP_KERNEL);
167 
168 	if (!param->name) {
169 		kfree(param);
170 		return -ENOMEM;
171 	}
172 
173 	param->addr.voidp = addr;
174 	param->size = size;
175 	param->type = type;
176 	param->model = model;
177 
178 	list_add(&param->link, &model->params);
179 
180 	return 0;
181 }
182 
kbase_ipa_model_param_free_all(struct kbase_ipa_model * model)183 void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model)
184 {
185 	struct kbase_ipa_model_param *param_p, *param_n;
186 
187 	list_for_each_entry_safe(param_p, param_n, &model->params, link) {
188 		list_del(&param_p->link);
189 		kfree(param_p->name);
190 		kfree(param_p);
191 	}
192 }
193 
force_fallback_model_get(void * data,u64 * val)194 static int force_fallback_model_get(void *data, u64 *val)
195 {
196 	struct kbase_device *kbdev = data;
197 
198 	mutex_lock(&kbdev->ipa.lock);
199 	*val = kbdev->ipa.force_fallback_model;
200 	mutex_unlock(&kbdev->ipa.lock);
201 
202 	return 0;
203 }
204 
force_fallback_model_set(void * data,u64 val)205 static int force_fallback_model_set(void *data, u64 val)
206 {
207 	struct kbase_device *kbdev = data;
208 
209 	mutex_lock(&kbdev->ipa.lock);
210 	kbdev->ipa.force_fallback_model = (val ? true : false);
211 	mutex_unlock(&kbdev->ipa.lock);
212 
213 	return 0;
214 }
215 
216 DEFINE_DEBUGFS_ATTRIBUTE(force_fallback_model,
217 		force_fallback_model_get,
218 		force_fallback_model_set,
219 		"%llu\n");
220 
current_power_get(void * data,u64 * val)221 static int current_power_get(void *data, u64 *val)
222 {
223 	struct kbase_device *kbdev = data;
224 	struct devfreq *df = kbdev->devfreq;
225 	u32 power;
226 
227 	kbase_pm_context_active(kbdev);
228 	/* The current model assumes that there's no more than one voltage
229 	 * regulator currently available in the system.
230 	 */
231 	kbase_get_real_power(df, &power,
232 		kbdev->current_nominal_freq,
233 		(kbdev->current_voltages[0] / 1000));
234 	kbase_pm_context_idle(kbdev);
235 
236 	*val = power;
237 
238 	return 0;
239 }
240 DEFINE_DEBUGFS_ATTRIBUTE(current_power, current_power_get, NULL, "%llu\n");
241 
kbase_ipa_model_debugfs_init(struct kbase_ipa_model * model)242 static void kbase_ipa_model_debugfs_init(struct kbase_ipa_model *model)
243 {
244 	struct list_head *it;
245 	struct dentry *dir;
246 
247 	lockdep_assert_held(&model->kbdev->ipa.lock);
248 
249 	dir = debugfs_create_dir(model->ops->name,
250 				 model->kbdev->mali_debugfs_directory);
251 
252 	if (IS_ERR_OR_NULL(dir)) {
253 		dev_err(model->kbdev->dev,
254 			"Couldn't create mali debugfs %s directory",
255 			model->ops->name);
256 		return;
257 	}
258 
259 	list_for_each(it, &model->params) {
260 		struct kbase_ipa_model_param *param =
261 				list_entry(it,
262 					   struct kbase_ipa_model_param,
263 					   link);
264 		const struct file_operations *fops = NULL;
265 
266 		switch (param->type) {
267 		case PARAM_TYPE_S32:
268 			fops = &fops_s32;
269 			break;
270 		case PARAM_TYPE_STRING:
271 			fops = &fops_string;
272 			break;
273 		}
274 
275 		if (unlikely(!fops)) {
276 			dev_err(model->kbdev->dev,
277 				"Type not set for %s parameter %s\n",
278 				model->ops->name, param->name);
279 		} else {
280 			debugfs_create_file(param->name, 0644,
281 					    dir, param, fops);
282 		}
283 	}
284 }
285 
kbase_ipa_model_param_set_s32(struct kbase_ipa_model * model,const char * name,s32 val)286 void kbase_ipa_model_param_set_s32(struct kbase_ipa_model *model,
287 	const char *name, s32 val)
288 {
289 	struct kbase_ipa_model_param *param;
290 
291 	mutex_lock(&model->kbdev->ipa.lock);
292 
293 	list_for_each_entry(param, &model->params, link) {
294 		if (!strcmp(param->name, name)) {
295 			if (param->type == PARAM_TYPE_S32) {
296 				*param->addr.s32p = val;
297 			} else {
298 				dev_err(model->kbdev->dev,
299 					"Wrong type for %s parameter %s\n",
300 					model->ops->name, param->name);
301 			}
302 			break;
303 		}
304 	}
305 
306 	mutex_unlock(&model->kbdev->ipa.lock);
307 }
308 KBASE_EXPORT_TEST_API(kbase_ipa_model_param_set_s32);
309 
kbase_ipa_debugfs_init(struct kbase_device * kbdev)310 void kbase_ipa_debugfs_init(struct kbase_device *kbdev)
311 {
312 	mutex_lock(&kbdev->ipa.lock);
313 
314 	if (kbdev->ipa.configured_model != kbdev->ipa.fallback_model)
315 		kbase_ipa_model_debugfs_init(kbdev->ipa.configured_model);
316 	kbase_ipa_model_debugfs_init(kbdev->ipa.fallback_model);
317 
318 	debugfs_create_file("ipa_current_power", 0444,
319 		kbdev->mali_debugfs_directory, kbdev, &current_power);
320 	debugfs_create_file("ipa_force_fallback_model", 0644,
321 		kbdev->mali_debugfs_directory, kbdev, &force_fallback_model);
322 
323 	mutex_unlock(&kbdev->ipa.lock);
324 }
325