2 * Copyright (C) 2011-2014 ARM Limited. All rights reserved.
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.
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.
13 * @file mali_kernel_sysfs.c
14 * Implementation of some sysfs data exports
17 #include <linux/kernel.h>
19 #include <linux/device.h>
20 #include <linux/module.h>
21 #include "mali_kernel_license.h"
22 #include "mali_kernel_common.h"
25 #if MALI_LICENSE_IS_GPL
27 #include <linux/seq_file.h>
28 #include <linux/debugfs.h>
29 #include <asm/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"
38 #include <linux/mali/mali_utgard.h>
41 #include "mali_group.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"
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)
61 #define POWER_BUFFER_SIZE 3
63 static struct dentry *mali_debugfs_dir = NULL;
68 _MALI_DEVICE_DVFS_PAUSE,
69 _MALI_DEVICE_DVFS_RESUME,
71 } _mali_device_debug_power_events;
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",
80 static mali_bool power_always_on_enabled = MALI_FALSE;
82 static int open_copy_private_data(struct inode *inode, struct file *filp)
84 filp->private_data = inode->i_private;
88 static ssize_t group_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
92 struct mali_group *group;
94 group = (struct mali_group *)filp->private_data;
95 MALI_DEBUG_ASSERT_POINTER(group);
97 r = snprintf(buffer, 64, "%u\n",
98 mali_executor_group_is_disabled(group) ? 0 : 1);
100 return simple_read_from_buffer(buf, count, offp, buffer, r);
103 static ssize_t group_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
108 struct mali_group *group;
110 group = (struct mali_group *)filp->private_data;
111 MALI_DEBUG_ASSERT_POINTER(group);
113 if (count >= sizeof(buffer)) {
117 if (copy_from_user(&buffer[0], buf, count)) {
120 buffer[count] = '\0';
122 r = kstrtoul(&buffer[0], 10, &val);
129 mali_executor_group_enable(group);
132 mali_executor_group_disable(group);
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,
150 static ssize_t hw_core_base_addr_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
154 struct mali_hw_core *hw_core;
156 hw_core = (struct mali_hw_core *)filp->private_data;
157 MALI_DEBUG_ASSERT_POINTER(hw_core);
159 r = snprintf(buffer, 64, "0x%lX\n", hw_core->phys_addr);
161 return simple_read_from_buffer(buf, count, offp, buffer, r);
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,
170 static ssize_t profiling_counter_src_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
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);
180 if (MALI_TRUE == is_pp) {
182 if (MALI_TRUE == is_sub_job) {
183 /* Get counter for a particular sub job */
185 val = mali_pp_job_get_pp_counter_sub_job_src0(sub_job);
187 val = mali_pp_job_get_pp_counter_sub_job_src1(sub_job);
190 /* Get default counter for all PP sub jobs */
192 val = mali_pp_job_get_pp_counter_global_src0();
194 val = mali_pp_job_get_pp_counter_global_src1();
200 val = mali_gp_job_get_gp_counter_src0();
202 val = mali_gp_job_get_gp_counter_src1();
206 if (MALI_HW_CORE_NO_COUNTER == val) {
207 r = snprintf(buf, 64, "-1\n");
209 r = snprintf(buf, 64, "%u\n", val);
212 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
215 static ssize_t profiling_counter_src_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
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);
225 if (cnt >= sizeof(buf)) {
229 if (copy_from_user(&buf, ubuf, cnt)) {
235 ret = kstrtol(buf, 10, &val);
241 /* any negative input will disable counter */
242 val = MALI_HW_CORE_NO_COUNTER;
245 if (MALI_TRUE == is_pp) {
247 if (MALI_TRUE == is_sub_job) {
248 /* Set counter for a particular sub job */
250 mali_pp_job_set_pp_counter_sub_job_src0(sub_job, (u32)val);
252 mali_pp_job_set_pp_counter_sub_job_src1(sub_job, (u32)val);
255 /* Set default counter for all PP sub jobs */
257 mali_pp_job_set_pp_counter_global_src0((u32)val);
259 mali_pp_job_set_pp_counter_global_src1((u32)val);
265 mali_gp_job_set_gp_counter_src0((u32)val);
267 mali_gp_job_set_gp_counter_src1((u32)val);
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,
282 static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
287 struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
290 val = mali_l2_cache_core_get_counter_src0(l2_core);
292 val = mali_l2_cache_core_get_counter_src1(l2_core);
295 if (MALI_HW_CORE_NO_COUNTER == val) {
296 r = snprintf(buf, 64, "-1\n");
298 r = snprintf(buf, 64, "%u\n", val);
300 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
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)
305 struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
310 if (cnt >= sizeof(buf)) {
314 if (copy_from_user(&buf, ubuf, cnt)) {
320 ret = kstrtol(buf, 10, &val);
326 /* any negative input will disable counter */
327 val = MALI_HW_CORE_NO_COUNTER;
330 mali_l2_cache_core_set_counter_src(l2_core, src_id, (u32)val);
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)
342 struct mali_l2_cache_core *l2_cache;
344 if (cnt >= sizeof(buf)) {
348 if (copy_from_user(&buf, ubuf, cnt)) {
354 ret = kstrtol(buf, 10, &val);
360 /* any negative input will disable counter */
361 val = MALI_HW_CORE_NO_COUNTER;
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);
371 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
378 static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
380 return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
383 static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
385 return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
388 static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
390 return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
393 static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
395 return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
398 static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
400 return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
403 static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
405 return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
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,
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,
422 static const struct file_operations l2_all_counter_src0_fops = {
423 .owner = THIS_MODULE,
424 .write = l2_all_counter_src0_write,
427 static const struct file_operations l2_all_counter_src1_fops = {
428 .owner = THIS_MODULE,
429 .write = l2_all_counter_src1_write,
432 static ssize_t l2_l2x_counter_valx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
441 struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
443 mali_l2_cache_core_get_counter_values(l2_core, &src0, &val0, &src1, &val1);
446 if (MALI_HW_CORE_NO_COUNTER != val0) {
450 if (MALI_HW_CORE_NO_COUNTER != val1) {
455 r = snprintf(buf, 64, "%u\n", val);
457 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
460 static ssize_t l2_l2x_counter_val0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
462 return l2_l2x_counter_valx_read(filp, ubuf, cnt, ppos, 0);
465 static ssize_t l2_l2x_counter_val1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
467 return l2_l2x_counter_valx_read(filp, ubuf, cnt, ppos, 1);
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,
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,
482 static ssize_t power_always_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
488 cnt = min(cnt, sizeof(buf) - 1);
489 if (copy_from_user(buf, ubuf, cnt)) {
494 ret = kstrtoul(buf, 10, &val);
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();
512 static ssize_t power_always_on_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
514 if (MALI_TRUE == power_always_on_enabled) {
515 return simple_read_from_buffer(ubuf, cnt, ppos, "1\n", 2);
517 return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2);
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,
527 static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
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)) {
533 } else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_DVFS_PAUSE], strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE])-1)) {
535 } else if (!strncmp(ubuf, mali_power_events[_MALI_DEVICE_DVFS_RESUME], strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME])-1)) {
542 static loff_t power_power_events_seek(struct file *file, loff_t offset, int orig)
544 file->f_pos = offset;
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,
554 #if MALI_STATE_TRACKING
555 static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
561 size = seq_get_buf(seq_file, &buf);
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);
571 len += _mali_kernel_core_dump_state(buf + len, size - len);
573 seq_commit(seq_file, len);
578 static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
580 return single_open(file, mali_seq_internal_state_show, NULL);
583 static const struct file_operations mali_seq_internal_state_fops = {
584 .owner = THIS_MODULE,
585 .open = mali_seq_internal_state_open,
588 .release = single_release,
590 #endif /* MALI_STATE_TRACKING */
592 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
593 static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
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);
602 static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
608 if (cnt >= sizeof(buf)) {
612 if (copy_from_user(&buf, ubuf, cnt)) {
618 ret = kstrtoul(buf, 10, &val);
624 u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */
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"));
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"));
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"));
646 MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit));
648 /* stop recording profiling data */
650 if (_MALI_OSK_ERR_OK != _mali_internal_profiling_stop(&count)) {
651 MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
655 MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count));
662 static const struct file_operations profiling_record_fops = {
663 .owner = THIS_MODULE,
664 .read = profiling_record_read,
665 .write = profiling_record_write,
668 static void *profiling_events_start(struct seq_file *s, loff_t *pos)
672 /* check if we have data avaiable */
673 if (MALI_TRUE != _mali_internal_profiling_have_recording()) {
677 spos = kmalloc(sizeof(loff_t), GFP_KERNEL);
686 static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos)
690 /* check if we have data avaiable */
691 if (MALI_TRUE != _mali_internal_profiling_have_recording()) {
695 /* check if the next entry actually is avaiable */
696 if (_mali_internal_profiling_get_count() <= (u32)(*spos + 1)) {
704 static void profiling_events_stop(struct seq_file *s, void *v)
709 static int profiling_events_show(struct seq_file *seq_file, void *v)
717 index = (u32) * spos;
719 /* Retrieve all events */
720 if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &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]);
728 static int profiling_events_show_human_readable(struct seq_file *seq_file, void *v)
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))
732 static u64 start_time = 0;
739 index = (u32) * spos;
741 /* Retrieve all events */
742 if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &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]);
746 start_time = timestamp;
749 seq_printf(seq_file, "[%06u] ", index);
751 switch (event_id & 0x0F000000) {
752 case MALI_PROFILING_EVENT_TYPE_SINGLE:
753 seq_printf(seq_file, "SINGLE | ");
755 case MALI_PROFILING_EVENT_TYPE_START:
756 seq_printf(seq_file, "START | ");
758 case MALI_PROFILING_EVENT_TYPE_STOP:
759 seq_printf(seq_file, "STOP | ");
761 case MALI_PROFILING_EVENT_TYPE_SUSPEND:
762 seq_printf(seq_file, "SUSPEND | ");
764 case MALI_PROFILING_EVENT_TYPE_RESUME:
765 seq_printf(seq_file, "RESUME | ");
768 seq_printf(seq_file, "0x%01X | ", (event_id & 0x0F000000) >> 24);
772 switch (event_id & 0x00FF0000) {
773 case MALI_PROFILING_EVENT_CHANNEL_SOFTWARE:
774 seq_printf(seq_file, "SW | ");
776 case MALI_PROFILING_EVENT_CHANNEL_GP0:
777 seq_printf(seq_file, "GP0 | ");
779 case MALI_PROFILING_EVENT_CHANNEL_PP0:
780 seq_printf(seq_file, "PP0 | ");
782 case MALI_PROFILING_EVENT_CHANNEL_PP1:
783 seq_printf(seq_file, "PP1 | ");
785 case MALI_PROFILING_EVENT_CHANNEL_PP2:
786 seq_printf(seq_file, "PP2 | ");
788 case MALI_PROFILING_EVENT_CHANNEL_PP3:
789 seq_printf(seq_file, "PP3 | ");
791 case MALI_PROFILING_EVENT_CHANNEL_PP4:
792 seq_printf(seq_file, "PP4 | ");
794 case MALI_PROFILING_EVENT_CHANNEL_PP5:
795 seq_printf(seq_file, "PP5 | ");
797 case MALI_PROFILING_EVENT_CHANNEL_PP6:
798 seq_printf(seq_file, "PP6 | ");
800 case MALI_PROFILING_EVENT_CHANNEL_PP7:
801 seq_printf(seq_file, "PP7 | ");
803 case MALI_PROFILING_EVENT_CHANNEL_GPU:
804 seq_printf(seq_file, "GPU | ");
807 seq_printf(seq_file, "0x%02X | ", (event_id & 0x00FF0000) >> 16);
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 | ");
817 case MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL:
818 seq_printf(seq_file, "VIRTUAL | ");
821 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
825 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
828 seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
831 seq_printf(seq_file, "T0 + 0x%016llX\n", timestamp - start_time);
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
846 static int profiling_events_open(struct inode *inode, struct file *file)
848 return seq_open(file, &profiling_events_seq_ops);
851 static const struct file_operations profiling_events_fops = {
852 .owner = THIS_MODULE,
853 .open = profiling_events_open,
856 .release = seq_release,
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
866 static int profiling_events_human_readable_open(struct inode *inode, struct file *file)
868 return seq_open(file, &profiling_events_human_readable_seq_ops);
871 static const struct file_operations profiling_events_human_readable_fops = {
872 .owner = THIS_MODULE,
873 .open = profiling_events_human_readable_open,
876 .release = seq_release,
881 static int memory_debugfs_show(struct seq_file *s, void *private_data)
883 seq_printf(s, " %-25s %-10s %-10s %-15s %-15s %-10s %-10s\n"\
884 "==============================================================================================================\n",
885 "Name (:bytes)", "pid", "mali_mem", "max_mali_mem",
886 "external_mem", "ump_mem", "dma_mem");
887 mali_session_memory_tracking(s);
891 static int memory_debugfs_open(struct inode *inode, struct file *file)
893 return single_open(file, memory_debugfs_show, inode->i_private);
896 static const struct file_operations memory_usage_fops = {
897 .owner = THIS_MODULE,
898 .open = memory_debugfs_open,
901 .release = single_release,
904 static ssize_t utilization_gp_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
908 u32 uval = _mali_ukk_utilization_gp_pp();
910 r = snprintf(buf, 64, "%u\n", uval);
911 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
914 static ssize_t utilization_gp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
918 u32 uval = _mali_ukk_utilization_gp();
920 r = snprintf(buf, 64, "%u\n", uval);
921 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
924 static ssize_t utilization_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
928 u32 uval = _mali_ukk_utilization_pp();
930 r = snprintf(buf, 64, "%u\n", uval);
931 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
935 static const struct file_operations utilization_gp_pp_fops = {
936 .owner = THIS_MODULE,
937 .read = utilization_gp_pp_read,
940 static const struct file_operations utilization_gp_fops = {
941 .owner = THIS_MODULE,
942 .read = utilization_gp_read,
945 static const struct file_operations utilization_pp_fops = {
946 .owner = THIS_MODULE,
947 .read = utilization_pp_read,
950 static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
954 _mali_uk_user_setting_t setting;
957 cnt = min(cnt, sizeof(buf) - 1);
958 if (copy_from_user(buf, ubuf, cnt)) {
963 ret = kstrtoul(buf, 10, &val);
969 setting = (_mali_uk_user_setting_t)(filp->private_data);
970 mali_set_user_setting(setting, val);
976 static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
981 _mali_uk_user_setting_t setting;
983 setting = (_mali_uk_user_setting_t)(filp->private_data);
984 value = mali_get_user_setting(setting);
986 r = snprintf(buf, 64, "%u\n", value);
987 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
990 static const struct file_operations user_settings_fops = {
991 .owner = THIS_MODULE,
992 .open = open_copy_private_data,
993 .read = user_settings_read,
994 .write = user_settings_write,
997 static int mali_sysfs_user_settings_register(void)
999 struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
1001 if (mali_user_settings_dir != NULL) {
1003 for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) {
1004 debugfs_create_file(_mali_uk_user_setting_descriptions[i],
1005 0600, mali_user_settings_dir, (void *)i,
1006 &user_settings_fops);
1013 static ssize_t pp_num_cores_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
1019 if (count >= sizeof(buffer)) {
1023 if (copy_from_user(&buffer[0], buf, count)) {
1026 buffer[count] = '\0';
1028 ret = kstrtoul(&buffer[0], 10, &val);
1033 ret = mali_executor_set_perf_level(val, MALI_TRUE); /* override even if core scaling is disabled */
1042 static ssize_t pp_num_cores_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1047 r = snprintf(buffer, 64, "%u\n", mali_executor_get_num_cores_enabled());
1049 return simple_read_from_buffer(buf, count, offp, buffer, r);
1052 static const struct file_operations pp_num_cores_enabled_fops = {
1053 .owner = THIS_MODULE,
1054 .write = pp_num_cores_enabled_write,
1055 .read = pp_num_cores_enabled_read,
1056 .llseek = default_llseek,
1059 static ssize_t pp_num_cores_total_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1064 r = snprintf(buffer, 64, "%u\n", mali_executor_get_num_cores_total());
1066 return simple_read_from_buffer(buf, count, offp, buffer, r);
1069 static const struct file_operations pp_num_cores_total_fops = {
1070 .owner = THIS_MODULE,
1071 .read = pp_num_cores_total_read,
1074 static ssize_t pp_core_scaling_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
1080 if (count >= sizeof(buffer)) {
1084 if (copy_from_user(&buffer[0], buf, count)) {
1087 buffer[count] = '\0';
1089 ret = kstrtoul(&buffer[0], 10, &val);
1096 mali_executor_core_scaling_enable();
1099 mali_executor_core_scaling_disable();
1110 static ssize_t pp_core_scaling_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1112 return simple_read_from_buffer(buf, count, offp, mali_executor_core_scaling_is_enabled() ? "1\n" : "0\n", 2);
1114 static const struct file_operations pp_core_scaling_enabled_fops = {
1115 .owner = THIS_MODULE,
1116 .write = pp_core_scaling_enabled_write,
1117 .read = pp_core_scaling_enabled_read,
1118 .llseek = default_llseek,
1121 static ssize_t version_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
1126 switch (mali_kernel_core_get_product_id()) {
1127 case _MALI_PRODUCT_ID_MALI200:
1128 r = snprintf(buffer, 64, "Mali-200\n");
1130 case _MALI_PRODUCT_ID_MALI300:
1131 r = snprintf(buffer, 64, "Mali-300\n");
1133 case _MALI_PRODUCT_ID_MALI400:
1134 r = snprintf(buffer, 64, "Mali-400 MP\n");
1136 case _MALI_PRODUCT_ID_MALI450:
1137 r = snprintf(buffer, 64, "Mali-450 MP\n");
1139 case _MALI_PRODUCT_ID_UNKNOWN:
1144 return simple_read_from_buffer(buf, count, offp, buffer, r);
1147 static const struct file_operations version_fops = {
1148 .owner = THIS_MODULE,
1149 .read = version_read,
1153 static int timeline_debugfs_show(struct seq_file *s, void *private_data)
1155 struct mali_session_data *session, *tmp;
1156 u32 session_seq = 1;
1158 seq_printf(s, "timeline system info: \n=================\n\n");
1160 mali_session_lock();
1161 MALI_SESSION_FOREACH(session, tmp, link) {
1162 seq_printf(s, "session %d <%p> start:\n", session_seq, session);
1163 mali_timeline_debug_print_system(session->timeline_system, s);
1164 seq_printf(s, "session %d end\n\n\n", session_seq++);
1166 mali_session_unlock();
1171 static int timeline_debugfs_open(struct inode *inode, struct file *file)
1173 return single_open(file, timeline_debugfs_show, inode->i_private);
1176 static const struct file_operations timeline_dump_fops = {
1177 .owner = THIS_MODULE,
1178 .open = timeline_debugfs_open,
1180 .llseek = seq_lseek,
1181 .release = single_release
1185 int mali_sysfs_register(const char *mali_dev_name)
1187 mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
1188 if (ERR_PTR(-ENODEV) == mali_debugfs_dir) {
1189 /* Debugfs not supported. */
1190 mali_debugfs_dir = NULL;
1192 if (NULL != mali_debugfs_dir) {
1193 /* Debugfs directory created successfully; create files now */
1194 struct dentry *mali_power_dir;
1195 struct dentry *mali_gp_dir;
1196 struct dentry *mali_pp_dir;
1197 struct dentry *mali_l2_dir;
1198 struct dentry *mali_profiling_dir;
1200 debugfs_create_file("version", 0400, mali_debugfs_dir, NULL, &version_fops);
1202 mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
1203 if (mali_power_dir != NULL) {
1204 debugfs_create_file("always_on", 0600, mali_power_dir, NULL, &power_always_on_fops);
1205 debugfs_create_file("power_events", 0200, mali_power_dir, NULL, &power_power_events_fops);
1208 mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
1209 if (mali_gp_dir != NULL) {
1213 num_groups = mali_group_get_glob_num_groups();
1214 for (i = 0; i < num_groups; i++) {
1215 struct mali_group *group = mali_group_get_glob_group(i);
1217 struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
1218 if (NULL != gp_core) {
1219 struct dentry *mali_gp_gpx_dir;
1220 mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
1221 if (NULL != mali_gp_gpx_dir) {
1222 debugfs_create_file("base_addr", 0400, mali_gp_gpx_dir, &gp_core->hw_core, &hw_core_base_addr_fops);
1223 debugfs_create_file("enabled", 0600, mali_gp_gpx_dir, group, &group_enabled_fops);
1225 break; /* no need to look for any other GP cores */
1231 mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
1232 if (mali_pp_dir != NULL) {
1236 debugfs_create_file("num_cores_total", 0400, mali_pp_dir, NULL, &pp_num_cores_total_fops);
1237 debugfs_create_file("num_cores_enabled", 0600, mali_pp_dir, NULL, &pp_num_cores_enabled_fops);
1238 debugfs_create_file("core_scaling_enabled", 0600, mali_pp_dir, NULL, &pp_core_scaling_enabled_fops);
1240 num_groups = mali_group_get_glob_num_groups();
1241 for (i = 0; i < num_groups; i++) {
1242 struct mali_group *group = mali_group_get_glob_group(i);
1244 struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
1245 if (NULL != pp_core) {
1247 struct dentry *mali_pp_ppx_dir;
1248 _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
1249 mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
1250 if (NULL != mali_pp_ppx_dir) {
1251 debugfs_create_file("base_addr", 0400, mali_pp_ppx_dir, &pp_core->hw_core, &hw_core_base_addr_fops);
1252 if (!mali_group_is_virtual(group)) {
1253 debugfs_create_file("enabled", 0600, mali_pp_ppx_dir, group, &group_enabled_fops);
1260 mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
1261 if (mali_l2_dir != NULL) {
1262 struct dentry *mali_l2_all_dir;
1264 struct mali_l2_cache_core *l2_cache;
1266 mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
1267 if (mali_l2_all_dir != NULL) {
1268 debugfs_create_file("counter_src0", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
1269 debugfs_create_file("counter_src1", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
1273 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1274 while (NULL != l2_cache) {
1276 struct dentry *mali_l2_l2x_dir;
1277 _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
1278 mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
1279 if (NULL != mali_l2_l2x_dir) {
1280 debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
1281 debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
1282 debugfs_create_file("counter_val0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_val0_fops);
1283 debugfs_create_file("counter_val1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_val1_fops);
1284 debugfs_create_file("base_addr", 0400, mali_l2_l2x_dir, &l2_cache->hw_core, &hw_core_base_addr_fops);
1289 l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1293 debugfs_create_file("gpu_memory", 0444, mali_debugfs_dir, NULL, &memory_usage_fops);
1295 debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops);
1296 debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops);
1297 debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops);
1299 mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
1300 if (mali_profiling_dir != NULL) {
1303 struct dentry *mali_profiling_gp_dir;
1304 struct dentry *mali_profiling_pp_dir;
1305 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1306 struct dentry *mali_profiling_proc_dir;
1309 * Create directory where we can set GP HW counters.
1311 mali_profiling_gp_dir = debugfs_create_dir("gp", mali_profiling_dir);
1312 if (mali_profiling_gp_dir != NULL) {
1313 debugfs_create_file("counter_src0", 0600, mali_profiling_gp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_GP(0), &profiling_counter_src_fops);
1314 debugfs_create_file("counter_src1", 0600, mali_profiling_gp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_GP(1), &profiling_counter_src_fops);
1318 * Create directory where we can set PP HW counters.
1319 * Possible override with specific HW counters for a particular sub job
1320 * (Disable core scaling before using the override!)
1322 mali_profiling_pp_dir = debugfs_create_dir("pp", mali_profiling_dir);
1323 if (mali_profiling_pp_dir != NULL) {
1324 debugfs_create_file("counter_src0", 0600, mali_profiling_pp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_PP(0), &profiling_counter_src_fops);
1325 debugfs_create_file("counter_src1", 0600, mali_profiling_pp_dir, (void *)PRIVATE_DATA_COUNTER_MAKE_PP(1), &profiling_counter_src_fops);
1328 max_sub_jobs = mali_executor_get_num_cores_total();
1329 for (i = 0; i < max_sub_jobs; i++) {
1331 struct dentry *mali_profiling_pp_x_dir;
1332 _mali_osk_snprintf(buf, sizeof(buf), "%u", i);
1333 mali_profiling_pp_x_dir = debugfs_create_dir(buf, mali_profiling_pp_dir);
1334 if (NULL != mali_profiling_pp_x_dir) {
1335 debugfs_create_file("counter_src0",
1336 0600, mali_profiling_pp_x_dir,
1337 (void *)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(0, i),
1338 &profiling_counter_src_fops);
1339 debugfs_create_file("counter_src1",
1340 0600, mali_profiling_pp_x_dir,
1341 (void *)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(1, i),
1342 &profiling_counter_src_fops);
1346 #if defined(CONFIG_MALI400_INTERNAL_PROFILING)
1347 mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir);
1348 if (mali_profiling_proc_dir != NULL) {
1349 struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir);
1350 if (mali_profiling_proc_default_dir != NULL) {
1351 debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void *)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
1354 debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
1355 debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
1356 debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops);
1360 #if MALI_STATE_TRACKING
1361 debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
1365 debugfs_create_file("timeline_dump", 0400, mali_debugfs_dir, NULL, &timeline_dump_fops);
1367 if (mali_sysfs_user_settings_register()) {
1368 /* Failed to create the debugfs entries for the user settings DB. */
1369 MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
1378 int mali_sysfs_unregister(void)
1380 if (NULL != mali_debugfs_dir) {
1381 debugfs_remove_recursive(mali_debugfs_dir);
1386 #else /* MALI_LICENSE_IS_GPL */
1388 /* Dummy implementations for non-GPL */
1390 int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1395 int mali_sysfs_unregister(void)
1400 #endif /* MALI_LICENSE_IS_GPL */