diff options
Diffstat (limited to 'drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c')
-rw-r--r-- | drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c | 977 |
1 files changed, 929 insertions, 48 deletions
diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c index 6dcf052..64853d7 100644 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2010 ARM Limited. All rights reserved. +/** + * Copyright (C) 2011-2012 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. @@ -14,9 +14,14 @@ * Implementation of some sysfs data exports */ +#include <linux/kernel.h> #include <linux/fs.h> #include <linux/device.h> +#include <linux/version.h> +#include <linux/module.h> +#include <linux/slab.h> #include "mali_kernel_license.h" +#include "mali_kernel_common.h" #include "mali_kernel_linux.h" #include "mali_ukk.h" @@ -25,13 +30,721 @@ #include <linux/seq_file.h> #include <linux/debugfs.h> #include <asm/uaccess.h> -#include <linux/slab.h> -#include "mali_kernel_subsystem.h" +#include <linux/module.h> #include "mali_kernel_sysfs.h" -#include "mali_kernel_profiling.h" +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +#include <linux/slab.h> +#include "mali_osk_profiling.h" +#endif +#include "mali_pm.h" +#include "mali_cluster.h" +#include "mali_group.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_l2_cache.h" +#include "mali_hw_core.h" +#include "mali_kernel_core.h" +#include "mali_user_settings_db.h" +#include "mali_device_pause_resume.h" + +#define POWER_BUFFER_SIZE 3 static struct dentry *mali_debugfs_dir = NULL; +typedef enum +{ + _MALI_DEVICE_SUSPEND, + _MALI_DEVICE_RESUME, + _MALI_DEVICE_DVFS_PAUSE, + _MALI_DEVICE_DVFS_RESUME, + _MALI_MAX_EVENTS +} _mali_device_debug_power_events; + +static const char* const mali_power_events[_MALI_MAX_EVENTS] = { + [_MALI_DEVICE_SUSPEND] = "suspend", + [_MALI_DEVICE_RESUME] = "resume", + [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause", + [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume", +}; + +static u32 virtual_power_status_register=0; +static char pwr_buf[POWER_BUFFER_SIZE]; + +static int open_copy_private_data(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data; + + if (0 == src_id) + { + val = mali_gp_core_get_counter_src0(gp_core); + } + else + { + val = mali_gp_core_get_counter_src1(gp_core); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, gpos, buf, r); +} + +static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data; + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val)) + { + return 0; + } + } + + *gpos += cnt; + return cnt; +} + +static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 ci; + struct mali_cluster *cluster; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + ci = 0; + cluster = mali_cluster_get_global_cluster(ci); + while (NULL != cluster) + { + u32 gi = 0; + struct mali_group *group = mali_cluster_get_group(cluster, gi); + while (NULL != group) + { + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val)) + { + return 0; + } + } + } + + /* try next group */ + gi++; + group = mali_cluster_get_group(cluster, gi); + } + + /* try next cluster */ + ci++; + cluster = mali_cluster_get_global_cluster(ci); + } + + *gpos += cnt; + return cnt; +} + +static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1); +} + +static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1); +} + +static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0); +} + +static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos) +{ + return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1); +} + +static const struct file_operations gp_gpx_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = gp_gpx_counter_src0_read, + .write = gp_gpx_counter_src0_write, +}; + +static const struct file_operations gp_gpx_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = gp_gpx_counter_src1_read, + .write = gp_gpx_counter_src1_write, +}; + +static const struct file_operations gp_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = gp_all_counter_src0_write, +}; + +static const struct file_operations gp_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = gp_all_counter_src1_write, +}; + +static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data; + + if (0 == src_id) + { + val = mali_pp_core_get_counter_src0(pp_core); + } + else + { + val = mali_pp_core_get_counter_src1(pp_core); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data; + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val)) + { + return 0; + } + } + + *ppos += cnt; + return cnt; +} + +static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 ci; + struct mali_cluster *cluster; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + ci = 0; + cluster = mali_cluster_get_global_cluster(ci); + while (NULL != cluster) + { + u32 gi = 0; + struct mali_group *group = mali_cluster_get_group(cluster, gi); + while (NULL != group) + { + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val)) + { + return 0; + } + } + } + + /* try next group */ + gi++; + group = mali_cluster_get_group(cluster, gi); + } + + /* try next cluster */ + ci++; + cluster = mali_cluster_get_global_cluster(ci); + } + + *ppos += cnt; + return cnt; +} + +static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static const struct file_operations pp_ppx_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = pp_ppx_counter_src0_read, + .write = pp_ppx_counter_src0_write, +}; + +static const struct file_operations pp_ppx_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = pp_ppx_counter_src1_read, + .write = pp_ppx_counter_src1_write, +}; + +static const struct file_operations pp_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = pp_all_counter_src0_write, +}; + +static const struct file_operations pp_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = pp_all_counter_src1_write, +}; + + + + + + +static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + int r; + u32 val; + struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data; + + if (0 == src_id) + { + val = mali_l2_cache_core_get_counter_src0(l2_core); + } + else + { + val = mali_l2_cache_core_get_counter_src1(l2_core); + } + + if (MALI_HW_CORE_NO_COUNTER == val) + { + r = sprintf(buf, "-1\n"); + } + else + { + r = sprintf(buf, "%u\n", val); + } + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data; + char buf[64]; + long val; + int ret; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + if (0 == src_id) + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val)) + { + return 0; + } + } + + *ppos += cnt; + return cnt; +} + +static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) +{ + char buf[64]; + long val; + int ret; + u32 l2_id; + struct mali_l2_cache_core *l2_cache; + + if (cnt >= sizeof(buf)) + { + return -EINVAL; + } + + if (copy_from_user(&buf, ubuf, cnt)) + { + return -EFAULT; + } + + buf[cnt] = 0; + + ret = strict_strtol(buf, 10, &val); + if (ret < 0) + { + return ret; + } + + if (val < 0) + { + /* any negative input will disable counter */ + val = MALI_HW_CORE_NO_COUNTER; + } + + l2_id = 0; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + while (NULL != l2_cache) + { + if (0 == src_id) + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val)) + { + return 0; + } + } + else + { + if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val)) + { + return 0; + } + } + + /* try next L2 */ + l2_id++; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + } + + *ppos += cnt; + return cnt; +} + +static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0); +} + +static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1); +} + +static const struct file_operations l2_l2x_counter_src0_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = l2_l2x_counter_src0_read, + .write = l2_l2x_counter_src0_write, +}; + +static const struct file_operations l2_l2x_counter_src1_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = l2_l2x_counter_src1_read, + .write = l2_l2x_counter_src1_write, +}; + +static const struct file_operations l2_all_counter_src0_fops = { + .owner = THIS_MODULE, + .write = l2_all_counter_src0_write, +}; + +static const struct file_operations l2_all_counter_src1_fops = { + .owner = THIS_MODULE, + .write = l2_all_counter_src1_write, +}; + +static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + + memset(pwr_buf,0,POWER_BUFFER_SIZE); + virtual_power_status_register = 0; + if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND]))) + { + mali_pm_os_suspend(); + /* @@@@ assuming currently suspend is successful later on to tune as per previous*/ + virtual_power_status_register =1; + + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME]))) + { + mali_pm_os_resume(); + + /* @@@@ assuming currently resume is successful later on to tune as per previous */ + virtual_power_status_register = 1; + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE]))) + { + mali_bool power_on; + mali_dev_pause(&power_on); + if (!power_on) + { + virtual_power_status_register = 2; + mali_dev_resume(); + } + else + { + /* @@@@ assuming currently resume is successful later on to tune as per previous */ + virtual_power_status_register =1; + } + } + else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME]))) + { + mali_dev_resume(); + /* @@@@ assuming currently resume is successful later on to tune as per previous */ + virtual_power_status_register = 1; + + } + *ppos += cnt; + sprintf(pwr_buf, "%d",virtual_power_status_register); + return cnt; +} + +static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE); +} + +static loff_t power_events_seek(struct file *file, loff_t offset, int orig) +{ + file->f_pos = offset; + return 0; +} + +static const struct file_operations power_events_fops = { + .owner = THIS_MODULE, + .read = power_events_read, + .write = power_events_write, + .llseek = power_events_seek, +}; + + #if MALI_STATE_TRACKING static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v) { @@ -72,13 +785,13 @@ static const struct file_operations mali_seq_internal_state_fops = { #endif /* MALI_STATE_TRACKING */ -#if MALI_TIMELINE_PROFILING_ENABLED +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { char buf[64]; int r; - r = sprintf(buf, "%u\n", _mali_profiling_is_recording() ? 1 : 0); + r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0); return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } @@ -111,16 +824,16 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */ /* check if we are already recording */ - if (MALI_TRUE == _mali_profiling_is_recording()) + if (MALI_TRUE == _mali_osk_profiling_is_recording()) { MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n")); return -EFAULT; } /* check if we need to clear out an old recording first */ - if (MALI_TRUE == _mali_profiling_have_recording()) + if (MALI_TRUE == _mali_osk_profiling_have_recording()) { - if (_MALI_OSK_ERR_OK != _mali_profiling_clear()) + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear()) { MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n")); return -EFAULT; @@ -128,7 +841,7 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf } /* start recording profiling data */ - if (_MALI_OSK_ERR_OK != _mali_profiling_start(&limit)) + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) { MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n")); return -EFAULT; @@ -140,7 +853,7 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf { /* stop recording profiling data */ u32 count = 0; - if (_MALI_OSK_ERR_OK != _mali_profiling_stop(&count)) + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count)) { MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n")); return -EFAULT; @@ -164,7 +877,7 @@ static void *profiling_events_start(struct seq_file *s, loff_t *pos) loff_t *spos; /* check if we have data avaiable */ - if (MALI_TRUE != _mali_profiling_have_recording()) + if (MALI_TRUE != _mali_osk_profiling_have_recording()) { return NULL; } @@ -184,13 +897,13 @@ static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos) loff_t *spos = v; /* check if we have data avaiable */ - if (MALI_TRUE != _mali_profiling_have_recording()) + if (MALI_TRUE != _mali_osk_profiling_have_recording()) { return NULL; } /* check if the next entry actually is avaiable */ - if (_mali_profiling_get_count() <= (u32)(*spos + 1)) + if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1)) { return NULL; } @@ -215,7 +928,7 @@ static int profiling_events_show(struct seq_file *seq_file, void *v) index = (u32)*spos; /* Retrieve all events */ - if (_MALI_OSK_ERR_OK == _mali_profiling_get_event(index, ×tamp, &event_id, data)) + if (_MALI_OSK_ERR_OK == _mali_osk_profiling_get_event(index, ×tamp, &event_id, data)) { 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]); return 0; @@ -243,68 +956,89 @@ static const struct file_operations profiling_events_fops = { .llseek = seq_lseek, .release = seq_release, }; +#endif -static ssize_t profiling_proc_default_enable_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { char buf[64]; - int r; + size_t r; + u32 mem = _mali_ukk_report_memory_usage(); - r = sprintf(buf, "%u\n", _mali_profiling_get_default_enable_state() ? 1 : 0); + r = snprintf(buf, 64, "%u\n", mem); return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } -static ssize_t profiling_proc_default_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +static const struct file_operations memory_usage_fops = { + .owner = THIS_MODULE, + .read = memory_used_read, +}; + + +static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { - char buf[64]; unsigned long val; int ret; + _mali_uk_user_setting_t setting; + char buf[32]; - if (cnt >= sizeof(buf)) - { - return -EINVAL; - } - - if (copy_from_user(&buf, ubuf, cnt)) + cnt = min(cnt, sizeof(buf) - 1); + if (copy_from_user(buf, ubuf, cnt)) { return -EFAULT; } - - buf[cnt] = 0; + buf[cnt] = '\0'; ret = strict_strtoul(buf, 10, &val); - if (ret < 0) + if (0 != ret) { return ret; } - _mali_profiling_set_default_enable_state(val != 0 ? MALI_TRUE : MALI_FALSE); + /* Update setting */ + setting = (_mali_uk_user_setting_t)(filp->private_data); + mali_set_user_setting(setting, val); *ppos += cnt; return cnt; } -static const struct file_operations profiling_proc_default_enable_fops = { - .owner = THIS_MODULE, - .read = profiling_proc_default_enable_read, - .write = profiling_proc_default_enable_write, -}; -#endif - -static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { char buf[64]; size_t r; - u32 mem = _mali_ukk_report_memory_usage(); + u32 value; + _mali_uk_user_setting_t setting; - r = snprintf(buf, 64, "%u\n", mem); + setting = (_mali_uk_user_setting_t)(filp->private_data); + value = mali_get_user_setting(setting); + + r = snprintf(buf, 64, "%u\n", value); return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } -static const struct file_operations memory_usage_fops = { +static const struct file_operations user_settings_fops = { .owner = THIS_MODULE, - .read = memory_used_read, + .open = open_copy_private_data, + .read = user_settings_read, + .write = user_settings_write, }; +static int mali_sysfs_user_settings_register(void) +{ + struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir); + + if (mali_user_settings_dir != NULL) + { + int i; + for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) + { + debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops); + } + } + + return 0; +} + int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) { int err = 0; @@ -334,8 +1068,151 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev if(NULL != mali_debugfs_dir) { /* Debugfs directory created successfully; create files now */ -#if MALI_TIMELINE_PROFILING_ENABLED - struct dentry *mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir); + struct dentry *mali_power_dir; + struct dentry *mali_gp_dir; + struct dentry *mali_pp_dir; + struct dentry *mali_l2_dir; +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + struct dentry *mali_profiling_dir; +#endif + + mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir); + if (mali_power_dir != NULL) + { + debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_events_fops); + } + + mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir); + if (mali_gp_dir != NULL) + { + struct dentry *mali_gp_all_dir; + u32 ci; + struct mali_cluster *cluster; + + mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir); + if (mali_gp_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops); + } + + ci = 0; + cluster = mali_cluster_get_global_cluster(ci); + while (NULL != cluster) + { + u32 gi = 0; + struct mali_group *group = mali_cluster_get_group(cluster, gi); + while (NULL != group) + { + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + struct dentry *mali_gp_gpx_dir; + mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir); + if (NULL != mali_gp_gpx_dir) + { + debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops); + } + break; /* no need to look for any other GP cores */ + } + + /* try next group */ + gi++; + group = mali_cluster_get_group(cluster, gi); + } + + /* try next cluster */ + ci++; + cluster = mali_cluster_get_global_cluster(ci); + } + } + + mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir); + if (mali_pp_dir != NULL) + { + struct dentry *mali_pp_all_dir; + u32 ci; + struct mali_cluster *cluster; + + mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir); + if (mali_pp_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops); + } + + ci = 0; + cluster = mali_cluster_get_global_cluster(ci); + while (NULL != cluster) + { + u32 gi = 0; + struct mali_group *group = mali_cluster_get_group(cluster, gi); + while (NULL != group) + { + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) + { + char buf[16]; + struct dentry *mali_pp_ppx_dir; + _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core)); + mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir); + if (NULL != mali_pp_ppx_dir) + { + debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops); + } + } + + /* try next group */ + gi++; + group = mali_cluster_get_group(cluster, gi); + } + + /* try next cluster */ + ci++; + cluster = mali_cluster_get_global_cluster(ci); + } + } + + mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir); + if (mali_l2_dir != NULL) + { + struct dentry *mali_l2_all_dir; + u32 l2_id; + struct mali_l2_cache_core *l2_cache; + + mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir); + if (mali_l2_all_dir != NULL) + { + debugfs_create_file("counter_src0", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops); + } + + l2_id = 0; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + while (NULL != l2_cache) + { + char buf[16]; + struct dentry *mali_l2_l2x_dir; + _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id); + mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir); + if (NULL != mali_l2_l2x_dir) + { + debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops); + } + + /* try next L2 */ + l2_id++; + l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id); + } + } + + debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops); + +#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir); if (mali_profiling_dir != NULL) { struct dentry *mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir); @@ -344,7 +1221,7 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir); if (mali_profiling_proc_default_dir != NULL) { - debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, NULL, &profiling_proc_default_enable_fops); + debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops); } } debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops); @@ -356,7 +1233,11 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops); #endif - debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops); + if (mali_sysfs_user_settings_register()) + { + /* Failed to create the debugfs entries for the user settings DB. */ + MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n")); + } } } @@ -385,7 +1266,7 @@ int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_d #else -/* Dummy implementations for when the sysfs API isn't available. */ +/* Dummy implementations for non-GPL */ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) { |