[RFC,v2,08/09] ARM: cpu topology: Add debugfs interface for cpu_power

Message ID 1321274405-2494-1-git-send-email-vincent.guittot@linaro.org
State New
Headers show

Commit Message

Vincent Guittot Nov. 14, 2011, 12:40 p.m.
Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
---
 arch/arm/kernel/topology.c |  113 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 113 insertions(+), 0 deletions(-)

Patch

diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 945b980..053ce9c 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -25,6 +25,11 @@ 
 #include <linux/cpufreq.h>
 #endif
 
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>	/* for copy_from_user */
+#endif
+
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
@@ -474,3 +479,111 @@  void init_cpu_topology(void)
 	}
 	smp_wmb();
 }
+
+/*
+ * debugfs interface for scaling cpu power
+ */
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *topo_debugfs_root;
+
+static ssize_t dbg_write(struct file *file, const char __user *buf,
+						size_t size, loff_t *off)
+{
+	unsigned int *value = file->f_dentry->d_inode->i_private;
+	char cdata[128];
+	unsigned long tmp;
+	unsigned int cpu;
+
+	if (size < (sizeof(cdata)-1)) {
+		if (copy_from_user(cdata, buf, size))
+			return -EFAULT;
+		cdata[size] = 0;
+		if (!strict_strtoul(cdata, 10, &tmp)) {
+			*value = tmp;
+
+#ifdef CONFIG_CPU_FREQ
+			for_each_online_cpu(cpu)
+				set_power_scale(cpu, cpu_power[cpu].id);
+#endif
+		}
+		return size;
+	}
+	return -EINVAL;
+}
+
+static ssize_t dbg_read(struct file *file, char __user *buf,
+						size_t size, loff_t *off)
+{
+	unsigned int *value = file->f_dentry->d_inode->i_private;
+	char cdata[128];
+	unsigned int len;
+
+	len = sprintf(cdata, "%u\n", *value);
+	return simple_read_from_buffer(buf, size, off, cdata, len);
+}
+
+static const struct file_operations debugfs_fops = {
+	.read = dbg_read,
+	.write = dbg_write,
+};
+
+static struct dentry *topo_debugfs_register(unsigned int cpu,
+						struct dentry *parent)
+{
+	struct dentry *cpu_d, *d;
+	char cpu_name[16];
+
+	sprintf(cpu_name, "cpu%u", cpu);
+
+	cpu_d = debugfs_create_dir(cpu_name, parent);
+	if (!cpu_d)
+		return NULL;
+
+	d = debugfs_create_file("cpu_power", S_IRUGO  | S_IWUGO,
+				cpu_d, &per_cpu(cpu_scale, cpu), &debugfs_fops);
+	if (!d)
+		goto err_out;
+
+#ifdef CONFIG_CPU_FREQ
+	d = debugfs_create_file("scale", S_IRUGO | S_IWUGO,
+				cpu_d, &cpu_power[cpu].id, &debugfs_fops);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_file("freq", S_IRUGO,
+				cpu_d, &cpu_power[cpu].freq, &debugfs_fops);
+	if (!d)
+		goto err_out;
+#endif
+	return cpu_d;
+
+err_out:
+	debugfs_remove_recursive(cpu_d);
+	return NULL;
+}
+
+static int __init topo_debugfs_init(void)
+{
+	struct dentry *d;
+	unsigned int cpu;
+
+	d = debugfs_create_dir("cpu_topo", NULL);
+	if (!d)
+		return -ENOMEM;
+	topo_debugfs_root = d;
+
+	for_each_possible_cpu(cpu) {
+		d = topo_debugfs_register(cpu, topo_debugfs_root);
+		if (d == NULL)
+			goto err_out;
+	}
+	return 0;
+
+err_out:
+	debugfs_remove_recursive(topo_debugfs_root);
+	return -ENOMEM;
+}
+
+late_initcall(topo_debugfs_init);
+#endif