i915_debugfs_params.c (6656B)
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 */ 25static 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 34static 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 39static 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 49static 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 70static 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 79static 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 */ 88static 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 97static 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 102static 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 133static 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 142static 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 */ 151static 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 160static 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 165static 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); 183out: 184 return len; 185} 186 187static 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 196static 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 206static struct dentry * 207i915_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 215static struct dentry * 216i915_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 224static struct dentry * 225i915_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 233static __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 */ 256struct 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}