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