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