diff options
author | Jani Nikula <jani.nikula@intel.com> | 2019-12-05 17:43:40 +0200 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2020-01-15 15:10:16 +0200 |
commit | c43c5a8818d4c399e38f636495fb02a8ff8a029a (patch) | |
tree | 8e3c1cf75e2e9cb435b2715bbedbeb114efe4f4e /drivers/gpu/drm/i915/i915_debugfs_params.c | |
parent | f22fd334890e0e24305aaa7249ff56baba082eca (diff) |
drm/i915/params: add i915 parameters to debugfs
Add a debugfs subdirectory i915_params with all the i915 module
parameters. This is a first step, with lots of boilerplate, and not much
benefit yet.
This will result in a new device specific debugfs directory at
/sys/kernel/debug/dri/<N>/i915_params duplicating the module specific
sysfs directory at /sys/module/i915/parameters/. Going forward, all
users of the parameters should use the debugfs, with the module
parameters being phased out.
Add debugfs permissions to I915_PARAMS_FOR_EACH(). This duplicates the
mode with module parameter sysfs, but the goal is to make the module
parameters read-only initial values for device specific parameters.
0 mode will bypass debugfs creation. Use it for verbose_state_checks
which will need special attention in follow-up work.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/600101c8433e7caf9303663fc85a9972fa1f05e7.1575560168.git.jani.nikula@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/i915_debugfs_params.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs_params.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs_params.c b/drivers/gpu/drm/i915/i915_debugfs_params.c new file mode 100644 index 000000000000..7f1af5a35ca1 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_debugfs_params.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2019 Intel Corporation + */ + +#include <linux/kernel.h> + +#include "i915_drv.h" +#include "i915_params.h" + +/* int param */ +static int i915_param_int_show(struct seq_file *m, void *data) +{ + int *value = m->private; + + seq_printf(m, "%d\n", *value); + + return 0; +} + +static int i915_param_int_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_param_int_show, inode->i_private); +} + +static ssize_t i915_param_int_write(struct file *file, + const char __user *ubuf, size_t len, + loff_t *offp) +{ + struct seq_file *m = file->private_data; + int *value = m->private; + int ret; + + ret = kstrtoint_from_user(ubuf, len, 0, value); + + return ret ?: len; +} + +static const struct file_operations i915_param_int_fops = { + .owner = THIS_MODULE, + .open = i915_param_int_open, + .read = seq_read, + .write = i915_param_int_write, + .llseek = default_llseek, + .release = single_release, +}; + +static const struct file_operations i915_param_int_fops_ro = { + .owner = THIS_MODULE, + .open = i915_param_int_open, + .read = seq_read, + .llseek = default_llseek, + .release = single_release, +}; + +/* unsigned int param */ +static int i915_param_uint_show(struct seq_file *m, void *data) +{ + unsigned int *value = m->private; + + seq_printf(m, "%u\n", *value); + + return 0; +} + +static int i915_param_uint_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_param_uint_show, inode->i_private); +} + +static ssize_t i915_param_uint_write(struct file *file, + const char __user *ubuf, size_t len, + loff_t *offp) +{ + struct seq_file *m = file->private_data; + unsigned int *value = m->private; + int ret; + + ret = kstrtouint_from_user(ubuf, len, 0, value); + + return ret ?: len; +} + +static const struct file_operations i915_param_uint_fops = { + .owner = THIS_MODULE, + .open = i915_param_uint_open, + .read = seq_read, + .write = i915_param_uint_write, + .llseek = default_llseek, + .release = single_release, +}; + +static const struct file_operations i915_param_uint_fops_ro = { + .owner = THIS_MODULE, + .open = i915_param_uint_open, + .read = seq_read, + .llseek = default_llseek, + .release = single_release, +}; + +/* char * param */ +static int i915_param_charp_show(struct seq_file *m, void *data) +{ + const char **s = m->private; + + seq_printf(m, "%s\n", *s); + + return 0; +} + +static int i915_param_charp_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_param_charp_show, inode->i_private); +} + +static ssize_t i915_param_charp_write(struct file *file, + const char __user *ubuf, size_t len, + loff_t *offp) +{ + struct seq_file *m = file->private_data; + char **s = m->private; + char *new, *old; + + /* FIXME: remove locking after params aren't the module params */ + kernel_param_lock(THIS_MODULE); + + old = *s; + new = strndup_user(ubuf, PAGE_SIZE); + if (IS_ERR(new)) { + len = PTR_ERR(new); + goto out; + } + + *s = new; + + kfree(old); +out: + kernel_param_unlock(THIS_MODULE); + + return len; +} + +static const struct file_operations i915_param_charp_fops = { + .owner = THIS_MODULE, + .open = i915_param_charp_open, + .read = seq_read, + .write = i915_param_charp_write, + .llseek = default_llseek, + .release = single_release, +}; + +static const struct file_operations i915_param_charp_fops_ro = { + .owner = THIS_MODULE, + .open = i915_param_charp_open, + .read = seq_read, + .llseek = default_llseek, + .release = single_release, +}; + +#define RO(mode) (((mode) & 0222) == 0) + +static struct dentry * +i915_debugfs_create_int(const char *name, umode_t mode, + struct dentry *parent, int *value) +{ + return debugfs_create_file_unsafe(name, mode, parent, value, + RO(mode) ? &i915_param_int_fops_ro : + &i915_param_int_fops); +} + +static struct dentry * +i915_debugfs_create_uint(const char *name, umode_t mode, + struct dentry *parent, unsigned int *value) +{ + return debugfs_create_file_unsafe(name, mode, parent, value, + RO(mode) ? &i915_param_uint_fops_ro : + &i915_param_uint_fops); +} + +static struct dentry * +i915_debugfs_create_charp(const char *name, umode_t mode, + struct dentry *parent, char **value) +{ + return debugfs_create_file(name, mode, parent, value, + RO(mode) ? &i915_param_charp_fops_ro : + &i915_param_charp_fops); +} + +static __always_inline void +_i915_param_create_file(struct dentry *parent, const char *name, + const char *type, int mode, void *value) +{ + if (!mode) + return; + + if (!__builtin_strcmp(type, "bool")) + debugfs_create_bool(name, mode, parent, value); + else if (!__builtin_strcmp(type, "int")) + i915_debugfs_create_int(name, mode, parent, value); + else if (!__builtin_strcmp(type, "unsigned int")) + i915_debugfs_create_uint(name, mode, parent, value); + else if (!__builtin_strcmp(type, "unsigned long")) + debugfs_create_ulong(name, mode, parent, value); + else if (!__builtin_strcmp(type, "char *")) + i915_debugfs_create_charp(name, mode, parent, value); + else + WARN(1, "no debugfs fops defined for param type %s (i915.%s)\n", + type, name); +} + +/* add a subdirectory with files for each i915 param */ +struct dentry *i915_debugfs_params(struct drm_i915_private *i915) +{ + struct drm_minor *minor = i915->drm.primary; + struct i915_params *params = &i915_modparams; + struct dentry *dir; + + dir = debugfs_create_dir("i915_params", minor->debugfs_root); + if (IS_ERR(dir)) + return dir; + + /* + * Note: We could create files for params needing special handling + * here. Set mode in params to 0 to skip the generic create file, or + * just let the generic create file fail silently with -EEXIST. + */ + +#define REGISTER(T, x, unused, mode, ...) _i915_param_create_file(dir, #x, #T, mode, ¶ms->x); + I915_PARAMS_FOR_EACH(REGISTER); +#undef REGISTER + + return dir; +} |