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