summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarol Herbst <nouveau@karolherbst.de>2015-07-30 12:53:31 +0300
committerBen Skeggs <bskeggs@redhat.com>2016-01-11 04:28:25 +0300
commit6e9fc177399f08446293fec7607913fdbc95e191 (patch)
treee0b2e68d3333803d3f9185228b4736be3d670d6c
parentb126a200e9dbd90fbe2148ee572dd0c2508be81f (diff)
downloadlinux-6e9fc177399f08446293fec7607913fdbc95e191.tar.xz
drm/nouveau/debugfs: add copy of sysfs pstate interface ported to debugfs
Signed-off-by: Karol Herbst <nouveau@karolherbst.de> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_debugfs.c140
1 files changed, 138 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
index fd4140be5472..3d0dc199b253 100644
--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -30,6 +30,7 @@
#include <linux/debugfs.h>
#include <nvif/class.h>
+#include <nvif/if0001.h>
#include "nouveau_debugfs.h"
#include "nouveau_drm.h"
@@ -45,6 +46,140 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
return 0;
}
+static int
+nouveau_debugfs_pstate_get(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct nouveau_debugfs *debugfs = nouveau_debugfs(node->minor->dev);
+ struct nvif_object *ctrl = &debugfs->ctrl;
+ struct nvif_control_pstate_info_v0 info = {};
+ int ret, i;
+
+ if (!debugfs)
+ return -ENODEV;
+
+ ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_INFO, &info, sizeof(info));
+ if (ret)
+ return ret;
+
+ for (i = 0; i < info.count + 1; i++) {
+ const s32 state = i < info.count ? i :
+ NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT;
+ struct nvif_control_pstate_attr_v0 attr = {
+ .state = state,
+ .index = 0,
+ };
+
+ ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR,
+ &attr, sizeof(attr));
+ if (ret)
+ return ret;
+
+ if (i < info.count)
+ seq_printf(m, "%02x:", attr.state);
+ else
+ seq_printf(m, "%s:", info.pwrsrc == 0 ? "DC" :
+ info.pwrsrc == 1 ? "AC" : "--");
+
+ attr.index = 0;
+ do {
+ attr.state = state;
+ ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR,
+ &attr, sizeof(attr));
+ if (ret)
+ return ret;
+
+ seq_printf(m, " %s %d", attr.name, attr.min);
+ if (attr.min != attr.max)
+ seq_printf(m, "-%d", attr.max);
+ seq_printf(m, " %s", attr.unit);
+ } while (attr.index);
+
+ if (state >= 0) {
+ if (info.ustate_ac == state)
+ seq_printf(m, " AC");
+ if (info.ustate_dc == state)
+ seq_printf(m, " DC");
+ if (info.pstate == state)
+ seq_printf(m, " *");
+ } else {
+ if (info.ustate_ac < -1)
+ seq_printf(m, " AC");
+ if (info.ustate_dc < -1)
+ seq_printf(m, " DC");
+ }
+
+ seq_printf(m, "\n");
+ }
+
+ return 0;
+}
+
+static ssize_t
+nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ struct seq_file *m = file->private_data;
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct nouveau_debugfs *debugfs = nouveau_debugfs(node->minor->dev);
+ struct nvif_object *ctrl = &debugfs->ctrl;
+ struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };
+ char buf[32] = {}, *tmp, *cur = buf;
+ long value, ret;
+
+ if (!debugfs)
+ return -ENODEV;
+
+ if (len >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(buf, ubuf, len))
+ return -EFAULT;
+
+ if ((tmp = strchr(buf, '\n')))
+ *tmp = '\0';
+
+ if (!strncasecmp(cur, "dc:", 3)) {
+ args.pwrsrc = 0;
+ cur += 3;
+ } else
+ if (!strncasecmp(cur, "ac:", 3)) {
+ args.pwrsrc = 1;
+ cur += 3;
+ }
+
+ if (!strcasecmp(cur, "none"))
+ args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN;
+ else
+ if (!strcasecmp(cur, "auto"))
+ args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON;
+ else {
+ ret = kstrtol(cur, 16, &value);
+ if (ret)
+ return ret;
+ args.ustate = value;
+ }
+
+ ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args));
+ if (ret < 0)
+ return ret;
+
+ return len;
+}
+
+static int
+nouveau_debugfs_pstate_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, nouveau_debugfs_pstate_get, inode->i_private);
+}
+
+static const struct file_operations nouveau_pstate_fops = {
+ .owner = THIS_MODULE,
+ .open = nouveau_debugfs_pstate_open,
+ .read = seq_read,
+ .write = nouveau_debugfs_pstate_set,
+};
+
static struct drm_info_list nouveau_debugfs_list[] = {
{ "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
};
@@ -53,8 +188,9 @@ static struct drm_info_list nouveau_debugfs_list[] = {
static const struct nouveau_debugfs_files {
const char *name;
const struct file_operations *fops;
-} nouveau_debugfs_files[] = {};
-
+} nouveau_debugfs_files[] = {
+ {"pstate", &nouveau_pstate_fops},
+};
static int
nouveau_debugfs_create_file(struct drm_minor *minor,