From dac44b421039df3dfd7704c2c652cb9ae2b3255f Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Sun, 19 Nov 2017 17:40:31 +0800 Subject: [PATCH] MALI Utgard: RK: add nodes to get gpu_utilisation Change-Id: I7ceebd882282fc08c8560fba5ec8978d18d5b819 Signed-off-by: Zhen Chen --- drivers/gpu/arm/mali400/mali/platform/rk/rk.c | 102 +++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c index 4db5212dab3e..103acdd5c319 100644 --- a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c +++ b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,8 @@ u32 mali_group_error; /*---------------------------------------------------------------------------*/ +#define DEFAULT_UTILISATION_PERIOD_IN_MS (100) + /* * rk_platform_context_of_mali_device. */ @@ -54,21 +57,116 @@ struct rk_context { struct device *dev; /* is the GPU powered on? */ bool is_powered; + /* debug only, the period in ms to count gpu_utilisation. */ + unsigned int utilisation_period; }; struct rk_context *s_rk_context; -/*-------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#ifdef CONFIG_MALI_DEVFREQ +static ssize_t utilisation_period_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rk_context *platform = s_rk_context; + ssize_t ret = 0; + + ret += snprintf(buf, PAGE_SIZE, "%u\n", platform->utilisation_period); + + return ret; +} + +static ssize_t utilisation_period_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct rk_context *platform = s_rk_context; + int ret = 0; + + ret = kstrtouint(buf, 0, &platform->utilisation_period); + if (ret) { + E("invalid input period : %s.", buf); + return ret; + } + D("set utilisation_period to '%d'.", platform->utilisation_period); + + return count; +} + +static ssize_t utilisation_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rk_context *platform = s_rk_context; + struct mali_device *mdev = dev_get_drvdata(dev); + ssize_t ret = 0; + unsigned long period_in_us = platform->utilisation_period * 1000; + unsigned long total_time; + unsigned long busy_time; + unsigned long utilisation; + + mali_pm_reset_dvfs_utilisation(mdev); + usleep_range(period_in_us, period_in_us + 100); + mali_pm_get_dvfs_utilisation(mdev, &total_time, &busy_time); + + /* 'devfreq_dev_profile' instance registered to devfreq + * also uses mali_pm_reset_dvfs_utilisation() + * and mali_pm_get_dvfs_utilisation(). + * So, it's better to disable GPU DVFS before reading this node. + */ + D("total_time : %lu, busy_time : %lu.", total_time, busy_time); + + utilisation = busy_time / (total_time / 100); + ret += snprintf(buf, PAGE_SIZE, "%lu\n", utilisation); + + return ret; +} + +static DEVICE_ATTR_RW(utilisation_period); +static DEVICE_ATTR_RO(utilisation); +#endif static int rk_context_create_sysfs_files(struct device *dev) { +#ifdef CONFIG_MALI_DEVFREQ + int ret; + + ret = device_create_file(dev, &dev_attr_utilisation_period); + if (ret) { + E("fail to create sysfs file 'utilisation_period'."); + goto out; + } + + ret = device_create_file(dev, &dev_attr_utilisation); + if (ret) { + E("fail to create sysfs file 'utilisation'."); + goto remove_utilisation_period; + } + return 0; + +remove_utilisation_period: + device_remove_file(dev, &dev_attr_utilisation_period); +out: + return ret; +#else + return 0; +#endif } static void rk_context_remove_sysfs_files(struct device *dev) { +#ifdef CONFIG_MALI_DEVFREQ + device_remove_file(dev, &dev_attr_utilisation_period); + device_remove_file(dev, &dev_attr_utilisation); +#endif } +/*---------------------------------------------------------------------------*/ + /* * Init rk_platform_context of mali_device. */ @@ -87,6 +185,8 @@ static int rk_context_init(struct platform_device *pdev) platform->dev = dev; platform->is_powered = false; + platform->utilisation_period = DEFAULT_UTILISATION_PERIOD_IN_MS; + ret = rk_context_create_sysfs_files(dev); if (ret) { E("fail to create sysfs files, ret = %d", ret);