diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/gpu/drm/i915/i915_debugfs_params.c | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_debugfs_params.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs_params.c | 277 |
1 files changed, 277 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 000000000..783c8676e --- /dev/null +++ b/drivers/gpu/drm/i915/i915_debugfs_params.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2019 Intel Corporation + */ + +#include <linux/kernel.h> + +#include "i915_debugfs_params.h" +#include "gt/intel_gt.h" +#include "gt/uc/intel_guc.h" +#include "i915_drv.h" +#include "i915_params.h" + +#define MATCH_DEBUGFS_NODE_NAME(_file, _name) \ + (strcmp((_file)->f_path.dentry->d_name.name, (_name)) == 0) + +#define GET_I915(i915, name, ptr) \ + do { \ + struct i915_params *params; \ + params = container_of(((void *)(ptr)), typeof(*params), name); \ + (i915) = container_of(params, typeof(*(i915)), params); \ + } while (0) + +/* 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 int notify_guc(struct drm_i915_private *i915) +{ + int ret = 0; + + if (intel_uc_uses_guc_submission(&to_gt(i915)->uc)) + ret = intel_guc_global_policies_update(&to_gt(i915)->uc.guc); + + return ret; +} + +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); + if (ret) { + /* support boolean values too */ + bool b; + + ret = kstrtobool_from_user(ubuf, len, &b); + if (!ret) + *value = b; + } + + 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 drm_i915_private *i915; + struct seq_file *m = file->private_data; + unsigned int *value = m->private; + unsigned int old = *value; + int ret; + + ret = kstrtouint_from_user(ubuf, len, 0, value); + if (ret) { + /* support boolean values too */ + bool b; + + ret = kstrtobool_from_user(ubuf, len, &b); + if (!ret) + *value = b; + } + + if (!ret && MATCH_DEBUGFS_NODE_NAME(file, "reset")) { + GET_I915(i915, reset, value); + + ret = notify_guc(i915); + if (ret) + *value = old; + } + + 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; + + old = *s; + new = strndup_user(ubuf, PAGE_SIZE); + if (IS_ERR(new)) { + len = PTR_ERR(new); + goto out; + } + + *s = new; + + kfree(old); +out: + 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->params; + 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; +} |