diff options
| author | Karol Herbst <nouveau@karolherbst.de> | 2015-07-30 11:53:31 +0200 | 
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2016-01-11 11:28:25 +1000 | 
| commit | 6e9fc177399f08446293fec7607913fdbc95e191 (patch) | |
| tree | e0b2e68d3333803d3f9185228b4736be3d670d6c | |
| parent | b126a200e9dbd90fbe2148ee572dd0c2508be81f (diff) | |
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.c | 140 | 
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, | 
