Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright © 2019 Intel Corporation
0004  */
0005 
0006 #include <linux/kernel.h>
0007 
0008 #include "i915_debugfs_params.h"
0009 #include "gt/intel_gt.h"
0010 #include "gt/uc/intel_guc.h"
0011 #include "i915_drv.h"
0012 #include "i915_params.h"
0013 
0014 #define MATCH_DEBUGFS_NODE_NAME(_file, _name) \
0015     (strcmp((_file)->f_path.dentry->d_name.name, (_name)) == 0)
0016 
0017 #define GET_I915(i915, name, ptr)   \
0018     do {    \
0019         struct i915_params *params; \
0020         params = container_of(((void *)(ptr)), typeof(*params), name);  \
0021         (i915) = container_of(params, typeof(*(i915)), params); \
0022     } while (0)
0023 
0024 /* int param */
0025 static int i915_param_int_show(struct seq_file *m, void *data)
0026 {
0027     int *value = m->private;
0028 
0029     seq_printf(m, "%d\n", *value);
0030 
0031     return 0;
0032 }
0033 
0034 static int i915_param_int_open(struct inode *inode, struct file *file)
0035 {
0036     return single_open(file, i915_param_int_show, inode->i_private);
0037 }
0038 
0039 static int notify_guc(struct drm_i915_private *i915)
0040 {
0041     int ret = 0;
0042 
0043     if (intel_uc_uses_guc_submission(&to_gt(i915)->uc))
0044         ret = intel_guc_global_policies_update(&to_gt(i915)->uc.guc);
0045 
0046     return ret;
0047 }
0048 
0049 static ssize_t i915_param_int_write(struct file *file,
0050                     const char __user *ubuf, size_t len,
0051                     loff_t *offp)
0052 {
0053     struct seq_file *m = file->private_data;
0054     int *value = m->private;
0055     int ret;
0056 
0057     ret = kstrtoint_from_user(ubuf, len, 0, value);
0058     if (ret) {
0059         /* support boolean values too */
0060         bool b;
0061 
0062         ret = kstrtobool_from_user(ubuf, len, &b);
0063         if (!ret)
0064             *value = b;
0065     }
0066 
0067     return ret ?: len;
0068 }
0069 
0070 static const struct file_operations i915_param_int_fops = {
0071     .owner = THIS_MODULE,
0072     .open = i915_param_int_open,
0073     .read = seq_read,
0074     .write = i915_param_int_write,
0075     .llseek = default_llseek,
0076     .release = single_release,
0077 };
0078 
0079 static const struct file_operations i915_param_int_fops_ro = {
0080     .owner = THIS_MODULE,
0081     .open = i915_param_int_open,
0082     .read = seq_read,
0083     .llseek = default_llseek,
0084     .release = single_release,
0085 };
0086 
0087 /* unsigned int param */
0088 static int i915_param_uint_show(struct seq_file *m, void *data)
0089 {
0090     unsigned int *value = m->private;
0091 
0092     seq_printf(m, "%u\n", *value);
0093 
0094     return 0;
0095 }
0096 
0097 static int i915_param_uint_open(struct inode *inode, struct file *file)
0098 {
0099     return single_open(file, i915_param_uint_show, inode->i_private);
0100 }
0101 
0102 static ssize_t i915_param_uint_write(struct file *file,
0103                      const char __user *ubuf, size_t len,
0104                      loff_t *offp)
0105 {
0106     struct drm_i915_private *i915;
0107     struct seq_file *m = file->private_data;
0108     unsigned int *value = m->private;
0109     unsigned int old = *value;
0110     int ret;
0111 
0112     ret = kstrtouint_from_user(ubuf, len, 0, value);
0113     if (ret) {
0114         /* support boolean values too */
0115         bool b;
0116 
0117         ret = kstrtobool_from_user(ubuf, len, &b);
0118         if (!ret)
0119             *value = b;
0120     }
0121 
0122     if (!ret && MATCH_DEBUGFS_NODE_NAME(file, "reset")) {
0123         GET_I915(i915, reset, value);
0124 
0125         ret = notify_guc(i915);
0126         if (ret)
0127             *value = old;
0128     }
0129 
0130     return ret ?: len;
0131 }
0132 
0133 static const struct file_operations i915_param_uint_fops = {
0134     .owner = THIS_MODULE,
0135     .open = i915_param_uint_open,
0136     .read = seq_read,
0137     .write = i915_param_uint_write,
0138     .llseek = default_llseek,
0139     .release = single_release,
0140 };
0141 
0142 static const struct file_operations i915_param_uint_fops_ro = {
0143     .owner = THIS_MODULE,
0144     .open = i915_param_uint_open,
0145     .read = seq_read,
0146     .llseek = default_llseek,
0147     .release = single_release,
0148 };
0149 
0150 /* char * param */
0151 static int i915_param_charp_show(struct seq_file *m, void *data)
0152 {
0153     const char **s = m->private;
0154 
0155     seq_printf(m, "%s\n", *s);
0156 
0157     return 0;
0158 }
0159 
0160 static int i915_param_charp_open(struct inode *inode, struct file *file)
0161 {
0162     return single_open(file, i915_param_charp_show, inode->i_private);
0163 }
0164 
0165 static ssize_t i915_param_charp_write(struct file *file,
0166                       const char __user *ubuf, size_t len,
0167                       loff_t *offp)
0168 {
0169     struct seq_file *m = file->private_data;
0170     char **s = m->private;
0171     char *new, *old;
0172 
0173     old = *s;
0174     new = strndup_user(ubuf, PAGE_SIZE);
0175     if (IS_ERR(new)) {
0176         len = PTR_ERR(new);
0177         goto out;
0178     }
0179 
0180     *s = new;
0181 
0182     kfree(old);
0183 out:
0184     return len;
0185 }
0186 
0187 static const struct file_operations i915_param_charp_fops = {
0188     .owner = THIS_MODULE,
0189     .open = i915_param_charp_open,
0190     .read = seq_read,
0191     .write = i915_param_charp_write,
0192     .llseek = default_llseek,
0193     .release = single_release,
0194 };
0195 
0196 static const struct file_operations i915_param_charp_fops_ro = {
0197     .owner = THIS_MODULE,
0198     .open = i915_param_charp_open,
0199     .read = seq_read,
0200     .llseek = default_llseek,
0201     .release = single_release,
0202 };
0203 
0204 #define RO(mode) (((mode) & 0222) == 0)
0205 
0206 static struct dentry *
0207 i915_debugfs_create_int(const char *name, umode_t mode,
0208             struct dentry *parent, int *value)
0209 {
0210     return debugfs_create_file_unsafe(name, mode, parent, value,
0211                       RO(mode) ? &i915_param_int_fops_ro :
0212                       &i915_param_int_fops);
0213 }
0214 
0215 static struct dentry *
0216 i915_debugfs_create_uint(const char *name, umode_t mode,
0217              struct dentry *parent, unsigned int *value)
0218 {
0219     return debugfs_create_file_unsafe(name, mode, parent, value,
0220                       RO(mode) ? &i915_param_uint_fops_ro :
0221                       &i915_param_uint_fops);
0222 }
0223 
0224 static struct dentry *
0225 i915_debugfs_create_charp(const char *name, umode_t mode,
0226               struct dentry *parent, char **value)
0227 {
0228     return debugfs_create_file(name, mode, parent, value,
0229                    RO(mode) ? &i915_param_charp_fops_ro :
0230                    &i915_param_charp_fops);
0231 }
0232 
0233 static __always_inline void
0234 _i915_param_create_file(struct dentry *parent, const char *name,
0235             const char *type, int mode, void *value)
0236 {
0237     if (!mode)
0238         return;
0239 
0240     if (!__builtin_strcmp(type, "bool"))
0241         debugfs_create_bool(name, mode, parent, value);
0242     else if (!__builtin_strcmp(type, "int"))
0243         i915_debugfs_create_int(name, mode, parent, value);
0244     else if (!__builtin_strcmp(type, "unsigned int"))
0245         i915_debugfs_create_uint(name, mode, parent, value);
0246     else if (!__builtin_strcmp(type, "unsigned long"))
0247         debugfs_create_ulong(name, mode, parent, value);
0248     else if (!__builtin_strcmp(type, "char *"))
0249         i915_debugfs_create_charp(name, mode, parent, value);
0250     else
0251         WARN(1, "no debugfs fops defined for param type %s (i915.%s)\n",
0252              type, name);
0253 }
0254 
0255 /* add a subdirectory with files for each i915 param */
0256 struct dentry *i915_debugfs_params(struct drm_i915_private *i915)
0257 {
0258     struct drm_minor *minor = i915->drm.primary;
0259     struct i915_params *params = &i915->params;
0260     struct dentry *dir;
0261 
0262     dir = debugfs_create_dir("i915_params", minor->debugfs_root);
0263     if (IS_ERR(dir))
0264         return dir;
0265 
0266     /*
0267      * Note: We could create files for params needing special handling
0268      * here. Set mode in params to 0 to skip the generic create file, or
0269      * just let the generic create file fail silently with -EEXIST.
0270      */
0271 
0272 #define REGISTER(T, x, unused, mode, ...) _i915_param_create_file(dir, #x, #T, mode, &params->x);
0273     I915_PARAMS_FOR_EACH(REGISTER);
0274 #undef REGISTER
0275 
0276     return dir;
0277 }