xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/linux/mali_kernel_sysfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /**
2  * Copyright (C) 2011-2017 ARM Limited. All rights reserved.
3  *
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  *
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10 
11 
12 /**
13  * @file mali_kernel_sysfs.c
14  * Implementation of some sysfs data exports
15  */
16 
17 #include <linux/kernel.h>
18 #include <linux/fs.h>
19 #include <linux/device.h>
20 #include <linux/module.h>
21 #include "mali_kernel_license.h"
22 #include "mali_kernel_common.h"
23 #include "mali_ukk.h"
24 
25 #if MALI_LICENSE_IS_GPL
26 
27 #include <linux/seq_file.h>
28 #include <linux/debugfs.h>
29 #include <linux/uaccess.h>
30 #include <linux/module.h>
31 #include <linux/mali/mali_utgard.h>
32 #include "mali_kernel_sysfs.h"
33 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
34 #include <linux/slab.h>
35 #include "mali_osk_profiling.h"
36 #endif
37 
38 #include <linux/mali/mali_utgard.h>
39 #include "mali_pm.h"
40 #include "mali_pmu.h"
41 #include "mali_group.h"
42 #include "mali_gp.h"
43 #include "mali_pp.h"
44 #include "mali_l2_cache.h"
45 #include "mali_hw_core.h"
46 #include "mali_kernel_core.h"
47 #include "mali_user_settings_db.h"
48 #include "mali_profiling_internal.h"
49 #include "mali_gp_job.h"
50 #include "mali_pp_job.h"
51 #include "mali_executor.h"
52 
53 #define PRIVATE_DATA_COUNTER_MAKE_GP(src) (src)
54 #define PRIVATE_DATA_COUNTER_MAKE_PP(src) ((1 << 24) | src)
55 #define PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(src, sub_job) ((1 << 24) | (1 << 16) | (sub_job << 8) | src)
56 #define PRIVATE_DATA_COUNTER_IS_PP(a) ((((a) >> 24) & 0xFF) ? MALI_TRUE : MALI_FALSE)
57 #define PRIVATE_DATA_COUNTER_GET_SRC(a) (a & 0xFF)
58 #define PRIVATE_DATA_COUNTER_IS_SUB_JOB(a) ((((a) >> 16) & 0xFF) ? MALI_TRUE : MALI_FALSE)
59 #define PRIVATE_DATA_COUNTER_GET_SUB_JOB(a) (((a) >> 8) & 0xFF)
60 
61 #define POWER_BUFFER_SIZE 3
62 
63 static struct dentry *mali_debugfs_dir = NULL;
64 
65 typedef enum {
66 	_MALI_DEVICE_SUSPEND,
67 	_MALI_DEVICE_RESUME,
68 	_MALI_DEVICE_DVFS_PAUSE,
69 	_MALI_DEVICE_DVFS_RESUME,
70 	_MALI_MAX_EVENTS
71 } _mali_device_debug_power_events;
72 
73 static const char *const mali_power_events[_MALI_MAX_EVENTS] = {
74 	[_MALI_DEVICE_SUSPEND] = "suspend",
75 	[_MALI_DEVICE_RESUME] = "resume",
76 	[_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause",
77 	[_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
78 };
79 
80 static mali_bool power_always_on_enabled = MALI_FALSE;
81 
open_copy_private_data(struct inode * inode,struct file * filp)82 static int open_copy_private_data(struct inode *inode, struct file *filp)
83 {
84 	filp->private_data = inode->i_private;
85 	return 0;
86 }
87 
group_enabled_read(struct file * filp,char __user * buf,size_t count,loff_t * offp)88 static ssize_t group_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
89 {
90 	int r;
91 	char buffer[64];
92 	struct mali_group *group;
93 
94 	group = (struct mali_group *)filp->private_data;
95 	MALI_DEBUG_ASSERT_POINTER(group);
96 
97 	r = snprintf(buffer, 64, "%u\n",
98 		     mali_executor_group_is_disabled(group) ? 0 : 1);
99 
100 	return simple_read_from_buffer(buf, count, offp, buffer, r);
101 }
102 
group_enabled_write(struct file * filp,const char __user * buf,size_t count,loff_t * offp)103 static ssize_t group_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
104 {
105 	int r;
106 	char buffer[64];
107 	unsigned long val;
108 	struct mali_group *group;
109 
110 	group = (struct mali_group *)filp->private_data;
111 	MALI_DEBUG_ASSERT_POINTER(group);
112 
113 	if (count >= sizeof(buffer)) {
114 		return -ENOMEM;
115 	}
116 
117 	if (copy_from_user(&buffer[0], buf, count)) {
118 		return -EFAULT;
119 	}
120 	buffer[count] = '\0';
121 
122 	r = kstrtoul(&buffer[0], 10, &val);
123 	if (0 != r) {
124 		return -EINVAL;
125 	}
126 
127 	switch (val) {
128 	case 1:
129 		mali_executor_group_enable(group);
130 		break;
131 	case 0:
132 		mali_executor_group_disable(group);
133 		break;
134 	default:
135 		return -EINVAL;
136 		break;
137 	}
138 
139 	*offp += count;
140 	return count;
141 }
142 
143 static const struct file_operations group_enabled_fops = {
144 	.owner = THIS_MODULE,
145 	.open  = open_copy_private_data,
146 	.read = group_enabled_read,
147 	.write = group_enabled_write,
148 };
149 
hw_core_base_addr_read(struct file * filp,char __user * buf,size_t count,loff_t * offp)150 static ssize_t hw_core_base_addr_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
151 {
152 	int r;
153 	char buffer[64];
154 	struct mali_hw_core *hw_core;
155 
156 	hw_core = (struct mali_hw_core *)filp->private_data;
157 	MALI_DEBUG_ASSERT_POINTER(hw_core);
158 
159 	r = snprintf(buffer, 64, "0x%lX\n", hw_core->phys_addr);
160 
161 	return simple_read_from_buffer(buf, count, offp, buffer, r);
162 }
163 
164 static const struct file_operations hw_core_base_addr_fops = {
165 	.owner = THIS_MODULE,
166 	.open  = open_copy_private_data,
167 	.read = hw_core_base_addr_read,
168 };
169 
profiling_counter_src_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)170 static ssize_t profiling_counter_src_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
171 {
172 	u32 is_pp = PRIVATE_DATA_COUNTER_IS_PP((uintptr_t)filp->private_data);
173 	u32 src_id = PRIVATE_DATA_COUNTER_GET_SRC((uintptr_t)filp->private_data);
174 	mali_bool is_sub_job = PRIVATE_DATA_COUNTER_IS_SUB_JOB((uintptr_t)filp->private_data);
175 	u32 sub_job = PRIVATE_DATA_COUNTER_GET_SUB_JOB((uintptr_t)filp->private_data);
176 	char buf[64];
177 	int r;
178 	u32 val;
179 
180 	if (MALI_TRUE == is_pp) {
181 		/* PP counter */
182 		if (MALI_TRUE == is_sub_job) {
183 			/* Get counter for a particular sub job */
184 			if (0 == src_id) {
185 				val = mali_pp_job_get_pp_counter_sub_job_src0(sub_job);
186 			} else {
187 				val = mali_pp_job_get_pp_counter_sub_job_src1(sub_job);
188 			}
189 		} else {
190 			/* Get default counter for all PP sub jobs */
191 			if (0 == src_id) {
192 				val = mali_pp_job_get_pp_counter_global_src0();
193 			} else {
194 				val = mali_pp_job_get_pp_counter_global_src1();
195 			}
196 		}
197 	} else {
198 		/* GP counter */
199 		if (0 == src_id) {
200 			val = mali_gp_job_get_gp_counter_src0();
201 		} else {
202 			val = mali_gp_job_get_gp_counter_src1();
203 		}
204 	}
205 
206 	if (MALI_HW_CORE_NO_COUNTER == val) {
207 		r = snprintf(buf, 64, "-1\n");
208 	} else {
209 		r = snprintf(buf, 64, "%u\n", val);
210 	}
211 
212 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
213 }
214 
profiling_counter_src_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)215 static ssize_t profiling_counter_src_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
216 {
217 	u32 is_pp = PRIVATE_DATA_COUNTER_IS_PP((uintptr_t)filp->private_data);
218 	u32 src_id = PRIVATE_DATA_COUNTER_GET_SRC((uintptr_t)filp->private_data);
219 	mali_bool is_sub_job = PRIVATE_DATA_COUNTER_IS_SUB_JOB((uintptr_t)filp->private_data);
220 	u32 sub_job = PRIVATE_DATA_COUNTER_GET_SUB_JOB((uintptr_t)filp->private_data);
221 	char buf[64];
222 	long val;
223 	int ret;
224 
225 	if (cnt >= sizeof(buf)) {
226 		return -EINVAL;
227 	}
228 
229 	if (copy_from_user(&buf, ubuf, cnt)) {
230 		return -EFAULT;
231 	}
232 
233 	buf[cnt] = 0;
234 
235 	ret = kstrtol(buf, 10, &val);
236 	if (ret < 0) {
237 		return ret;
238 	}
239 
240 	if (val < 0) {
241 		/* any negative input will disable counter */
242 		val = MALI_HW_CORE_NO_COUNTER;
243 	}
244 
245 	if (MALI_TRUE == is_pp) {
246 		/* PP counter */
247 		if (MALI_TRUE == is_sub_job) {
248 			/* Set counter for a particular sub job */
249 			if (0 == src_id) {
250 				mali_pp_job_set_pp_counter_sub_job_src0(sub_job, (u32)val);
251 			} else {
252 				mali_pp_job_set_pp_counter_sub_job_src1(sub_job, (u32)val);
253 			}
254 		} else {
255 			/* Set default counter for all PP sub jobs */
256 			if (0 == src_id) {
257 				mali_pp_job_set_pp_counter_global_src0((u32)val);
258 			} else {
259 				mali_pp_job_set_pp_counter_global_src1((u32)val);
260 			}
261 		}
262 	} else {
263 		/* GP counter */
264 		if (0 == src_id) {
265 			mali_gp_job_set_gp_counter_src0((u32)val);
266 		} else {
267 			mali_gp_job_set_gp_counter_src1((u32)val);
268 		}
269 	}
270 
271 	*ppos += cnt;
272 	return cnt;
273 }
274 
275 static const struct file_operations profiling_counter_src_fops = {
276 	.owner = THIS_MODULE,
277 	.open  = open_copy_private_data,
278 	.read  = profiling_counter_src_read,
279 	.write = profiling_counter_src_write,
280 };
281 
l2_l2x_counter_srcx_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos,u32 src_id)282 static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
283 {
284 	char buf[64];
285 	int r;
286 	u32 val;
287 	struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
288 
289 	if (0 == src_id) {
290 		val = mali_l2_cache_core_get_counter_src0(l2_core);
291 	} else {
292 		val = mali_l2_cache_core_get_counter_src1(l2_core);
293 	}
294 
295 	if (MALI_HW_CORE_NO_COUNTER == val) {
296 		r = snprintf(buf, 64, "-1\n");
297 	} else {
298 		r = snprintf(buf, 64, "%u\n", val);
299 	}
300 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
301 }
302 
l2_l2x_counter_srcx_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos,u32 src_id)303 static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
304 {
305 	struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
306 	char buf[64];
307 	long val;
308 	int ret;
309 
310 	if (cnt >= sizeof(buf)) {
311 		return -EINVAL;
312 	}
313 
314 	if (copy_from_user(&buf, ubuf, cnt)) {
315 		return -EFAULT;
316 	}
317 
318 	buf[cnt] = 0;
319 
320 	ret = kstrtol(buf, 10, &val);
321 	if (ret < 0) {
322 		return ret;
323 	}
324 
325 	if (val < 0) {
326 		/* any negative input will disable counter */
327 		val = MALI_HW_CORE_NO_COUNTER;
328 	}
329 
330 	mali_l2_cache_core_set_counter_src(l2_core, src_id, (u32)val);
331 
332 	*ppos += cnt;
333 	return cnt;
334 }
335 
l2_all_counter_srcx_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos,u32 src_id)336 static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
337 {
338 	char buf[64];
339 	long val;
340 	int ret;
341 	u32 l2_id;
342 	struct mali_l2_cache_core *l2_cache;
343 
344 	if (cnt >= sizeof(buf)) {
345 		return -EINVAL;
346 	}
347 
348 	if (copy_from_user(&buf, ubuf, cnt)) {
349 		return -EFAULT;
350 	}
351 
352 	buf[cnt] = 0;
353 
354 	ret = kstrtol(buf, 10, &val);
355 	if (ret < 0) {
356 		return ret;
357 	}
358 
359 	if (val < 0) {
360 		/* any negative input will disable counter */
361 		val = MALI_HW_CORE_NO_COUNTER;
362 	}
363 
364 	l2_id = 0;
365 	l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
366 	while (NULL != l2_cache) {
367 		mali_l2_cache_core_set_counter_src(l2_cache, src_id, (u32)val);
368 
369 		/* try next L2 */
370 		l2_id++;
371 		l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
372 	}
373 
374 	*ppos += cnt;
375 	return cnt;
376 }
377 
l2_l2x_counter_src0_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)378 static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
379 {
380 	return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
381 }
382 
l2_l2x_counter_src1_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)383 static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
384 {
385 	return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
386 }
387 
l2_l2x_counter_src0_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)388 static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
389 {
390 	return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
391 }
392 
l2_l2x_counter_src1_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)393 static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
394 {
395 	return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
396 }
397 
l2_all_counter_src0_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)398 static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
399 {
400 	return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
401 }
402 
l2_all_counter_src1_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)403 static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
404 {
405 	return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
406 }
407 
408 static const struct file_operations l2_l2x_counter_src0_fops = {
409 	.owner = THIS_MODULE,
410 	.open  = open_copy_private_data,
411 	.read  = l2_l2x_counter_src0_read,
412 	.write = l2_l2x_counter_src0_write,
413 };
414 
415 static const struct file_operations l2_l2x_counter_src1_fops = {
416 	.owner = THIS_MODULE,
417 	.open  = open_copy_private_data,
418 	.read  = l2_l2x_counter_src1_read,
419 	.write = l2_l2x_counter_src1_write,
420 };
421 
422 static const struct file_operations l2_all_counter_src0_fops = {
423 	.owner = THIS_MODULE,
424 	.write = l2_all_counter_src0_write,
425 };
426 
427 static const struct file_operations l2_all_counter_src1_fops = {
428 	.owner = THIS_MODULE,
429 	.write = l2_all_counter_src1_write,
430 };
431 
l2_l2x_counter_valx_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos,u32 src_id)432 static ssize_t l2_l2x_counter_valx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
433 {
434 	char buf[64];
435 	int r;
436 	u32 src0 = 0;
437 	u32 val0 = 0;
438 	u32 src1 = 0;
439 	u32 val1 = 0;
440 	u32 val = -1;
441 	struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
442 
443 	mali_l2_cache_core_get_counter_values(l2_core, &src0, &val0, &src1, &val1);
444 
445 	if (0 == src_id) {
446 		if (MALI_HW_CORE_NO_COUNTER != val0) {
447 			val = val0;
448 		}
449 	} else {
450 		if (MALI_HW_CORE_NO_COUNTER != val1) {
451 			val = val1;
452 		}
453 	}
454 
455 	r = snprintf(buf, 64, "%u\n", val);
456 
457 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
458 }
459 
l2_l2x_counter_val0_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)460 static ssize_t l2_l2x_counter_val0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
461 {
462 	return l2_l2x_counter_valx_read(filp, ubuf, cnt, ppos, 0);
463 }
464 
l2_l2x_counter_val1_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)465 static ssize_t l2_l2x_counter_val1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
466 {
467 	return l2_l2x_counter_valx_read(filp, ubuf, cnt, ppos, 1);
468 }
469 
470 static const struct file_operations l2_l2x_counter_val0_fops = {
471 	.owner = THIS_MODULE,
472 	.open  = open_copy_private_data,
473 	.read  = l2_l2x_counter_val0_read,
474 };
475 
476 static const struct file_operations l2_l2x_counter_val1_fops = {
477 	.owner = THIS_MODULE,
478 	.open  = open_copy_private_data,
479 	.read  = l2_l2x_counter_val1_read,
480 };
481 
power_always_on_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)482 static ssize_t power_always_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
483 {
484 	unsigned long val;
485 	int ret;
486 	char buf[32];
487 
488 	cnt = min(cnt, sizeof(buf) - 1);
489 	if (copy_from_user(buf, ubuf, cnt)) {
490 		return -EFAULT;
491 	}
492 	buf[cnt] = '\0';
493 
494 	ret = kstrtoul(buf, 10, &val);
495 	if (0 != ret) {
496 		return ret;
497 	}
498 
499 	/* Update setting (not exactly thread safe) */
500 	if (1 == val && MALI_FALSE == power_always_on_enabled) {
501 		power_always_on_enabled = MALI_TRUE;
502 		_mali_osk_pm_dev_ref_get_sync();
503 	} else if (0 == val && MALI_TRUE == power_always_on_enabled) {
504 		power_always_on_enabled = MALI_FALSE;
505 		_mali_osk_pm_dev_ref_put();
506 	}
507 
508 	*ppos += cnt;
509 	return cnt;
510 }
511 
power_always_on_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)512 static ssize_t power_always_on_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
513 {
514 	if (MALI_TRUE == power_always_on_enabled) {
515 		return simple_read_from_buffer(ubuf, cnt, ppos, "1\n", 2);
516 	} else {
517 		return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2);
518 	}
519 }
520 
521 static const struct file_operations power_always_on_fops = {
522 	.owner = THIS_MODULE,
523 	.read  = power_always_on_read,
524 	.write = power_always_on_write,
525 };
526 
power_power_events_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)527 static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
528 {
529 	if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_SUSPEND], strlen(mali_power_events[_MALI_DEVICE_SUSPEND]) - 1)) {
530 		mali_pm_os_suspend(MALI_TRUE);
531 	} else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_RESUME], strlen(mali_power_events[_MALI_DEVICE_RESUME]) - 1)) {
532 		mali_pm_os_resume();
533 	} else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_DVFS_PAUSE], strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE]) - 1)) {
534 		mali_dev_pause();
535 	} else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_DVFS_RESUME], strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME]) - 1)) {
536 		mali_dev_resume();
537 	}
538 	*ppos += cnt;
539 	return cnt;
540 }
541 
power_power_events_seek(struct file * file,loff_t offset,int orig)542 static loff_t power_power_events_seek(struct file *file, loff_t offset, int orig)
543 {
544 	file->f_pos = offset;
545 	return 0;
546 }
547 
548 static const struct file_operations power_power_events_fops = {
549 	.owner = THIS_MODULE,
550 	.write = power_power_events_write,
551 	.llseek = power_power_events_seek,
552 };
553 
554 #if MALI_STATE_TRACKING
mali_seq_internal_state_show(struct seq_file * seq_file,void * v)555 static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
556 {
557 	u32 len = 0;
558 	u32 size;
559 	char *buf;
560 
561 	size = seq_get_buf(seq_file, &buf);
562 
563 	if (!size) {
564 		return -ENOMEM;
565 	}
566 
567 	/* Create the internal state dump. */
568 	len  = snprintf(buf + len, size - len, "Mali device driver %s\n", SVN_REV_STRING);
569 	len += snprintf(buf + len, size - len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE);
570 
571 	len += _mali_kernel_core_dump_state(buf + len, size - len);
572 
573 	seq_commit(seq_file, len);
574 
575 	return 0;
576 }
577 
mali_seq_internal_state_open(struct inode * inode,struct file * file)578 static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
579 {
580 	return single_open(file, mali_seq_internal_state_show, NULL);
581 }
582 
583 static const struct file_operations mali_seq_internal_state_fops = {
584 	.owner = THIS_MODULE,
585 	.open = mali_seq_internal_state_open,
586 	.read = seq_read,
587 	.llseek = seq_lseek,
588 	.release = single_release,
589 };
590 #endif /* MALI_STATE_TRACKING */
591 
592 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
profiling_record_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)593 static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
594 {
595 	char buf[64];
596 	int r;
597 
598 	r = snprintf(buf, 64, "%u\n", _mali_internal_profiling_is_recording() ? 1 : 0);
599 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
600 }
601 
profiling_record_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)602 static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
603 {
604 	char buf[64];
605 	unsigned long val;
606 	int ret;
607 
608 	if (cnt >= sizeof(buf)) {
609 		return -EINVAL;
610 	}
611 
612 	if (copy_from_user(&buf, ubuf, cnt)) {
613 		return -EFAULT;
614 	}
615 
616 	buf[cnt] = 0;
617 
618 	ret = kstrtoul(buf, 10, &val);
619 	if (ret < 0) {
620 		return ret;
621 	}
622 
623 	if (val != 0) {
624 		u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */
625 
626 		/* check if we are already recording */
627 		if (MALI_TRUE == _mali_internal_profiling_is_recording()) {
628 			MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n"));
629 			return -EFAULT;
630 		}
631 
632 		/* check if we need to clear out an old recording first */
633 		if (MALI_TRUE == _mali_internal_profiling_have_recording()) {
634 			if (_MALI_OSK_ERR_OK != _mali_internal_profiling_clear()) {
635 				MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n"));
636 				return -EFAULT;
637 			}
638 		}
639 
640 		/* start recording profiling data */
641 		if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) {
642 			MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n"));
643 			return -EFAULT;
644 		}
645 
646 		MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit));
647 	} else {
648 		/* stop recording profiling data */
649 		u32 count = 0;
650 		if (_MALI_OSK_ERR_OK != _mali_internal_profiling_stop(&count)) {
651 			MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
652 			return -EFAULT;
653 		}
654 
655 		MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count));
656 	}
657 
658 	*ppos += cnt;
659 	return cnt;
660 }
661 
662 static const struct file_operations profiling_record_fops = {
663 	.owner = THIS_MODULE,
664 	.read  = profiling_record_read,
665 	.write = profiling_record_write,
666 };
667 
profiling_events_start(struct seq_file * s,loff_t * pos)668 static void *profiling_events_start(struct seq_file *s, loff_t *pos)
669 {
670 	loff_t *spos;
671 
672 	/* check if we have data avaiable */
673 	if (MALI_TRUE != _mali_internal_profiling_have_recording()) {
674 		return NULL;
675 	}
676 
677 	spos = kmalloc(sizeof(loff_t), GFP_KERNEL);
678 	if (NULL == spos) {
679 		return NULL;
680 	}
681 
682 	*spos = *pos;
683 	return spos;
684 }
685 
profiling_events_next(struct seq_file * s,void * v,loff_t * pos)686 static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos)
687 {
688 	loff_t *spos = v;
689 
690 	/* check if we have data avaiable */
691 	if (MALI_TRUE != _mali_internal_profiling_have_recording()) {
692 		return NULL;
693 	}
694 
695 	/* check if the next entry actually is avaiable */
696 	if (_mali_internal_profiling_get_count() <= (u32)(*spos + 1)) {
697 		return NULL;
698 	}
699 
700 	*pos = ++*spos;
701 	return spos;
702 }
703 
profiling_events_stop(struct seq_file * s,void * v)704 static void profiling_events_stop(struct seq_file *s, void *v)
705 {
706 	kfree(v);
707 }
708 
profiling_events_show(struct seq_file * seq_file,void * v)709 static int profiling_events_show(struct seq_file *seq_file, void *v)
710 {
711 	loff_t *spos = v;
712 	u32 index;
713 	u64 timestamp;
714 	u32 event_id;
715 	u32 data[5];
716 
717 	index = (u32) * spos;
718 
719 	/* Retrieve all events */
720 	if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, &timestamp, &event_id, data)) {
721 		seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
722 		return 0;
723 	}
724 
725 	return 0;
726 }
727 
profiling_events_show_human_readable(struct seq_file * seq_file,void * v)728 static int profiling_events_show_human_readable(struct seq_file *seq_file, void *v)
729 {
730 #define MALI_EVENT_ID_IS_HW(event_id) (((event_id & 0x00FF0000) >= MALI_PROFILING_EVENT_CHANNEL_GP0) && ((event_id & 0x00FF0000) <= MALI_PROFILING_EVENT_CHANNEL_PP7))
731 
732 	static u64 start_time = 0;
733 	loff_t *spos = v;
734 	u32 index;
735 	u64 timestamp;
736 	u32 event_id;
737 	u32 data[5];
738 
739 	index = (u32) * spos;
740 
741 	/* Retrieve all events */
742 	if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, &timestamp, &event_id, data)) {
743 		seq_printf(seq_file, "%llu %u %u %u %u %u %u # ", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
744 
745 		if (0 == index) {
746 			start_time = timestamp;
747 		}
748 
749 		seq_printf(seq_file, "[%06u] ", index);
750 
751 		switch (event_id & 0x0F000000) {
752 		case MALI_PROFILING_EVENT_TYPE_SINGLE:
753 			seq_printf(seq_file, "SINGLE | ");
754 			break;
755 		case MALI_PROFILING_EVENT_TYPE_START:
756 			seq_printf(seq_file, "START | ");
757 			break;
758 		case MALI_PROFILING_EVENT_TYPE_STOP:
759 			seq_printf(seq_file, "STOP | ");
760 			break;
761 		case MALI_PROFILING_EVENT_TYPE_SUSPEND:
762 			seq_printf(seq_file, "SUSPEND | ");
763 			break;
764 		case MALI_PROFILING_EVENT_TYPE_RESUME:
765 			seq_printf(seq_file, "RESUME | ");
766 			break;
767 		default:
768 			seq_printf(seq_file, "0x%01X | ", (event_id & 0x0F000000) >> 24);
769 			break;
770 		}
771 
772 		switch (event_id & 0x00FF0000) {
773 		case MALI_PROFILING_EVENT_CHANNEL_SOFTWARE:
774 			seq_printf(seq_file, "SW | ");
775 			break;
776 		case MALI_PROFILING_EVENT_CHANNEL_GP0:
777 			seq_printf(seq_file, "GP0 | ");
778 			break;
779 		case MALI_PROFILING_EVENT_CHANNEL_PP0:
780 			seq_printf(seq_file, "PP0 | ");
781 			break;
782 		case MALI_PROFILING_EVENT_CHANNEL_PP1:
783 			seq_printf(seq_file, "PP1 | ");
784 			break;
785 		case MALI_PROFILING_EVENT_CHANNEL_PP2:
786 			seq_printf(seq_file, "PP2 | ");
787 			break;
788 		case MALI_PROFILING_EVENT_CHANNEL_PP3:
789 			seq_printf(seq_file, "PP3 | ");
790 			break;
791 		case MALI_PROFILING_EVENT_CHANNEL_PP4:
792 			seq_printf(seq_file, "PP4 | ");
793 			break;
794 		case MALI_PROFILING_EVENT_CHANNEL_PP5:
795 			seq_printf(seq_file, "PP5 | ");
796 			break;
797 		case MALI_PROFILING_EVENT_CHANNEL_PP6:
798 			seq_printf(seq_file, "PP6 | ");
799 			break;
800 		case MALI_PROFILING_EVENT_CHANNEL_PP7:
801 			seq_printf(seq_file, "PP7 | ");
802 			break;
803 		case MALI_PROFILING_EVENT_CHANNEL_GPU:
804 			seq_printf(seq_file, "GPU | ");
805 			break;
806 		default:
807 			seq_printf(seq_file, "0x%02X | ", (event_id & 0x00FF0000) >> 16);
808 			break;
809 		}
810 
811 		if (MALI_EVENT_ID_IS_HW(event_id)) {
812 			if (((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_START) || ((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_STOP)) {
813 				switch (event_id & 0x0000FFFF) {
814 				case MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL:
815 					seq_printf(seq_file, "PHYSICAL | ");
816 					break;
817 				case MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL:
818 					seq_printf(seq_file, "VIRTUAL | ");
819 					break;
820 				default:
821 					seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
822 					break;
823 				}
824 			} else {
825 				seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
826 			}
827 		} else {
828 			seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
829 		}
830 
831 		seq_printf(seq_file, "T0 + 0x%016llX\n", timestamp - start_time);
832 
833 		return 0;
834 	}
835 
836 	return 0;
837 }
838 
839 static const struct seq_operations profiling_events_seq_ops = {
840 	.start = profiling_events_start,
841 	.next  = profiling_events_next,
842 	.stop  = profiling_events_stop,
843 	.show  = profiling_events_show
844 };
845 
profiling_events_open(struct inode * inode,struct file * file)846 static int profiling_events_open(struct inode *inode, struct file *file)
847 {
848 	return seq_open(file, &profiling_events_seq_ops);
849 }
850 
851 static const struct file_operations profiling_events_fops = {
852 	.owner = THIS_MODULE,
853 	.open = profiling_events_open,
854 	.read = seq_read,
855 	.llseek = seq_lseek,
856 	.release = seq_release,
857 };
858 
859 static const struct seq_operations profiling_events_human_readable_seq_ops = {
860 	.start = profiling_events_start,
861 	.next  = profiling_events_next,
862 	.stop  = profiling_events_stop,
863 	.show  = profiling_events_show_human_readable
864 };
865 
profiling_events_human_readable_open(struct inode * inode,struct file * file)866 static int profiling_events_human_readable_open(struct inode *inode, struct file *file)
867 {
868 	return seq_open(file, &profiling_events_human_readable_seq_ops);
869 }
870 
871 static const struct file_operations profiling_events_human_readable_fops = {
872 	.owner = THIS_MODULE,
873 	.open = profiling_events_human_readable_open,
874 	.read = seq_read,
875 	.llseek = seq_lseek,
876 	.release = seq_release,
877 };
878 
879 #endif
880 
memory_debugfs_show(struct seq_file * s,void * private_data)881 static int memory_debugfs_show(struct seq_file *s, void *private_data)
882 {
883 #ifdef MALI_MEM_SWAP_TRACKING
884 	seq_printf(s, "  %-25s  %-10s  %-10s  %-15s  %-15s  %-10s  %-10s %-10s \n"\
885 		   "=================================================================================================================================\n",
886 		   "Name (:bytes)", "pid", "mali_mem", "max_mali_mem",
887 		   "external_mem", "ump_mem", "dma_mem", "swap_mem");
888 #else
889 	seq_printf(s, "  %-25s  %-10s  %-10s  %-15s  %-15s  %-10s  %-10s \n"\
890 		   "========================================================================================================================\n",
891 		   "Name (:bytes)", "pid", "mali_mem", "max_mali_mem",
892 		   "external_mem", "ump_mem", "dma_mem");
893 #endif
894 	mali_session_memory_tracking(s);
895 	return 0;
896 }
897 
memory_debugfs_open(struct inode * inode,struct file * file)898 static int memory_debugfs_open(struct inode *inode, struct file *file)
899 {
900 	return single_open(file, memory_debugfs_show, inode->i_private);
901 }
902 
903 static const struct file_operations memory_usage_fops = {
904 	.owner = THIS_MODULE,
905 	.open = memory_debugfs_open,
906 	.read  = seq_read,
907 	.llseek = seq_lseek,
908 	.release = single_release,
909 };
910 
utilization_gp_pp_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)911 static ssize_t utilization_gp_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
912 {
913 	char buf[64];
914 	size_t r;
915 	u32 uval = _mali_ukk_utilization_gp_pp();
916 
917 	r = snprintf(buf, 64, "%u\n", uval);
918 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
919 }
920 
utilization_gp_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)921 static ssize_t utilization_gp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
922 {
923 	char buf[64];
924 	size_t r;
925 	u32 uval = _mali_ukk_utilization_gp();
926 
927 	r = snprintf(buf, 64, "%u\n", uval);
928 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
929 }
930 
utilization_pp_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)931 static ssize_t utilization_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
932 {
933 	char buf[64];
934 	size_t r;
935 	u32 uval = _mali_ukk_utilization_pp();
936 
937 	r = snprintf(buf, 64, "%u\n", uval);
938 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
939 }
940 
941 
942 static const struct file_operations utilization_gp_pp_fops = {
943 	.owner = THIS_MODULE,
944 	.read = utilization_gp_pp_read,
945 };
946 
947 static const struct file_operations utilization_gp_fops = {
948 	.owner = THIS_MODULE,
949 	.read = utilization_gp_read,
950 };
951 
952 static const struct file_operations utilization_pp_fops = {
953 	.owner = THIS_MODULE,
954 	.read = utilization_pp_read,
955 };
956 
user_settings_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)957 static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
958 {
959 	unsigned long val;
960 	int ret;
961 	_mali_uk_user_setting_t setting;
962 	char buf[32];
963 
964 	cnt = min(cnt, sizeof(buf) - 1);
965 	if (copy_from_user(buf, ubuf, cnt)) {
966 		return -EFAULT;
967 	}
968 	buf[cnt] = '\0';
969 
970 	ret = kstrtoul(buf, 10, &val);
971 	if (0 != ret) {
972 		return ret;
973 	}
974 
975 	/* Update setting */
976 	setting = (_mali_uk_user_setting_t)(filp->private_data);
977 	mali_set_user_setting(setting, val);
978 
979 	*ppos += cnt;
980 	return cnt;
981 }
982 
user_settings_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)983 static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
984 {
985 	char buf[64];
986 	size_t r;
987 	u32 value;
988 	_mali_uk_user_setting_t setting;
989 
990 	setting = (_mali_uk_user_setting_t)(filp->private_data);
991 	value = mali_get_user_setting(setting);
992 
993 	r = snprintf(buf, 64, "%u\n", value);
994 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
995 }
996 
997 static const struct file_operations user_settings_fops = {
998 	.owner = THIS_MODULE,
999 	.open = open_copy_private_data,
1000 	.read = user_settings_read,
1001 	.write = user_settings_write,
1002 };
1003 
mali_sysfs_user_settings_register(void)1004 static int mali_sysfs_user_settings_register(void)
1005 {
1006 	struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
1007 
1008 	if (mali_user_settings_dir != NULL) {
1009 		long i;
1010 		for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) {
1011 			debugfs_create_file(_mali_uk_user_setting_descriptions[i],
1012 					    0600, mali_user_settings_dir, (void *)i,
1013 					    &user_settings_fops);
1014 		}
1015 	}
1016 
1017 	return 0;
1018 }
1019 
pp_num_cores_enabled_write(struct file * filp,const char __user * buf,size_t count,loff_t * offp)1020 static ssize_t pp_num_cores_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
1021 {
1022 	int ret;
1023 	char buffer[32];
1024 	unsigned long val;
1025 
1026 	if (count >= sizeof(buffer)) {
1027 		return -ENOMEM;
1028 	}
1029 
1030 	if (copy_from_user(&buffer[0], buf, count)) {
1031 		return -EFAULT;
1032 	}
1033 	buffer[count] = '\0';
1034 
1035 	ret = kstrtoul(&buffer[0], 10, &val);
1036 	if (0 != ret) {
1037 		return -EINVAL;
1038 	}
1039 
1040 	ret = mali_executor_set_perf_level(val, MALI_TRUE); /* override even if core scaling is disabled */
1041 	if (ret) {
1042 		return ret;
1043 	}
1044 
1045 	*offp += count;
1046 	return count;
1047 }
1048 
pp_num_cores_enabled_read(struct file * filp,char __user * buf,size_t count,loff_t * offp)1049 static ssize_t pp_num_cores_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1050 {
1051 	int r;
1052 	char buffer[64];
1053 
1054 	r = snprintf(buffer, 64, "%u\n", mali_executor_get_num_cores_enabled());
1055 
1056 	return simple_read_from_buffer(buf, count, offp, buffer, r);
1057 }
1058 
1059 static const struct file_operations pp_num_cores_enabled_fops = {
1060 	.owner = THIS_MODULE,
1061 	.write = pp_num_cores_enabled_write,
1062 	.read = pp_num_cores_enabled_read,
1063 	.llseek = default_llseek,
1064 };
1065 
pp_num_cores_total_read(struct file * filp,char __user * buf,size_t count,loff_t * offp)1066 static ssize_t pp_num_cores_total_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1067 {
1068 	int r;
1069 	char buffer[64];
1070 
1071 	r = snprintf(buffer, 64, "%u\n", mali_executor_get_num_cores_total());
1072 
1073 	return simple_read_from_buffer(buf, count, offp, buffer, r);
1074 }
1075 
1076 static const struct file_operations pp_num_cores_total_fops = {
1077 	.owner = THIS_MODULE,
1078 	.read = pp_num_cores_total_read,
1079 };
1080 
pp_core_scaling_enabled_write(struct file * filp,const char __user * buf,size_t count,loff_t * offp)1081 static ssize_t pp_core_scaling_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
1082 {
1083 	int ret;
1084 	char buffer[32];
1085 	unsigned long val;
1086 
1087 	if (count >= sizeof(buffer)) {
1088 		return -ENOMEM;
1089 	}
1090 
1091 	if (copy_from_user(&buffer[0], buf, count)) {
1092 		return -EFAULT;
1093 	}
1094 	buffer[count] = '\0';
1095 
1096 	ret = kstrtoul(&buffer[0], 10, &val);
1097 	if (0 != ret) {
1098 		return -EINVAL;
1099 	}
1100 
1101 	switch (val) {
1102 	case 1:
1103 		mali_executor_core_scaling_enable();
1104 		break;
1105 	case 0:
1106 		mali_executor_core_scaling_disable();
1107 		break;
1108 	default:
1109 		return -EINVAL;
1110 		break;
1111 	}
1112 
1113 	*offp += count;
1114 	return count;
1115 }
1116 
pp_core_scaling_enabled_read(struct file * filp,char __user * buf,size_t count,loff_t * offp)1117 static ssize_t pp_core_scaling_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1118 {
1119 	return simple_read_from_buffer(buf, count, offp, mali_executor_core_scaling_is_enabled() ? "1\n" : "0\n", 2);
1120 }
1121 static const struct file_operations pp_core_scaling_enabled_fops = {
1122 	.owner = THIS_MODULE,
1123 	.write = pp_core_scaling_enabled_write,
1124 	.read = pp_core_scaling_enabled_read,
1125 	.llseek = default_llseek,
1126 };
1127 
version_read(struct file * filp,char __user * buf,size_t count,loff_t * offp)1128 static ssize_t version_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1129 {
1130 	int r = 0;
1131 	char buffer[64];
1132 
1133 	switch (mali_kernel_core_get_product_id()) {
1134 	case _MALI_PRODUCT_ID_MALI200:
1135 		r = snprintf(buffer, 64, "Mali-200\n");
1136 		break;
1137 	case _MALI_PRODUCT_ID_MALI300:
1138 		r = snprintf(buffer, 64, "Mali-300\n");
1139 		break;
1140 	case _MALI_PRODUCT_ID_MALI400:
1141 		r = snprintf(buffer, 64, "Mali-400 MP\n");
1142 		break;
1143 	case _MALI_PRODUCT_ID_MALI450:
1144 		r = snprintf(buffer, 64, "Mali-450 MP\n");
1145 		break;
1146 	case _MALI_PRODUCT_ID_MALI470:
1147 		r = snprintf(buffer, 64, "Mali-470 MP\n");
1148 		break;
1149 	case _MALI_PRODUCT_ID_UNKNOWN:
1150 		return -EINVAL;
1151 		break;
1152 	};
1153 
1154 	return simple_read_from_buffer(buf, count, offp, buffer, r);
1155 }
1156 
1157 static const struct file_operations version_fops = {
1158 	.owner = THIS_MODULE,
1159 	.read = version_read,
1160 };
1161 
1162 #if defined(DEBUG)
timeline_debugfs_show(struct seq_file * s,void * private_data)1163 static int timeline_debugfs_show(struct seq_file *s, void *private_data)
1164 {
1165 	struct mali_session_data *session, *tmp;
1166 	u32 session_seq = 1;
1167 
1168 	seq_printf(s, "timeline system info: \n=================\n\n");
1169 
1170 	mali_session_lock();
1171 	MALI_SESSION_FOREACH(session, tmp, link) {
1172 		seq_printf(s, "session %d <%p> start:\n", session_seq, session);
1173 		mali_timeline_debug_print_system(session->timeline_system, s);
1174 		seq_printf(s, "session %d end\n\n\n", session_seq++);
1175 	}
1176 	mali_session_unlock();
1177 
1178 	return 0;
1179 }
1180 
timeline_debugfs_open(struct inode * inode,struct file * file)1181 static int timeline_debugfs_open(struct inode *inode, struct file *file)
1182 {
1183 	return single_open(file, timeline_debugfs_show, inode->i_private);
1184 }
1185 
1186 static const struct file_operations timeline_dump_fops = {
1187 	.owner = THIS_MODULE,
1188 	.open = timeline_debugfs_open,
1189 	.read  = seq_read,
1190 	.llseek = seq_lseek,
1191 	.release = single_release
1192 };
1193 #endif
1194 
mali_sysfs_register(const char * mali_dev_name)1195 int mali_sysfs_register(const char *mali_dev_name)
1196 {
1197 	mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
1198 	if (ERR_PTR(-ENODEV) == mali_debugfs_dir) {
1199 		/* Debugfs not supported. */
1200 		mali_debugfs_dir = NULL;
1201 	} else {
1202 		if (NULL != mali_debugfs_dir) {
1203 			/* Debugfs directory created successfully; create files now */
1204 			struct dentry *mali_power_dir;
1205 			struct dentry *mali_gp_dir;
1206 			struct dentry *mali_pp_dir;
1207 			struct dentry *mali_l2_dir;
1208 			struct dentry *mali_profiling_dir;
1209 
1210 			debugfs_create_file("version", 0400, mali_debugfs_dir, NULL, &version_fops);
1211 
1212 			mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
1213 			if (mali_power_dir != NULL) {
1214 				debugfs_create_file("always_on", 0600, mali_power_dir, NULL, &power_always_on_fops);
1215 				debugfs_create_file("power_events", 0200, mali_power_dir, NULL, &power_power_events_fops);
1216 			}
1217 
1218 			mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
1219 			if (mali_gp_dir != NULL) {
1220 				u32 num_groups;
1221 				long i;
1222 
1223 				num_groups = mali_group_get_glob_num_groups();
1224 				for (i = 0; i < num_groups; i++) {
1225 					struct mali_group *group = mali_group_get_glob_group(i);
1226 
1227 					struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
1228 					if (NULL != gp_core) {
1229 						struct dentry *mali_gp_gpx_dir;
1230 						mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
1231 						if (NULL != mali_gp_gpx_dir) {
1232 							debugfs_create_file("base_addr", 0400, mali_gp_gpx_dir, &gp_core->hw_core, &hw_core_base_addr_fops);
1233 							debugfs_create_file("enabled", 0600, mali_gp_gpx_dir, group, &group_enabled_fops);
1234 						}
1235 						break; /* no need to look for any other GP cores */
1236 					}
1237 
1238 				}
1239 			}
1240 
1241 			mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
1242 			if (mali_pp_dir != NULL) {
1243 				u32 num_groups;
1244 				long i;
1245 
1246 				debugfs_create_file("num_cores_total", 0400, mali_pp_dir, NULL, &pp_num_cores_total_fops);
1247 				debugfs_create_file("num_cores_enabled", 0600, mali_pp_dir, NULL, &pp_num_cores_enabled_fops);
1248 				debugfs_create_file("core_scaling_enabled", 0600, mali_pp_dir, NULL, &pp_core_scaling_enabled_fops);
1249 
1250 				num_groups = mali_group_get_glob_num_groups();
1251 				for (i = 0; i < num_groups; i++) {
1252 					struct mali_group *group = mali_group_get_glob_group(i);
1253 
1254 					struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
1255 					if (NULL != pp_core) {
1256 						char buf[16];
1257 						struct dentry *mali_pp_ppx_dir;
1258 						_mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
1259 						mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
1260 						if (NULL != mali_pp_ppx_dir) {
1261 							debugfs_create_file("base_addr", 0400, mali_pp_ppx_dir, &pp_core->hw_core, &hw_core_base_addr_fops);
1262 							if (!mali_group_is_virtual(group)) {
1263 								debugfs_create_file("enabled", 0600, mali_pp_ppx_dir, group, &group_enabled_fops);
1264 							}
1265 						}
1266 					}
1267 				}
1268 			}
1269 
1270 			mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
1271 			if (mali_l2_dir != NULL) {
1272 				struct dentry *mali_l2_all_dir;
1273 				u32 l2_id;
1274 				struct mali_l2_cache_core *l2_cache;
1275 
1276 				mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
1277 				if (mali_l2_all_dir != NULL) {
1278 					debugfs_create_file("counter_src0", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
1279 					debugfs_create_file("counter_src1", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
1280 				}
1281 
1282 				l2_id = 0;
1283 				l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1284 				while (NULL != l2_cache) {
1285 					char buf[16];
1286 					struct dentry *mali_l2_l2x_dir;
1287 					_mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
1288 					mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
1289 					if (NULL != mali_l2_l2x_dir) {
1290 						debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
1291 						debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
1292 						debugfs_create_file("counter_val0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_val0_fops);
1293 						debugfs_create_file("counter_val1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_val1_fops);
1294 						debugfs_create_file("base_addr", 0400, mali_l2_l2x_dir, &l2_cache->hw_core, &hw_core_base_addr_fops);
1295 					}
1296 
1297 					/* try next L2 */
1298 					l2_id++;
1299 					l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1300 				}
1301 			}
1302 
1303 			debugfs_create_file("gpu_memory", 0444, mali_debugfs_dir, NULL, &memory_usage_fops);
1304 
1305 			debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops);
1306 			debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops);
1307 			debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops);
1308 
1309 			mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
1310 			if (mali_profiling_dir != NULL) {
1311 				u32 max_sub_jobs;
1312 				long i;
1313 				struct dentry *mali_profiling_gp_dir;
1314 				struct dentry *mali_profiling_pp_dir;
1315 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1316 				struct dentry *mali_profiling_proc_dir;
1317 #endif
1318 				/*
1319 				 * Create directory where we can set GP HW counters.
1320 				 */
1321 				mali_profiling_gp_dir = debugfs_create_dir("gp", mali_profiling_dir);
1322 				if (mali_profiling_gp_dir != NULL) {
1323 					debugfs_create_file("counter_src0", 0600, mali_profiling_gp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_GP(0), &profiling_counter_src_fops);
1324 					debugfs_create_file("counter_src1", 0600, mali_profiling_gp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_GP(1), &profiling_counter_src_fops);
1325 				}
1326 
1327 				/*
1328 				 * Create directory where we can set PP HW counters.
1329 				 * Possible override with specific HW counters for a particular sub job
1330 				 * (Disable core scaling before using the override!)
1331 				 */
1332 				mali_profiling_pp_dir = debugfs_create_dir("pp", mali_profiling_dir);
1333 				if (mali_profiling_pp_dir != NULL) {
1334 					debugfs_create_file("counter_src0", 0600, mali_profiling_pp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_PP(0), &profiling_counter_src_fops);
1335 					debugfs_create_file("counter_src1", 0600, mali_profiling_pp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_PP(1), &profiling_counter_src_fops);
1336 				}
1337 
1338 				max_sub_jobs = mali_executor_get_num_cores_total();
1339 				for (i = 0; i < max_sub_jobs; i++) {
1340 					char buf[16];
1341 					struct dentry *mali_profiling_pp_x_dir;
1342 					_mali_osk_snprintf(buf, sizeof(buf), "%u", i);
1343 					mali_profiling_pp_x_dir = debugfs_create_dir(buf, mali_profiling_pp_dir);
1344 					if (NULL != mali_profiling_pp_x_dir) {
1345 						debugfs_create_file("counter_src0",
1346 								    0600, mali_profiling_pp_x_dir,
1347 								    (void *)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(0, i),
1348 								    &profiling_counter_src_fops);
1349 						debugfs_create_file("counter_src1",
1350 								    0600, mali_profiling_pp_x_dir,
1351 								    (void *)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(1, i),
1352 								    &profiling_counter_src_fops);
1353 					}
1354 				}
1355 
1356 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1357 				mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir);
1358 				if (mali_profiling_proc_dir != NULL) {
1359 					struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir);
1360 					if (mali_profiling_proc_default_dir != NULL) {
1361 						debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void *)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
1362 					}
1363 				}
1364 				debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
1365 				debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
1366 				debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops);
1367 #endif
1368 			}
1369 
1370 #if MALI_STATE_TRACKING
1371 			debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
1372 #endif
1373 
1374 #if defined(DEBUG)
1375 			debugfs_create_file("timeline_dump", 0400, mali_debugfs_dir, NULL, &timeline_dump_fops);
1376 #endif
1377 			if (mali_sysfs_user_settings_register()) {
1378 				/* Failed to create the debugfs entries for the user settings DB. */
1379 				MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
1380 			}
1381 		}
1382 	}
1383 
1384 	/* Success! */
1385 	return 0;
1386 }
1387 
mali_sysfs_unregister(void)1388 int mali_sysfs_unregister(void)
1389 {
1390 	if (NULL != mali_debugfs_dir) {
1391 		debugfs_remove_recursive(mali_debugfs_dir);
1392 	}
1393 	return 0;
1394 }
1395 
1396 #else /* MALI_LICENSE_IS_GPL */
1397 
1398 /* Dummy implementations for non-GPL */
1399 
mali_sysfs_register(struct mali_dev * device,dev_t dev,const char * mali_dev_name)1400 int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1401 {
1402 	return 0;
1403 }
1404 
mali_sysfs_unregister(void)1405 int mali_sysfs_unregister(void)
1406 {
1407 	return 0;
1408 }
1409 
1410 #endif /* MALI_LICENSE_IS_GPL */
1411