brintos

brintos / linux-shallow public Read only

0
0
Text · 8.0 KiB · e83db05 Raw
316 lines · c
1/*2 * Copyright (C) 2009 Red Hat <bskeggs@redhat.com>3 *4 * Permission is hereby granted, free of charge, to any person obtaining5 * a copy of this software and associated documentation files (the6 * "Software"), to deal in the Software without restriction, including7 * without limitation the rights to use, copy, modify, merge, publish,8 * distribute, sublicense, and/or sell copies of the Software, and to9 * permit persons to whom the Software is furnished to do so, subject to10 * the following conditions:11 *12 * The above copyright notice and this permission notice (including the13 * next paragraph) shall be included in all copies or substantial14 * portions of the Software.15 *16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.19 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.23 *24 */25 26/*27 * Authors:28 *  Ben Skeggs <bskeggs@redhat.com>29 */30 31#include <linux/debugfs.h>32#include <nvif/class.h>33#include <nvif/if0001.h>34#include "nouveau_debugfs.h"35#include "nouveau_drv.h"36 37static int38nouveau_debugfs_vbios_image(struct seq_file *m, void *data)39{40	struct drm_info_node *node = (struct drm_info_node *) m->private;41	struct nouveau_drm *drm = nouveau_drm(node->minor->dev);42	int i;43 44	for (i = 0; i < drm->vbios.length; i++)45		seq_printf(m, "%c", drm->vbios.data[i]);46	return 0;47}48 49static int50nouveau_debugfs_strap_peek(struct seq_file *m, void *data)51{52	struct drm_info_node *node = m->private;53	struct nouveau_drm *drm = nouveau_drm(node->minor->dev);54	int ret;55 56	ret = pm_runtime_get_sync(drm->dev->dev);57	if (ret < 0 && ret != -EACCES) {58		pm_runtime_put_autosuspend(drm->dev->dev);59		return ret;60	}61 62	seq_printf(m, "0x%08x\n",63		   nvif_rd32(&drm->client.device.object, 0x101000));64 65	pm_runtime_mark_last_busy(drm->dev->dev);66	pm_runtime_put_autosuspend(drm->dev->dev);67 68	return 0;69}70 71static int72nouveau_debugfs_pstate_get(struct seq_file *m, void *data)73{74	struct drm_device *drm = m->private;75	struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);76	struct nvif_object *ctrl;77	struct nvif_control_pstate_info_v0 info = {};78	int ret, i;79 80	if (!debugfs)81		return -ENODEV;82 83	ctrl = &debugfs->ctrl;84	ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_INFO, &info, sizeof(info));85	if (ret)86		return ret;87 88	for (i = 0; i < info.count + 1; i++) {89		const s32 state = i < info.count ? i :90			NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT;91		struct nvif_control_pstate_attr_v0 attr = {92			.state = state,93			.index = 0,94		};95 96		ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR,97				&attr, sizeof(attr));98		if (ret)99			return ret;100 101		if (i < info.count)102			seq_printf(m, "%02x:", attr.state);103		else104			seq_printf(m, "%s:", info.pwrsrc == 0 ? "DC" :105					     info.pwrsrc == 1 ? "AC" : "--");106 107		attr.index = 0;108		do {109			attr.state = state;110			ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR,111					&attr, sizeof(attr));112			if (ret)113				return ret;114 115			seq_printf(m, " %s %d", attr.name, attr.min);116			if (attr.min != attr.max)117				seq_printf(m, "-%d", attr.max);118			seq_printf(m, " %s", attr.unit);119		} while (attr.index);120 121		if (state >= 0) {122			if (info.ustate_ac == state)123				seq_puts(m, " AC");124			if (info.ustate_dc == state)125				seq_puts(m, " DC");126			if (info.pstate == state)127				seq_puts(m, " *");128		} else {129			if (info.ustate_ac < -1)130				seq_puts(m, " AC");131			if (info.ustate_dc < -1)132				seq_puts(m, " DC");133		}134 135		seq_putc(m, '\n');136	}137 138	return 0;139}140 141static ssize_t142nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,143			   size_t len, loff_t *offp)144{145	struct seq_file *m = file->private_data;146	struct drm_device *drm = m->private;147	struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);148	struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };149	char buf[32] = {}, *tmp, *cur = buf;150	long value, ret;151 152	if (!debugfs)153		return -ENODEV;154 155	if (len >= sizeof(buf))156		return -EINVAL;157 158	if (copy_from_user(buf, ubuf, len))159		return -EFAULT;160 161	if ((tmp = strchr(buf, '\n')))162		*tmp = '\0';163 164	if (!strncasecmp(cur, "dc:", 3)) {165		args.pwrsrc = 0;166		cur += 3;167	} else168	if (!strncasecmp(cur, "ac:", 3)) {169		args.pwrsrc = 1;170		cur += 3;171	}172 173	if (!strcasecmp(cur, "none"))174		args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN;175	else176	if (!strcasecmp(cur, "auto"))177		args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON;178	else {179		ret = kstrtol(cur, 16, &value);180		if (ret)181			return ret;182		args.ustate = value;183	}184 185	ret = pm_runtime_get_sync(drm->dev);186	if (ret < 0 && ret != -EACCES) {187		pm_runtime_put_autosuspend(drm->dev);188		return ret;189	}190 191	ret = nvif_mthd(&debugfs->ctrl, NVIF_CONTROL_PSTATE_USER,192			&args, sizeof(args));193	pm_runtime_put_autosuspend(drm->dev);194	if (ret < 0)195		return ret;196 197	return len;198}199 200static int201nouveau_debugfs_pstate_open(struct inode *inode, struct file *file)202{203	return single_open(file, nouveau_debugfs_pstate_get, inode->i_private);204}205 206static void207nouveau_debugfs_gpuva_regions(struct seq_file *m, struct nouveau_uvmm *uvmm)208{209	MA_STATE(mas, &uvmm->region_mt, 0, 0);210	struct nouveau_uvma_region *reg;211 212	seq_puts  (m, " VA regions  | start              | range              | end                \n");213	seq_puts  (m, "----------------------------------------------------------------------------\n");214	mas_for_each(&mas, reg, ULONG_MAX)215		seq_printf(m, "             | 0x%016llx | 0x%016llx | 0x%016llx\n",216			   reg->va.addr, reg->va.range, reg->va.addr + reg->va.range);217}218 219static int220nouveau_debugfs_gpuva(struct seq_file *m, void *data)221{222	struct drm_info_node *node = (struct drm_info_node *) m->private;223	struct nouveau_drm *drm = nouveau_drm(node->minor->dev);224	struct nouveau_cli *cli;225 226	mutex_lock(&drm->clients_lock);227	list_for_each_entry(cli, &drm->clients, head) {228		struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli);229 230		if (!uvmm)231			continue;232 233		nouveau_uvmm_lock(uvmm);234		drm_debugfs_gpuva_info(m, &uvmm->base);235		seq_puts(m, "\n");236		nouveau_debugfs_gpuva_regions(m, uvmm);237		nouveau_uvmm_unlock(uvmm);238	}239	mutex_unlock(&drm->clients_lock);240 241	return 0;242}243 244static const struct file_operations nouveau_pstate_fops = {245	.owner = THIS_MODULE,246	.open = nouveau_debugfs_pstate_open,247	.read = seq_read,248	.write = nouveau_debugfs_pstate_set,249	.release = single_release,250};251 252static struct drm_info_list nouveau_debugfs_list[] = {253	{ "vbios.rom",  nouveau_debugfs_vbios_image, 0, NULL },254	{ "strap_peek", nouveau_debugfs_strap_peek, 0, NULL },255	DRM_DEBUGFS_GPUVA_INFO(nouveau_debugfs_gpuva, NULL),256};257#define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)258 259static const struct nouveau_debugfs_files {260	const char *name;261	const struct file_operations *fops;262} nouveau_debugfs_files[] = {263	{"pstate", &nouveau_pstate_fops},264};265 266void267nouveau_drm_debugfs_init(struct drm_minor *minor)268{269	struct nouveau_drm *drm = nouveau_drm(minor->dev);270	struct dentry *dentry;271	int i;272 273	for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {274		debugfs_create_file(nouveau_debugfs_files[i].name,275				    S_IRUGO | S_IWUSR,276				    minor->debugfs_root, minor->dev,277				    nouveau_debugfs_files[i].fops);278	}279 280	drm_debugfs_create_files(nouveau_debugfs_list,281				 NOUVEAU_DEBUGFS_ENTRIES,282				 minor->debugfs_root, minor);283 284	/* Set the size of the vbios since we know it, and it's confusing to285	 * userspace if it wants to seek() but the file has a length of 0286	 */287	dentry = debugfs_lookup("vbios.rom", minor->debugfs_root);288	if (!dentry)289		return;290 291	d_inode(dentry)->i_size = drm->vbios.length;292	dput(dentry);293}294 295int296nouveau_debugfs_init(struct nouveau_drm *drm)297{298	drm->debugfs = kzalloc(sizeof(*drm->debugfs), GFP_KERNEL);299	if (!drm->debugfs)300		return -ENOMEM;301 302	return nvif_object_ctor(&drm->client.device.object, "debugfsCtrl", 0,303				NVIF_CLASS_CONTROL, NULL, 0,304				&drm->debugfs->ctrl);305}306 307void308nouveau_debugfs_fini(struct nouveau_drm *drm)309{310	if (drm->debugfs && drm->debugfs->ctrl.priv)311		nvif_object_dtor(&drm->debugfs->ctrl);312 313	kfree(drm->debugfs);314	drm->debugfs = NULL;315}316