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