Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6e9fc177 authored by Karol Herbst's avatar Karol Herbst Committed by Ben Skeggs
Browse files

drm/nouveau/debugfs: add copy of sysfs pstate interface ported to debugfs

parent b126a200
Loading
Loading
Loading
Loading
+138 −2
Original line number Diff line number Diff line
@@ -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,