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