brintos

brintos / linux-shallow public Read only

0
0
Text · 6.2 KiB · 33d2dcb Raw
271 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2019 Intel Corporation4 */5 6#include <linux/kernel.h>7#include <linux/debugfs.h>8 9#include "i915_debugfs_params.h"10#include "gt/intel_gt.h"11#include "gt/uc/intel_guc.h"12#include "i915_drv.h"13#include "i915_params.h"14 15#define MATCH_DEBUGFS_NODE_NAME(_file, _name) \16	(strcmp((_file)->f_path.dentry->d_name.name, (_name)) == 0)17 18#define GET_I915(i915, name, ptr)	\19	do {	\20		struct i915_params *params;	\21		params = container_of(((void *)(ptr)), typeof(*params), name);	\22		(i915) = container_of(params, typeof(*(i915)), params);	\23	} while (0)24 25/* int param */26static int i915_param_int_show(struct seq_file *m, void *data)27{28	int *value = m->private;29 30	seq_printf(m, "%d\n", *value);31 32	return 0;33}34 35static int i915_param_int_open(struct inode *inode, struct file *file)36{37	return single_open(file, i915_param_int_show, inode->i_private);38}39 40static int notify_guc(struct drm_i915_private *i915)41{42	struct intel_gt *gt;43	int i, ret = 0;44 45	for_each_gt(gt, i915, i) {46		if (intel_uc_uses_guc_submission(&gt->uc))47			ret = intel_guc_global_policies_update(&gt->uc.guc);48	}49 50	return ret;51}52 53static ssize_t i915_param_int_write(struct file *file,54				    const char __user *ubuf, size_t len,55				    loff_t *offp)56{57	struct seq_file *m = file->private_data;58	int *value = m->private;59	int ret;60 61	ret = kstrtoint_from_user(ubuf, len, 0, value);62	if (ret) {63		/* support boolean values too */64		bool b;65 66		ret = kstrtobool_from_user(ubuf, len, &b);67		if (!ret)68			*value = b;69	}70 71	return ret ?: len;72}73 74static const struct file_operations i915_param_int_fops = {75	.owner = THIS_MODULE,76	.open = i915_param_int_open,77	.read = seq_read,78	.write = i915_param_int_write,79	.llseek = default_llseek,80	.release = single_release,81};82 83static const struct file_operations i915_param_int_fops_ro = {84	.owner = THIS_MODULE,85	.open = i915_param_int_open,86	.read = seq_read,87	.llseek = default_llseek,88	.release = single_release,89};90 91/* unsigned int param */92static int i915_param_uint_show(struct seq_file *m, void *data)93{94	unsigned int *value = m->private;95 96	seq_printf(m, "%u\n", *value);97 98	return 0;99}100 101static int i915_param_uint_open(struct inode *inode, struct file *file)102{103	return single_open(file, i915_param_uint_show, inode->i_private);104}105 106static ssize_t i915_param_uint_write(struct file *file,107				     const char __user *ubuf, size_t len,108				     loff_t *offp)109{110	struct drm_i915_private *i915;111	struct seq_file *m = file->private_data;112	unsigned int *value = m->private;113	unsigned int old = *value;114	int ret;115 116	ret = kstrtouint_from_user(ubuf, len, 0, value);117	if (ret) {118		/* support boolean values too */119		bool b;120 121		ret = kstrtobool_from_user(ubuf, len, &b);122		if (!ret)123			*value = b;124	}125 126	if (!ret && MATCH_DEBUGFS_NODE_NAME(file, "reset")) {127		GET_I915(i915, reset, value);128 129		ret = notify_guc(i915);130		if (ret)131			*value = old;132	}133 134	return ret ?: len;135}136 137static const struct file_operations i915_param_uint_fops = {138	.owner = THIS_MODULE,139	.open = i915_param_uint_open,140	.read = seq_read,141	.write = i915_param_uint_write,142	.llseek = default_llseek,143	.release = single_release,144};145 146static const struct file_operations i915_param_uint_fops_ro = {147	.owner = THIS_MODULE,148	.open = i915_param_uint_open,149	.read = seq_read,150	.llseek = default_llseek,151	.release = single_release,152};153 154/* char * param */155static int i915_param_charp_show(struct seq_file *m, void *data)156{157	const char **s = m->private;158 159	seq_printf(m, "%s\n", *s);160 161	return 0;162}163 164static int i915_param_charp_open(struct inode *inode, struct file *file)165{166	return single_open(file, i915_param_charp_show, inode->i_private);167}168 169static ssize_t i915_param_charp_write(struct file *file,170				      const char __user *ubuf, size_t len,171				      loff_t *offp)172{173	struct seq_file *m = file->private_data;174	char **s = m->private;175	char *new, *old;176 177	old = *s;178	new = strndup_user(ubuf, PAGE_SIZE);179	if (IS_ERR(new)) {180		len = PTR_ERR(new);181		goto out;182	}183 184	*s = new;185 186	kfree(old);187out:188	return len;189}190 191static const struct file_operations i915_param_charp_fops = {192	.owner = THIS_MODULE,193	.open = i915_param_charp_open,194	.read = seq_read,195	.write = i915_param_charp_write,196	.llseek = default_llseek,197	.release = single_release,198};199 200static const struct file_operations i915_param_charp_fops_ro = {201	.owner = THIS_MODULE,202	.open = i915_param_charp_open,203	.read = seq_read,204	.llseek = default_llseek,205	.release = single_release,206};207 208#define RO(mode) (((mode) & 0222) == 0)209 210static struct dentry *211i915_debugfs_create_int(const char *name, umode_t mode,212			struct dentry *parent, int *value)213{214	return debugfs_create_file_unsafe(name, mode, parent, value,215					  RO(mode) ? &i915_param_int_fops_ro :216					  &i915_param_int_fops);217}218 219static struct dentry *220i915_debugfs_create_uint(const char *name, umode_t mode,221			 struct dentry *parent, unsigned int *value)222{223	return debugfs_create_file_unsafe(name, mode, parent, value,224					  RO(mode) ? &i915_param_uint_fops_ro :225					  &i915_param_uint_fops);226}227 228static struct dentry *229i915_debugfs_create_charp(const char *name, umode_t mode,230			  struct dentry *parent, char **value)231{232	return debugfs_create_file(name, mode, parent, value,233				   RO(mode) ? &i915_param_charp_fops_ro :234				   &i915_param_charp_fops);235}236 237#define _i915_param_create_file(parent, name, mode, valp)		\238	do {								\239		if (mode)						\240			_Generic(valp,					\241				 bool *: debugfs_create_bool,		\242				 int *: i915_debugfs_create_int,	\243				 unsigned int *: i915_debugfs_create_uint, \244				 unsigned long *: debugfs_create_ulong,	\245				 char **: i915_debugfs_create_charp)(name, mode, parent, valp); \246	} while(0)247 248/* add a subdirectory with files for each i915 param */249struct dentry *i915_debugfs_params(struct drm_i915_private *i915)250{251	struct drm_minor *minor = i915->drm.primary;252	struct i915_params *params = &i915->params;253	struct dentry *dir;254 255	dir = debugfs_create_dir("i915_params", minor->debugfs_root);256	if (IS_ERR(dir))257		return dir;258 259	/*260	 * Note: We could create files for params needing special handling261	 * here. Set mode in params to 0 to skip the generic create file, or262	 * just let the generic create file fail silently with -EEXIST.263	 */264 265#define REGISTER(T, x, unused, mode, ...) _i915_param_create_file(dir, #x, mode, &params->x);266	I915_PARAMS_FOR_EACH(REGISTER);267#undef REGISTER268 269	return dir;270}271