summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSidath Senanayake <sidaths@google.com>2020-08-28 16:36:11 +0100
committerSidath Senanayake <sidaths@google.com>2020-09-02 21:01:38 +0100
commit01278baa0e6506d197c44bf09d2032f24dd9a1e4 (patch)
treef043fa0881da5c5d0a1beae973427bc2217ae2b1
parent6512329057af12dd9d81e23f62d890bfca7b1849 (diff)
downloadgpu-01278baa0e6506d197c44bf09d2032f24dd9a1e4.tar.gz
mali_kbase: platform: Add QOS support
This change allows the GPU DVFS table to specify clock restrictions for INT, MIF and the CPU clusters to ensure consistent performance. These restrictions are set via Linux's PM QOS framework and rely on devfreq and cpufreq support. It also adds support for bus traffic shaping scenarios. Configuration for these features is read from the GPU's device tree node. Bug: 156057140 Bug: 158091247 Signed-off-by: Sidath Senanayake <sidaths@google.com> Change-Id: I13a92c147aa0b22df2dc1207ccffda7eacd1c8d0
-rw-r--r--mali_kbase/Kbuild4
-rw-r--r--mali_kbase/Makefile2
-rw-r--r--mali_kbase/platform/Kconfig1
-rw-r--r--mali_kbase/platform/pixel/Kbuild3
-rw-r--r--mali_kbase/platform/pixel/Kconfig28
-rw-r--r--mali_kbase/platform/pixel/mali_kbase_config_platform.h38
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_dvfs.c46
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_dvfs.h7
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_dvfs_qos.c179
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_sysfs.c31
10 files changed, 335 insertions, 4 deletions
diff --git a/mali_kbase/Kbuild b/mali_kbase/Kbuild
index 9ed314f..d85f71c 100644
--- a/mali_kbase/Kbuild
+++ b/mali_kbase/Kbuild
@@ -60,7 +60,9 @@ DEFINES = \
# Pixel integration defines
DEFINES += \
- -DCONFIG_MALI_MIDGARD_DVFS=y
+ -DCONFIG_MALI_MIDGARD_DVFS=y \
+ -DCONFIG_MALI_PIXEL_GPU_QOS=y \
+ -DCONFIG_MALI_PIXEL_GPU_BTS=y
ifeq ($(KBUILD_EXTMOD),)
# in-tree
diff --git a/mali_kbase/Makefile b/mali_kbase/Makefile
index 7034a1a..31ceb51 100644
--- a/mali_kbase/Makefile
+++ b/mali_kbase/Makefile
@@ -34,6 +34,8 @@ KBUILD_OPTIONS += CONFIG_MALI_DMA_BUF_LEGACY_COMPAT=y
# Pixel integration Kbuild options
KBUILD_OPTIONS += CONFIG_MALI_PLATFORM_NAME="pixel"
KBUILD_OPTIONS += CONFIG_MALI_MIDGARD_DVFS=y
+KBUILD_OPTIONS += CONFIG_MALI_PIXEL_GPU_QOS=y
+KBUILD_OPTIONS += CONFIG_MALI_PIXEL_GPU_QOS=y
KBUILD_OPTIONS += $(KBUILD_EXTRA) # Extra config if any
diff --git a/mali_kbase/platform/Kconfig b/mali_kbase/platform/Kconfig
index ef9fb96..f393ba8 100644
--- a/mali_kbase/platform/Kconfig
+++ b/mali_kbase/platform/Kconfig
@@ -28,3 +28,4 @@
# Where xxx is the platform name is the name set in MALI_PLATFORM_NAME
#
+source "drivers/gpu/arm/mali/platform/pixel/Kconfig"
diff --git a/mali_kbase/platform/pixel/Kbuild b/mali_kbase/platform/pixel/Kbuild
index d8040d0..866ce1b 100644
--- a/mali_kbase/platform/pixel/Kbuild
+++ b/mali_kbase/platform/pixel/Kbuild
@@ -27,3 +27,6 @@ mali_kbase-$(CONFIG_MALI_MIDGARD_DVFS) += \
$(MALI_PLATFORM_DIR)/pixel_gpu_dvfs.o \
$(MALI_PLATFORM_DIR)/pixel_gpu_dvfs_governor.o \
$(MALI_PLATFORM_DIR)/pixel_gpu_sysfs.o
+
+mali_kbase-$(CONFIG_MALI_PIXEL_GPU_QOS) += \
+ $(MALI_PLATFORM_DIR)/pixel_gpu_dvfs_qos.o
diff --git a/mali_kbase/platform/pixel/Kconfig b/mali_kbase/platform/pixel/Kconfig
new file mode 100644
index 0000000..5f9048a
--- /dev/null
+++ b/mali_kbase/platform/pixel/Kconfig
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0
+
+#
+# Mali Pixel integration configuration
+#
+# Copyright 2020 Google LLC.
+#
+
+config MALI_PIXEL_GPU_QOS
+ bool "Enable QOS requests for GPU"
+ depends on MALI_MIDGARD_DVFS && PM_DEVFREQ && CPU_FREQ
+ default y
+ help
+ Turns on quality of service (QOS) requests on MIF, INT
+ and the CPU clusters based on GPU utilization. Frequency
+ values, thresholds and hysteresis valus are specified for
+ each GPU OPP in the GPU device tree entry.
+
+config MALI_PIXEL_GPU_BTS
+ bool "Enable Bus Traffic Shaping for GPU"
+ depends on MALI_PIXEL_GPU_QOS && EXYNOS_BTS
+ default y
+ help
+ Enables the setting of Bus Traffic Shaping scenarios when
+ GPU utilization is at a specific level. Configuration for
+ this feature is specified on the GPU device tree entry and
+ allows for setting the BTS scenario to use, and the GPU OPP
+ at which it is triggered.
diff --git a/mali_kbase/platform/pixel/mali_kbase_config_platform.h b/mali_kbase/platform/pixel/mali_kbase_config_platform.h
index 617fffc..687ad1b 100644
--- a/mali_kbase/platform/pixel/mali_kbase_config_platform.h
+++ b/mali_kbase/platform/pixel/mali_kbase_config_platform.h
@@ -67,7 +67,11 @@ extern struct kbase_platform_funcs_conf platform_funcs;
#if IS_ENABLED(CONFIG_EXYNOS_PD)
#include <soc/google/exynos-pd.h>
#endif
-
+#ifdef CONFIG_MALI_MIDGARD_DVFS
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+#include <soc/google/exynos_pm_qos.h>
+#endif /* CONFIG_MALI_MIDGARD_DVFS */
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
/* Pixel integration includes */
#ifdef CONFIG_MALI_MIDGARD_DVFS
@@ -194,6 +198,18 @@ struct gpu_dvfs_opp {
* @dvfs.governor.curr: The currently enabled DVFS governor.
* @dvfs.governor.delay: Governor specific variable. The basic governor uses this to store the
* remaining ticks before a lower throughput level will be set.
+ *
+ * @dvfs.qos.enabled: Stores whether QOS requests have been set.
+ * @dvfs.qos.level_last: The level for which QOS requests were made. Negative if no QOS is set.
+ * @dvfs.qos.int_min: QOS request structure for setting minimum INT clock
+ * @dvfs.qos.mif_min: QOS request structure for setting minimum MIF clock
+ * @dvfs.qos.cpu0_min: QOS request structure for setting minimum CPU cluster 0 (little) clock
+ * @dvfs.qos.cpu1_min: QOS request structure for setting minimum CPU cluster 1 (medium) clock
+ * @dvfs.qos.cpu2_max: QOS request structure for setting maximum CPU cluster 2 (big) clock
+ *
+ * @dvfs.qos.bts.enabled: Stores whether Bus Traffic Shaping is currently enabled
+ * @dvfs.qos.bts.threshold: The DVFS level at which Bus Traffic Shaping will be enabled. Set via DT.
+ * @dvfs.qos.bts.scenario: The index of the Bus Traffic Shaping scenario to be used. Set via DT.
*/
struct pixel_context {
struct kbase_device *kbdev;
@@ -242,6 +258,26 @@ struct pixel_context {
enum gpu_dvfs_governor_type curr;
int delay;
} governor;
+
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+ struct {
+ bool enabled;
+ int level_last;
+ struct exynos_pm_qos_request int_min;
+ struct exynos_pm_qos_request mif_min;
+ struct exynos_pm_qos_request cpu0_min;
+ struct exynos_pm_qos_request cpu1_min;
+ struct exynos_pm_qos_request cpu2_max;
+
+#ifdef CONFIG_MALI_PIXEL_GPU_BTS
+ struct {
+ bool enabled;
+ int threshold;
+ unsigned int scenario;
+ } bts;
+#endif /* CONFIG_MALI_PIXEL_GPU_BTS */
+ } qos;
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
} dvfs;
#endif /* CONFIG_MALI_MIDGARD_DVFS */
};
diff --git a/mali_kbase/platform/pixel/pixel_gpu_dvfs.c b/mali_kbase/platform/pixel/pixel_gpu_dvfs.c
index 2799457..a54d6cc 100644
--- a/mali_kbase/platform/pixel/pixel_gpu_dvfs.c
+++ b/mali_kbase/platform/pixel/pixel_gpu_dvfs.c
@@ -169,6 +169,12 @@ static int gpu_dvfs_set_new_level(struct kbase_device *kbdev, int next_level)
lockdep_assert_held(&pc->dvfs.lock);
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+ /* If we are clocking up, update QOS frequencies before GPU frequencies */
+ if (next_level < pc->dvfs.level)
+ gpu_dvfs_qos_set(kbdev, next_level);
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
+
mutex_lock(&pc->pm.domain->access_lock);
gpu_dvfs_metrics_update(kbdev, next_level, true);
@@ -180,6 +186,12 @@ static int gpu_dvfs_set_new_level(struct kbase_device *kbdev, int next_level)
mutex_unlock(&pc->pm.domain->access_lock);
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+ /* If we are clocking down, update QOS frequencies after GPU frequencies */
+ if (next_level > pc->dvfs.level)
+ gpu_dvfs_qos_set(kbdev, next_level);
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
+
gpu_dvfs_trace_clock(kbdev, true);
return 0;
@@ -286,14 +298,27 @@ static void gpu_dvfs_worker(struct work_struct *data)
pc->dvfs.clock_down_delay = pc->dvfs.clock_down_hysteresis;
pc->dvfs.level_target = gpu_dvfs_governor_get_next_level(kbdev, util);
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+ /* If we have reset our QOS requests due to the GPU going idle, and haven't
+ * changed level, we need to request the QOS values for that level again
+ */
+ if (pc->dvfs.level_target == pc->dvfs.level && !pc->dvfs.qos.enabled)
+ gpu_dvfs_qos_set(kbdev, pc->dvfs.level_target);
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
+
if (pc->dvfs.level_target != pc->dvfs.level) {
GPU_LOG(LOG_DEBUG, kbdev, "util=%d results in level change (%d->%d)\n",
util, pc->dvfs.level, pc->dvfs.level_target);
gpu_dvfs_set_new_level(kbdev, pc->dvfs.level_target);
}
+
} else if (pc->dvfs.clock_down_delay) {
- if (--pc->dvfs.clock_down_delay == 0)
+ if (--pc->dvfs.clock_down_delay == 0) {
pc->dvfs.level_target = pc->dvfs.level_scaling_min;
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+ gpu_dvfs_qos_reset(kbdev);
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
+ }
}
mutex_unlock(&pc->dvfs.lock);
@@ -493,7 +518,7 @@ static int gpu_dvfs_get_initial_level(struct kbase_device *kbdev)
*
* @kbdev: The &struct kbase_device for the GPU.
*
- * This function calls initializers for the subsystems in DVFS: governors and metrics.
+ * This function calls initializers for the subsystems in DVFS: governors, metrics & qos.
*
* Return: On success, returns 0. -EINVAL on error.
*/
@@ -560,6 +585,15 @@ int gpu_dvfs_init(struct kbase_device *kbdev)
goto fail_metrics_init;
}
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+ /* Initialize QOS framework */
+ ret = gpu_dvfs_qos_init(kbdev);
+ if (ret) {
+ GPU_LOG(LOG_ERROR, kbdev, "DVFS QOS init failed\n");
+ goto fail_qos_init;
+ }
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
+
/* Initialize workqueue */
pc->dvfs.wq = create_singlethread_workqueue("gpu-dvfs");
INIT_WORK(&pc->dvfs.work, gpu_dvfs_worker);
@@ -567,6 +601,11 @@ int gpu_dvfs_init(struct kbase_device *kbdev)
/* Initialization was successful */
goto done;
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+fail_qos_init:
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
+ gpu_dvfs_metrics_term(kbdev);
+
fail_metrics_init:
gpu_dvfs_governor_term(kbdev);
@@ -585,6 +624,9 @@ void gpu_dvfs_term(struct kbase_device *kbdev)
destroy_workqueue(pc->dvfs.wq);
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+ gpu_dvfs_qos_term(kbdev);
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
gpu_dvfs_metrics_term(kbdev);
gpu_dvfs_governor_term(kbdev);
}
diff --git a/mali_kbase/platform/pixel/pixel_gpu_dvfs.h b/mali_kbase/platform/pixel/pixel_gpu_dvfs.h
index 64143db..d20bac1 100644
--- a/mali_kbase/platform/pixel/pixel_gpu_dvfs.h
+++ b/mali_kbase/platform/pixel/pixel_gpu_dvfs.h
@@ -70,4 +70,11 @@ void gpu_dvfs_governor_term(struct kbase_device *kbdev);
void gpu_dvfs_update_level_locks(struct kbase_device *kbdev);
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+void gpu_dvfs_qos_set(struct kbase_device *kbdev, int level);
+void gpu_dvfs_qos_reset(struct kbase_device *kbdev);
+int gpu_dvfs_qos_init(struct kbase_device *kbdev);
+void gpu_dvfs_qos_term(struct kbase_device *kbdev);
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
+
#endif /* _PIXEL_GPU_DVFS_H_ */
diff --git a/mali_kbase/platform/pixel/pixel_gpu_dvfs_qos.c b/mali_kbase/platform/pixel/pixel_gpu_dvfs_qos.c
new file mode 100644
index 0000000..f30940a
--- /dev/null
+++ b/mali_kbase/platform/pixel/pixel_gpu_dvfs_qos.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2020 Google LLC.
+ *
+ * Author: Sidath Senanayake <sidaths@google.com>
+ */
+
+/* Linux includes */
+#include <linux/of.h>
+
+/* SOC includes */
+#ifdef CONFIG_MALI_PIXEL_GPU_BTS
+#include <soc/google/bts.h>
+#endif
+
+/* Mali core includes */
+#include <mali_kbase.h>
+
+/* Pixel integration includes */
+#include "mali_kbase_config_platform.h"
+#include "pixel_gpu_control.h"
+#include "pixel_gpu_debug.h"
+#include "pixel_gpu_dvfs.h"
+
+
+/**
+ * gpu_dvfs_qos_set() - Issue QOS requests for a GPU DVFS level.
+ *
+ * @kbdev: The &struct kbase_device for the GPU.
+ * @level: The DVFS level from which to retrieve QOS values from.
+ *
+ * Context: Process context. Expects caller to hold the DVFS lock.
+ */
+void gpu_dvfs_qos_set(struct kbase_device *kbdev, int level)
+{
+ struct pixel_context *pc = kbdev->platform_context;
+ struct gpu_dvfs_opp opp = pc->dvfs.table[level];
+
+ lockdep_assert_held(&pc->dvfs.lock);
+
+ if (pc->dvfs.qos.level_last != level) {
+
+ GPU_LOG(LOG_DEBUG, kbdev,
+ "QOS int_min: %d\n"
+ "QOS mif_min: %d\n"
+ "QOS cpu0_min: %d\n"
+ "QOS cpu1_min: %d\n"
+ "QOS cpu2_max: %d\n",
+ opp.qos.int_min, opp.qos.mif_min, opp.qos.cpu0_min,
+ opp.qos.cpu1_min, opp.qos.cpu2_max);
+
+ exynos_pm_qos_update_request(&pc->dvfs.qos.int_min, opp.qos.int_min);
+ exynos_pm_qos_update_request(&pc->dvfs.qos.mif_min, opp.qos.mif_min);
+ exynos_pm_qos_update_request(&pc->dvfs.qos.cpu0_min, opp.qos.cpu0_min);
+ exynos_pm_qos_update_request(&pc->dvfs.qos.cpu1_min, opp.qos.cpu1_min);
+ exynos_pm_qos_update_request(&pc->dvfs.qos.cpu2_max, opp.qos.cpu2_max);
+
+#ifdef CONFIG_MALI_PIXEL_GPU_BTS
+ if (level <= pc->dvfs.qos.bts.threshold && !pc->dvfs.qos.bts.enabled) {
+ bts_add_scenario(pc->dvfs.qos.bts.scenario);
+ pc->dvfs.qos.bts.enabled = true;
+ } else if (level > pc->dvfs.qos.bts.threshold && pc->dvfs.qos.bts.enabled) {
+ bts_del_scenario(pc->dvfs.qos.bts.scenario);
+ pc->dvfs.qos.bts.enabled = false;
+ }
+#endif /* CONFIG_MALI_PIXEL_GPU_BTS */
+
+ pc->dvfs.qos.level_last = level;
+ pc->dvfs.qos.enabled = true;
+ }
+}
+
+/**
+ * gpu_dvfs_qos_reset() - Clears QOS requests.
+ *
+ * @kbdev: The &struct kbase_device for the GPU.
+ *
+ * Context: Process context. Expects caller to hold the DVFS lock.
+ */
+void gpu_dvfs_qos_reset(struct kbase_device *kbdev)
+{
+ struct pixel_context *pc = kbdev->platform_context;
+
+ lockdep_assert_held(&pc->dvfs.lock);
+
+ exynos_pm_qos_update_request(&pc->dvfs.qos.int_min, 0);
+ exynos_pm_qos_update_request(&pc->dvfs.qos.mif_min, 0);
+ exynos_pm_qos_update_request(&pc->dvfs.qos.cpu0_min, 0);
+ exynos_pm_qos_update_request(&pc->dvfs.qos.cpu1_min, 0);
+ exynos_pm_qos_update_request(&pc->dvfs.qos.cpu2_max, PM_QOS_CLUSTER2_FREQ_MAX_DEFAULT_VALUE);
+
+#ifdef CONFIG_MALI_PIXEL_GPU_BTS
+ if (pc->dvfs.qos.bts.enabled) {
+ bts_del_scenario(pc->dvfs.qos.bts.scenario);
+ pc->dvfs.qos.bts.enabled = false;
+ }
+#endif /* CONFIG_MALI_PIXEL_GPU_BTS */
+
+ pc->dvfs.qos.level_last = -1;
+ pc->dvfs.qos.enabled = false;
+}
+
+/**
+ * gpu_dvfs_qos_init() - Initializes the Pixel GPU DVFS QOS subsystem.
+ *
+ * @kbdev: The &struct kbase_device for the GPU.
+ *
+ * Return: On success, returns 0. -EINVAL on error.
+ */
+int gpu_dvfs_qos_init(struct kbase_device *kbdev)
+{
+ struct pixel_context *pc = kbdev->platform_context;
+ int ret;
+
+#ifdef CONFIG_MALI_PIXEL_GPU_BTS
+ struct device_node *np = kbdev->dev->of_node;
+ const char *bts_scenario_name;
+
+ pc->dvfs.qos.bts.enabled = false;
+
+ if (of_property_read_string(np, "gpu_dvfs_qos_bts_scenario", &bts_scenario_name)) {
+ GPU_LOG(LOG_ERROR, kbdev, "GPU QOS BTS scenario not specified in DT\n");
+ ret = -EINVAL;
+ goto done;
+ }
+
+ pc->dvfs.qos.bts.scenario = bts_get_scenindex(bts_scenario_name);
+ if (!pc->dvfs.qos.bts.scenario) {
+ GPU_LOG(LOG_ERROR, kbdev, "invalid GPU QOS BTS scenario specified in DT\n");
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (of_property_read_u32(np, "gpu_dvfs_qos_bts_level", &pc->dvfs.qos.bts.threshold)) {
+ GPU_LOG(LOG_ERROR, kbdev, "GPU QOS BTS threshold not specified in DT\n");
+ ret = -EINVAL;
+ goto done;
+ }
+#endif /* CONFIG_MALI_PIXEL_GPU_BTS */
+
+ exynos_pm_qos_add_request(&pc->dvfs.qos.int_min, PM_QOS_DEVICE_THROUGHPUT, 0);
+ exynos_pm_qos_add_request(&pc->dvfs.qos.mif_min, PM_QOS_BUS_THROUGHPUT, 0);
+ exynos_pm_qos_add_request(&pc->dvfs.qos.cpu0_min, PM_QOS_CLUSTER0_FREQ_MIN, 0);
+ exynos_pm_qos_add_request(&pc->dvfs.qos.cpu1_min, PM_QOS_CLUSTER1_FREQ_MIN, 0);
+ exynos_pm_qos_add_request(&pc->dvfs.qos.cpu2_max, PM_QOS_CLUSTER2_FREQ_MAX,
+ PM_QOS_CLUSTER2_FREQ_MAX_DEFAULT_VALUE);
+
+ pc->dvfs.qos.level_last = -1;
+ pc->dvfs.qos.enabled = false;
+
+ GPU_LOG(LOG_DEBUG, kbdev, "GPU QOS initialized\n");
+ ret = 0;
+
+done:
+ return ret;
+}
+
+/**
+ * gpu_dvfs_qos_term() - Terminates the Pixel GPU DVFS QOS subsystem.
+ *
+ * @kbdev: The &struct kbase_device for the GPU.
+ */
+void gpu_dvfs_qos_term(struct kbase_device *kbdev)
+{
+ struct pixel_context *pc = kbdev->platform_context;
+
+ exynos_pm_qos_remove_request(&pc->dvfs.qos.int_min);
+ exynos_pm_qos_remove_request(&pc->dvfs.qos.mif_min);
+ exynos_pm_qos_remove_request(&pc->dvfs.qos.cpu0_min);
+ exynos_pm_qos_remove_request(&pc->dvfs.qos.cpu1_min);
+ exynos_pm_qos_remove_request(&pc->dvfs.qos.cpu2_max);
+
+#ifdef CONFIG_MALI_PIXEL_GPU_BTS
+ if (pc->dvfs.qos.bts.enabled) {
+ bts_del_scenario(pc->dvfs.qos.bts.scenario);
+ pc->dvfs.qos.bts.enabled = false;
+ }
+#endif /* CONFIG_MALI_PIXEL_GPU_BTS */
+}
diff --git a/mali_kbase/platform/pixel/pixel_gpu_sysfs.c b/mali_kbase/platform/pixel/pixel_gpu_sysfs.c
index 2beb632..1b0a2b3 100644
--- a/mali_kbase/platform/pixel/pixel_gpu_sysfs.c
+++ b/mali_kbase/platform/pixel/pixel_gpu_sysfs.c
@@ -58,6 +58,37 @@ static ssize_t clock_info_show(struct device *dev, struct device_attribute *attr
pc->dvfs.table[pc->dvfs.level_target].clk0,
pc->dvfs.table[pc->dvfs.level_target].clk1);
+#ifdef CONFIG_MALI_PIXEL_GPU_QOS
+
+#ifdef CONFIG_MALI_PIXEL_GPU_BTS
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "GPU Bus Traffic Shaping :%s\n",
+ (pc->dvfs.qos.bts.enabled ? "on" : "off"));
+#endif /* CONFIG_MALI_PIXEL_GPU_BTS */
+
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "QOS status : %s\n"
+ " INT min clock : %d kHz\n"
+ " MIF min clock : %d kHz\n"
+ " CPU cluster 0 min clock : %d kHz\n"
+ " CPU cluster 1 min clock : %d kHz\n",
+
+ (pc->dvfs.qos.enabled ? "on" : "off"),
+ pc->dvfs.table[pc->dvfs.level_target].qos.int_min,
+ pc->dvfs.table[pc->dvfs.level_target].qos.mif_min,
+ pc->dvfs.table[pc->dvfs.level_target].qos.cpu0_min,
+ pc->dvfs.table[pc->dvfs.level_target].qos.cpu1_min);
+
+ if (pc->dvfs.table[pc->dvfs.level_target].qos.cpu2_max == CPU_FREQ_MAX)
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ " CPU cluster 2 max clock : (no limit)\n");
+ else
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ " CPU cluster 2 max clock : %d kHz\n",
+ pc->dvfs.table[pc->dvfs.level_target].qos.cpu2_max);
+
+#endif /* CONFIG_MALI_PIXEL_GPU_QOS */
+
return ret;
}