3bce94fd5f4c0 (Greg Kroah-Hartman 2017-11-07 16:59:23 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * file.c - part of debugfs, a tiny little debug file system
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * Copyright (C) 2004 IBM Inc.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * debugfs is for people to use instead of /proc or /sys.
e1b4fc7add72f (Mauro Carvalho Chehab 2017-05-14 12:04:55 -0300 9) * See Documentation/filesystems/ for more details.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <linux/module.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/fs.h>
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 14) #include <linux/seq_file.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) #include <linux/pagemap.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) #include <linux/debugfs.h>
03e099fbb0fbd (Alessandro Rubini 2011-11-21 10:01:40 +0100 17) #include <linux/io.h>
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 18) #include <linux/slab.h>
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 19) #include <linux/atomic.h>
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 20) #include <linux/device.h>
30332eeefec8f (Geert Uytterhoeven 2020-02-11 19:18:55 +0100 21) #include <linux/pm_runtime.h>
cfe39442ab8ce (Al Viro 2018-02-01 12:14:57 -0500 22) #include <linux/poll.h>
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 23) #include <linux/security.h>
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 24)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 25) #include "internal.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 27) struct poll_table_struct;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 28)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) static ssize_t default_read_file(struct file *file, char __user *buf,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30) size_t count, loff_t *ppos)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) static ssize_t default_write_file(struct file *file, const char __user *buf,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) size_t count, loff_t *ppos)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 38) return count;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 41) const struct file_operations debugfs_noop_file_operations = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42) .read = default_read_file,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 43) .write = default_write_file,
234e340582901 (Stephen Boyd 2012-04-05 14:25:11 -0700 44) .open = simple_open,
6038f373a3dc1 (Arnd Bergmann 2010-08-15 18:52:59 +0200 45) .llseek = noop_llseek,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 48) #define F_DENTRY(filp) ((filp)->f_path.dentry)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 49)
7c8d469877b16 (Nicolai Stange 2017-10-31 00:15:47 +0100 50) const struct file_operations *debugfs_real_fops(const struct file *filp)
7c8d469877b16 (Nicolai Stange 2017-10-31 00:15:47 +0100 51) {
7c8d469877b16 (Nicolai Stange 2017-10-31 00:15:47 +0100 52) struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata;
055ab8e3e3d52 (Nicolai Stange 2017-10-31 00:15:49 +0100 53)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 54) if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) {
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 55) /*
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 56) * Urgh, we've been called w/o a protecting
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 57) * debugfs_file_get().
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 58) */
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 59) WARN_ON(1);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 60) return NULL;
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 61) }
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 62)
7c8d469877b16 (Nicolai Stange 2017-10-31 00:15:47 +0100 63) return fsd->real_fops;
7c8d469877b16 (Nicolai Stange 2017-10-31 00:15:47 +0100 64) }
7c8d469877b16 (Nicolai Stange 2017-10-31 00:15:47 +0100 65) EXPORT_SYMBOL_GPL(debugfs_real_fops);
7c8d469877b16 (Nicolai Stange 2017-10-31 00:15:47 +0100 66)
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 67) /**
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 68) * debugfs_file_get - mark the beginning of file data access
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 69) * @dentry: the dentry object whose data is being accessed.
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 70) *
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 71) * Up to a matching call to debugfs_file_put(), any successive call
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 72) * into the file removing functions debugfs_remove() and
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 73) * debugfs_remove_recursive() will block. Since associated private
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 74) * file data may only get freed after a successful return of any of
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 75) * the removal functions, you may safely access it after a successful
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 76) * call to debugfs_file_get() without worrying about lifetime issues.
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 77) *
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 78) * If -%EIO is returned, the file has already been removed and thus,
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 79) * it is not safe to access any of its data. If, on the other hand,
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 80) * it is allowed to access the file data, zero is returned.
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 81) */
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 82) int debugfs_file_get(struct dentry *dentry)
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 83) {
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 84) struct debugfs_fsdata *fsd;
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 85) void *d_fsd;
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 86)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 87) d_fsd = READ_ONCE(dentry->d_fsdata);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 88) if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 89) fsd = d_fsd;
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 90) } else {
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 91) fsd = kmalloc(sizeof(*fsd), GFP_KERNEL);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 92) if (!fsd)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 93) return -ENOMEM;
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 94)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 95) fsd->real_fops = (void *)((unsigned long)d_fsd &
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 96) ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 97) refcount_set(&fsd->active_users, 1);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 98) init_completion(&fsd->active_users_drained);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 99) if (cmpxchg(&dentry->d_fsdata, d_fsd, fsd) != d_fsd) {
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 100) kfree(fsd);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 101) fsd = READ_ONCE(dentry->d_fsdata);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 102) }
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 103) }
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 104)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 105) /*
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 106) * In case of a successful cmpxchg() above, this check is
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 107) * strictly necessary and must follow it, see the comment in
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 108) * __debugfs_remove_file().
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 109) * OTOH, if the cmpxchg() hasn't been executed or wasn't
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 110) * successful, this serves the purpose of not starving
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 111) * removers.
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 112) */
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 113) if (d_unlinked(dentry))
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 114) return -EIO;
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 115)
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 116) if (!refcount_inc_not_zero(&fsd->active_users))
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 117) return -EIO;
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 118)
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 119) return 0;
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 120) }
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 121) EXPORT_SYMBOL_GPL(debugfs_file_get);
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 122)
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 123) /**
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 124) * debugfs_file_put - mark the end of file data access
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 125) * @dentry: the dentry object formerly passed to
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 126) * debugfs_file_get().
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 127) *
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 128) * Allow any ongoing concurrent call into debugfs_remove() or
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 129) * debugfs_remove_recursive() blocked by a former call to
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 130) * debugfs_file_get() to proceed and return to its caller.
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 131) */
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 132) void debugfs_file_put(struct dentry *dentry)
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 133) {
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 134) struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata);
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 135)
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 136) if (refcount_dec_and_test(&fsd->active_users))
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 137) complete(&fsd->active_users_drained);
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 138) }
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 139) EXPORT_SYMBOL_GPL(debugfs_file_put);
e9117a5a4bf65 (Nicolai Stange 2017-10-31 00:15:48 +0100 140)
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 141) /*
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 142) * Only permit access to world-readable files when the kernel is locked down.
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 143) * We also need to exclude any file that has ways to write or alter it as root
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 144) * can bypass the permissions check.
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 145) */
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 146) static int debugfs_locked_down(struct inode *inode,
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 147) struct file *filp,
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 148) const struct file_operations *real_fops)
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 149) {
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 150) if ((inode->i_mode & 07777) == 0444 &&
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 151) !(filp->f_mode & FMODE_WRITE) &&
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 152) !real_fops->unlocked_ioctl &&
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 153) !real_fops->compat_ioctl &&
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 154) !real_fops->mmap)
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 155) return 0;
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 156)
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 157) if (security_locked_down(LOCKDOWN_DEBUGFS))
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 158) return -EPERM;
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 159)
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 160) return 0;
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 161) }
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 162)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 163) static int open_proxy_open(struct inode *inode, struct file *filp)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 164) {
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 165) struct dentry *dentry = F_DENTRY(filp);
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 166) const struct file_operations *real_fops = NULL;
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 167) int r;
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 168)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 169) r = debugfs_file_get(dentry);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 170) if (r)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 171) return r == -EIO ? -ENOENT : r;
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 172)
86f0e06767dda (Christian Lamparter 2016-09-17 21:43:01 +0200 173) real_fops = debugfs_real_fops(filp);
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 174)
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 175) r = debugfs_locked_down(inode, filp, real_fops);
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 176) if (r)
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 177) goto out;
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 178)
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 179) if (!fops_get(real_fops)) {
e3b9fc7eec55e (Vladis Dronov 2020-08-11 17:01:29 +0200 180) #ifdef CONFIG_MODULES
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 181) if (real_fops->owner &&
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 182) real_fops->owner->state == MODULE_STATE_GOING)
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 183) goto out;
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 184) #endif
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 185)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 186) /* Huh? Module did not clean up after itself at exit? */
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 187) WARN(1, "debugfs file owner did not clean up at exit: %pd",
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 188) dentry);
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 189) r = -ENXIO;
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 190) goto out;
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 191) }
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 192) replace_fops(filp, real_fops);
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 193)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 194) if (real_fops->open)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 195) r = real_fops->open(inode, filp);
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 196)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 197) out:
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 198) debugfs_file_put(dentry);
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 199) return r;
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 200) }
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 201)
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 202) const struct file_operations debugfs_open_proxy_file_operations = {
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 203) .open = open_proxy_open,
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 204) };
9fd4dcece43a5 (Nicolai Stange 2016-03-22 14:11:13 +0100 205)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 206) #define PROTO(args...) args
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 207) #define ARGS(args...) args
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 208)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 209) #define FULL_PROXY_FUNC(name, ret_type, filp, proto, args) \
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 210) static ret_type full_proxy_ ## name(proto) \
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 211) { \
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 212) struct dentry *dentry = F_DENTRY(filp); \
154b9d7512ae0 (Nicolai Stange 2017-10-31 00:15:53 +0100 213) const struct file_operations *real_fops; \
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 214) ret_type r; \
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 215) \
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 216) r = debugfs_file_get(dentry); \
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 217) if (unlikely(r)) \
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 218) return r; \
154b9d7512ae0 (Nicolai Stange 2017-10-31 00:15:53 +0100 219) real_fops = debugfs_real_fops(filp); \
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 220) r = real_fops->name(args); \
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 221) debugfs_file_put(dentry); \
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 222) return r; \
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 223) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 224)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 225) FULL_PROXY_FUNC(llseek, loff_t, filp,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 226) PROTO(struct file *filp, loff_t offset, int whence),
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 227) ARGS(filp, offset, whence));
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 228)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 229) FULL_PROXY_FUNC(read, ssize_t, filp,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 230) PROTO(struct file *filp, char __user *buf, size_t size,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 231) loff_t *ppos),
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 232) ARGS(filp, buf, size, ppos));
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 233)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 234) FULL_PROXY_FUNC(write, ssize_t, filp,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 235) PROTO(struct file *filp, const char __user *buf, size_t size,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 236) loff_t *ppos),
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 237) ARGS(filp, buf, size, ppos));
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 238)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 239) FULL_PROXY_FUNC(unlocked_ioctl, long, filp,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 240) PROTO(struct file *filp, unsigned int cmd, unsigned long arg),
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 241) ARGS(filp, cmd, arg));
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 242)
076ccb76e1a6c (Al Viro 2017-07-03 01:02:18 -0400 243) static __poll_t full_proxy_poll(struct file *filp,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 244) struct poll_table_struct *wait)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 245) {
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 246) struct dentry *dentry = F_DENTRY(filp);
e6c8adca20ba4 (Al Viro 2017-07-03 22:25:56 -0400 247) __poll_t r = 0;
154b9d7512ae0 (Nicolai Stange 2017-10-31 00:15:53 +0100 248) const struct file_operations *real_fops;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 249)
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 250) if (debugfs_file_get(dentry))
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 251) return EPOLLHUP;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 252)
154b9d7512ae0 (Nicolai Stange 2017-10-31 00:15:53 +0100 253) real_fops = debugfs_real_fops(filp);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 254) r = real_fops->poll(filp, wait);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 255) debugfs_file_put(dentry);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 256) return r;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 257) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 258)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 259) static int full_proxy_release(struct inode *inode, struct file *filp)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 260) {
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 261) const struct dentry *dentry = F_DENTRY(filp);
86f0e06767dda (Christian Lamparter 2016-09-17 21:43:01 +0200 262) const struct file_operations *real_fops = debugfs_real_fops(filp);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 263) const struct file_operations *proxy_fops = filp->f_op;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 264) int r = 0;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 265)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 266) /*
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 267) * We must not protect this against removal races here: the
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 268) * original releaser should be called unconditionally in order
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 269) * not to leak any resources. Releasers must not assume that
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 270) * ->i_private is still being meaningful here.
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 271) */
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 272) if (real_fops->release)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 273) r = real_fops->release(inode, filp);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 274)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 275) replace_fops(filp, d_inode(dentry)->i_fop);
c80a67bd5d13e (Xu Wang 2020-07-09 05:40:33 +0000 276) kfree(proxy_fops);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 277) fops_put(real_fops);
a1a9e5d29854f (Eric Engestrom 2016-09-21 10:27:36 +0100 278) return r;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 279) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 280)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 281) static void __full_proxy_fops_init(struct file_operations *proxy_fops,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 282) const struct file_operations *real_fops)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 283) {
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 284) proxy_fops->release = full_proxy_release;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 285) if (real_fops->llseek)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 286) proxy_fops->llseek = full_proxy_llseek;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 287) if (real_fops->read)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 288) proxy_fops->read = full_proxy_read;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 289) if (real_fops->write)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 290) proxy_fops->write = full_proxy_write;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 291) if (real_fops->poll)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 292) proxy_fops->poll = full_proxy_poll;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 293) if (real_fops->unlocked_ioctl)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 294) proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 295) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 296)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 297) static int full_proxy_open(struct inode *inode, struct file *filp)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 298) {
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 299) struct dentry *dentry = F_DENTRY(filp);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 300) const struct file_operations *real_fops = NULL;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 301) struct file_operations *proxy_fops = NULL;
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 302) int r;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 303)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 304) r = debugfs_file_get(dentry);
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 305) if (r)
7d39bc50c47b3 (Nicolai Stange 2017-10-31 00:15:54 +0100 306) return r == -EIO ? -ENOENT : r;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 307)
86f0e06767dda (Christian Lamparter 2016-09-17 21:43:01 +0200 308) real_fops = debugfs_real_fops(filp);
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 309)
a37f4958f7b63 (Eric Snowberg 2019-12-07 11:16:03 -0500 310) r = debugfs_locked_down(inode, filp, real_fops);
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 311) if (r)
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 312) goto out;
5496197f9b084 (David Howells 2019-08-19 17:18:02 -0700 313)
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 314) if (!fops_get(real_fops)) {
e3b9fc7eec55e (Vladis Dronov 2020-08-11 17:01:29 +0200 315) #ifdef CONFIG_MODULES
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 316) if (real_fops->owner &&
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 317) real_fops->owner->state == MODULE_STATE_GOING)
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 318) goto out;
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 319) #endif
275678e7a9be6 (Taehee Yoo 2020-02-18 04:31:50 +0000 320)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 321) /* Huh? Module did not cleanup after itself at exit? */
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 322) WARN(1, "debugfs file owner did not clean up at exit: %pd",
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 323) dentry);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 324) r = -ENXIO;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 325) goto out;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 326) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 327)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 328) proxy_fops = kzalloc(sizeof(*proxy_fops), GFP_KERNEL);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 329) if (!proxy_fops) {
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 330) r = -ENOMEM;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 331) goto free_proxy;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 332) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 333) __full_proxy_fops_init(proxy_fops, real_fops);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 334) replace_fops(filp, proxy_fops);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 335)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 336) if (real_fops->open) {
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 337) r = real_fops->open(inode, filp);
b10e3e90485e3 (Nicolai Stange 2016-05-24 13:08:53 +0200 338) if (r) {
b10e3e90485e3 (Nicolai Stange 2016-05-24 13:08:53 +0200 339) replace_fops(filp, d_inode(dentry)->i_fop);
b10e3e90485e3 (Nicolai Stange 2016-05-24 13:08:53 +0200 340) goto free_proxy;
b10e3e90485e3 (Nicolai Stange 2016-05-24 13:08:53 +0200 341) } else if (filp->f_op != proxy_fops) {
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 342) /* No protection against file removal anymore. */
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 343) WARN(1, "debugfs file owner replaced proxy fops: %pd",
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 344) dentry);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 345) goto free_proxy;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 346) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 347) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 348)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 349) goto out;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 350) free_proxy:
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 351) kfree(proxy_fops);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 352) fops_put(real_fops);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 353) out:
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 354) debugfs_file_put(dentry);
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 355) return r;
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 356) }
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 357)
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 358) const struct file_operations debugfs_full_proxy_file_operations = {
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 359) .open = full_proxy_open,
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 360) };
49d200deaa680 (Nicolai Stange 2016-03-22 14:11:14 +0100 361)
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 362) ssize_t debugfs_attr_read(struct file *file, char __user *buf,
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 363) size_t len, loff_t *ppos)
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 364) {
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 365) struct dentry *dentry = F_DENTRY(file);
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 366) ssize_t ret;
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 367)
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 368) ret = debugfs_file_get(dentry);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 369) if (unlikely(ret))
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 370) return ret;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 371) ret = simple_attr_read(file, buf, len, ppos);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 372) debugfs_file_put(dentry);
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 373) return ret;
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 374) }
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 375) EXPORT_SYMBOL_GPL(debugfs_attr_read);
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 376)
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 377) ssize_t debugfs_attr_write(struct file *file, const char __user *buf,
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 378) size_t len, loff_t *ppos)
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 379) {
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 380) struct dentry *dentry = F_DENTRY(file);
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 381) ssize_t ret;
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 382)
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 383) ret = debugfs_file_get(dentry);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 384) if (unlikely(ret))
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 385) return ret;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 386) ret = simple_attr_write(file, buf, len, ppos);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 387) debugfs_file_put(dentry);
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 388) return ret;
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 389) }
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 390) EXPORT_SYMBOL_GPL(debugfs_attr_write);
c646880814903 (Nicolai Stange 2016-03-22 14:11:15 +0100 391)
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 392) static struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 393) struct dentry *parent, void *value,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 394) const struct file_operations *fops,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 395) const struct file_operations *fops_ro,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 396) const struct file_operations *fops_wo)
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 397) {
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 398) /* if there are no write bits set, make read only */
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 399) if (!(mode & S_IWUGO))
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 400) return debugfs_create_file_unsafe(name, mode, parent, value,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 401) fops_ro);
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 402) /* if there are no read bits set, make write only */
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 403) if (!(mode & S_IRUGO))
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 404) return debugfs_create_file_unsafe(name, mode, parent, value,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 405) fops_wo);
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 406)
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 407) return debugfs_create_file_unsafe(name, mode, parent, value, fops);
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 408) }
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 409)
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 410) static int debugfs_u8_set(void *data, u64 val)
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 411) {
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 412) *(u8 *)data = val;
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 413) return 0;
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 414) }
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 415) static int debugfs_u8_get(void *data, u64 *val)
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 416) {
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 417) *val = *(u8 *)data;
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 418) return 0;
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 419) }
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 420) DEFINE_DEBUGFS_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 421) DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 422) DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n");
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 423)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 424) /**
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 425) * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 426) * @name: a pointer to a string containing the name of the file to create.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 427) * @mode: the permission that the file should have
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 428) * @parent: a pointer to the parent dentry for this file. This should be a
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 429) * directory dentry if set. If this parameter is %NULL, then the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 430) * file will be created in the root of the debugfs filesystem.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 431) * @value: a pointer to the variable that the file should read to and write
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 432) * from.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 433) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 434) * This function creates a file in debugfs with the given name that
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 435) * contains the value of the variable @value. If the @mode variable is so
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 436) * set, it can be read from, and written to.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 437) */
9655ac4aca20d (Greg Kroah-Hartman 2019-10-11 15:29:24 +0200 438) void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent,
9655ac4aca20d (Greg Kroah-Hartman 2019-10-11 15:29:24 +0200 439) u8 *value)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 440) {
9655ac4aca20d (Greg Kroah-Hartman 2019-10-11 15:29:24 +0200 441) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8,
b97f679954b77 (Stephen Boyd 2015-10-12 18:09:09 -0700 442) &fops_u8_ro, &fops_u8_wo);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 443) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 444) EXPORT_SYMBOL_GPL(debugfs_create_u8);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 445)
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 446) static int debugfs_u16_set(void *data, u64 val)
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 447) {
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 448) *(u16 *)data = val;
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 449) return 0;
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 450) }
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 451) static int debugfs_u16_get(void *data, u64 *val)
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 452) {
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 453) *val = *(u16 *)data;
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 454) return 0;
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 455) }
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 456) DEFINE_DEBUGFS_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 457) DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 458) DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n");
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 459)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 460) /**
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 461) * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 462) * @name: a pointer to a string containing the name of the file to create.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 463) * @mode: the permission that the file should have
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 464) * @parent: a pointer to the parent dentry for this file. This should be a
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 465) * directory dentry if set. If this parameter is %NULL, then the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 466) * file will be created in the root of the debugfs filesystem.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 467) * @value: a pointer to the variable that the file should read to and write
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 468) * from.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 469) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 470) * This function creates a file in debugfs with the given name that
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 471) * contains the value of the variable @value. If the @mode variable is so
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 472) * set, it can be read from, and written to.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 473) */
313f5dbba41d9 (Greg Kroah-Hartman 2019-10-11 15:29:25 +0200 474) void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent,
313f5dbba41d9 (Greg Kroah-Hartman 2019-10-11 15:29:25 +0200 475) u16 *value)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 476) {
313f5dbba41d9 (Greg Kroah-Hartman 2019-10-11 15:29:25 +0200 477) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16,
b97f679954b77 (Stephen Boyd 2015-10-12 18:09:09 -0700 478) &fops_u16_ro, &fops_u16_wo);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 479) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 480) EXPORT_SYMBOL_GPL(debugfs_create_u16);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 481)
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 482) static int debugfs_u32_set(void *data, u64 val)
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 483) {
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 484) *(u32 *)data = val;
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 485) return 0;
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 486) }
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 487) static int debugfs_u32_get(void *data, u64 *val)
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 488) {
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 489) *val = *(u32 *)data;
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 490) return 0;
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 491) }
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 492) DEFINE_DEBUGFS_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 493) DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 494) DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n");
acaefc25d21f8 (Arnd Bergmann 2005-05-18 14:40:59 +0200 495)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 496) /**
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 497) * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 498) * @name: a pointer to a string containing the name of the file to create.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 499) * @mode: the permission that the file should have
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 500) * @parent: a pointer to the parent dentry for this file. This should be a
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 501) * directory dentry if set. If this parameter is %NULL, then the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 502) * file will be created in the root of the debugfs filesystem.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 503) * @value: a pointer to the variable that the file should read to and write
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 504) * from.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 505) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 506) * This function creates a file in debugfs with the given name that
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 507) * contains the value of the variable @value. If the @mode variable is so
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 508) * set, it can be read from, and written to.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 509) */
2b07021a940ce (Greg Kroah-Hartman 2020-04-16 16:54:48 +0200 510) void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent,
2b07021a940ce (Greg Kroah-Hartman 2020-04-16 16:54:48 +0200 511) u32 *value)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 512) {
2b07021a940ce (Greg Kroah-Hartman 2020-04-16 16:54:48 +0200 513) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32,
b97f679954b77 (Stephen Boyd 2015-10-12 18:09:09 -0700 514) &fops_u32_ro, &fops_u32_wo);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 515) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 516) EXPORT_SYMBOL_GPL(debugfs_create_u32);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 517)
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 518) static int debugfs_u64_set(void *data, u64 val)
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 519) {
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 520) *(u64 *)data = val;
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 521) return 0;
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 522) }
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 523)
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 524) static int debugfs_u64_get(void *data, u64 *val)
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 525) {
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 526) *val = *(u64 *)data;
8b88b0998e35d (Christoph Hellwig 2008-02-08 04:20:26 -0800 527) return 0;
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 528) }
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 529) DEFINE_DEBUGFS_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 530) DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 531) DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n");
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 532)
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 533) /**
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 534) * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 535) * @name: a pointer to a string containing the name of the file to create.
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 536) * @mode: the permission that the file should have
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 537) * @parent: a pointer to the parent dentry for this file. This should be a
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 538) * directory dentry if set. If this parameter is %NULL, then the
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 539) * file will be created in the root of the debugfs filesystem.
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 540) * @value: a pointer to the variable that the file should read to and write
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 541) * from.
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 542) *
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 543) * This function creates a file in debugfs with the given name that
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 544) * contains the value of the variable @value. If the @mode variable is so
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 545) * set, it can be read from, and written to.
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 546) */
ad26221fb9e64 (Greg Kroah-Hartman 2019-10-11 15:29:26 +0200 547) void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent,
ad26221fb9e64 (Greg Kroah-Hartman 2019-10-11 15:29:26 +0200 548) u64 *value)
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 549) {
ad26221fb9e64 (Greg Kroah-Hartman 2019-10-11 15:29:26 +0200 550) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64,
b97f679954b77 (Stephen Boyd 2015-10-12 18:09:09 -0700 551) &fops_u64_ro, &fops_u64_wo);
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 552) }
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 553) EXPORT_SYMBOL_GPL(debugfs_create_u64);
8447891fe8458 (Michael Ellerman 2007-04-17 15:59:36 +1000 554)
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 555) static int debugfs_ulong_set(void *data, u64 val)
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 556) {
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 557) *(unsigned long *)data = val;
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 558) return 0;
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 559) }
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 560)
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 561) static int debugfs_ulong_get(void *data, u64 *val)
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 562) {
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 563) *val = *(unsigned long *)data;
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 564) return 0;
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 565) }
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 566) DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 567) "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 568) DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 569) DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n");
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 570)
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 571) /**
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 572) * debugfs_create_ulong - create a debugfs file that is used to read and write
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 573) * an unsigned long value.
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 574) * @name: a pointer to a string containing the name of the file to create.
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 575) * @mode: the permission that the file should have
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 576) * @parent: a pointer to the parent dentry for this file. This should be a
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 577) * directory dentry if set. If this parameter is %NULL, then the
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 578) * file will be created in the root of the debugfs filesystem.
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 579) * @value: a pointer to the variable that the file should read to and write
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 580) * from.
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 581) *
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 582) * This function creates a file in debugfs with the given name that
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 583) * contains the value of the variable @value. If the @mode variable is so
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 584) * set, it can be read from, and written to.
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 585) *
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 586) * This function will return a pointer to a dentry if it succeeds. This
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 587) * pointer must be passed to the debugfs_remove() function when the file is
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 588) * to be removed (no automatic cleanup happens if your module is unloaded,
adc92dd4550ee (Daniel W. S. Almeida 2019-12-26 22:00:33 -0300 589) * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
9abb24990a2bf (Ronald Tschalär 2019-04-15 01:25:05 -0700 590) * returned.
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 591) *
adc92dd4550ee (Daniel W. S. Almeida 2019-12-26 22:00:33 -0300 592) * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
9abb24990a2bf (Ronald Tschalär 2019-04-15 01:25:05 -0700 593) * be returned.
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 594) */
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 595) struct dentry *debugfs_create_ulong(const char *name, umode_t mode,
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 596) struct dentry *parent, unsigned long *value)
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 597) {
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 598) return debugfs_create_mode_unsafe(name, mode, parent, value,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 599) &fops_ulong, &fops_ulong_ro,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 600) &fops_ulong_wo);
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 601) }
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 602) EXPORT_SYMBOL_GPL(debugfs_create_ulong);
c23fe83138ed7 (Viresh Kumar 2015-10-18 22:43:19 +0530 603)
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 604) DEFINE_DEBUGFS_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 605) DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 606) DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n");
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 607)
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 608) DEFINE_DEBUGFS_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 609) "0x%04llx\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 610) DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 611) DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n");
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 612)
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 613) DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 614) "0x%08llx\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 615) DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 616) DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n");
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 617)
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 618) DEFINE_DEBUGFS_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 619) "0x%016llx\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 620) DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 621) DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n");
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 622)
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 623) /*
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 624) * debugfs_create_x{8,16,32,64} - create a debugfs file that is used to read and write an unsigned {8,16,32,64}-bit value
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 625) *
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 626) * These functions are exactly the same as the above functions (but use a hex
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 627) * output for the decimal challenged). For details look at the above unsigned
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 628) * decimal functions.
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 629) */
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 630)
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 631) /**
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 632) * debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8-bit value
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 633) * @name: a pointer to a string containing the name of the file to create.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 634) * @mode: the permission that the file should have
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 635) * @parent: a pointer to the parent dentry for this file. This should be a
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 636) * directory dentry if set. If this parameter is %NULL, then the
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 637) * file will be created in the root of the debugfs filesystem.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 638) * @value: a pointer to the variable that the file should read to and write
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 639) * from.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 640) */
c7c1168909410 (Greg Kroah-Hartman 2019-10-11 15:29:28 +0200 641) void debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent,
c7c1168909410 (Greg Kroah-Hartman 2019-10-11 15:29:28 +0200 642) u8 *value)
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 643) {
c7c1168909410 (Greg Kroah-Hartman 2019-10-11 15:29:28 +0200 644) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8,
b97f679954b77 (Stephen Boyd 2015-10-12 18:09:09 -0700 645) &fops_x8_ro, &fops_x8_wo);
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 646) }
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 647) EXPORT_SYMBOL_GPL(debugfs_create_x8);
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 648)
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 649) /**
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 650) * debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16-bit value
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 651) * @name: a pointer to a string containing the name of the file to create.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 652) * @mode: the permission that the file should have
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 653) * @parent: a pointer to the parent dentry for this file. This should be a
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 654) * directory dentry if set. If this parameter is %NULL, then the
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 655) * file will be created in the root of the debugfs filesystem.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 656) * @value: a pointer to the variable that the file should read to and write
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 657) * from.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 658) */
e40d38f28c10e (Greg Kroah-Hartman 2019-10-11 15:29:29 +0200 659) void debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent,
e40d38f28c10e (Greg Kroah-Hartman 2019-10-11 15:29:29 +0200 660) u16 *value)
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 661) {
e40d38f28c10e (Greg Kroah-Hartman 2019-10-11 15:29:29 +0200 662) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16,
b97f679954b77 (Stephen Boyd 2015-10-12 18:09:09 -0700 663) &fops_x16_ro, &fops_x16_wo);
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 664) }
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 665) EXPORT_SYMBOL_GPL(debugfs_create_x16);
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 666)
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 667) /**
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 668) * debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32-bit value
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 669) * @name: a pointer to a string containing the name of the file to create.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 670) * @mode: the permission that the file should have
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 671) * @parent: a pointer to the parent dentry for this file. This should be a
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 672) * directory dentry if set. If this parameter is %NULL, then the
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 673) * file will be created in the root of the debugfs filesystem.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 674) * @value: a pointer to the variable that the file should read to and write
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 675) * from.
e6716b87d5c9e (Randy Dunlap 2007-10-15 17:30:19 -0700 676) */
f5cb0a7e64f41 (Greg Kroah-Hartman 2019-10-11 15:29:30 +0200 677) void debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent,
f5cb0a7e64f41 (Greg Kroah-Hartman 2019-10-11 15:29:30 +0200 678) u32 *value)
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 679) {
f5cb0a7e64f41 (Greg Kroah-Hartman 2019-10-11 15:29:30 +0200 680) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32,
b97f679954b77 (Stephen Boyd 2015-10-12 18:09:09 -0700 681) &fops_x32_ro, &fops_x32_wo);
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 682) }
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 683) EXPORT_SYMBOL_GPL(debugfs_create_x32);
2ebefc50161a0 (Robin Getz 2007-08-02 18:23:50 -0400 684)
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 685) /**
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 686) * debugfs_create_x64 - create a debugfs file that is used to read and write an unsigned 64-bit value
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 687) * @name: a pointer to a string containing the name of the file to create.
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 688) * @mode: the permission that the file should have
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 689) * @parent: a pointer to the parent dentry for this file. This should be a
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 690) * directory dentry if set. If this parameter is %NULL, then the
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 691) * file will be created in the root of the debugfs filesystem.
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 692) * @value: a pointer to the variable that the file should read to and write
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 693) * from.
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 694) */
0864c408fb1e5 (Greg Kroah-Hartman 2019-10-11 15:29:31 +0200 695) void debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent,
0864c408fb1e5 (Greg Kroah-Hartman 2019-10-11 15:29:31 +0200 696) u64 *value)
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 697) {
0864c408fb1e5 (Greg Kroah-Hartman 2019-10-11 15:29:31 +0200 698) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64,
82b7d4fb4e0bc (Stephen Boyd 2015-10-12 18:09:10 -0700 699) &fops_x64_ro, &fops_x64_wo);
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 700) }
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 701) EXPORT_SYMBOL_GPL(debugfs_create_x64);
15b0beaa332b3 (Huang Ying 2010-05-18 14:35:23 +0800 702)
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 703)
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 704) static int debugfs_size_t_set(void *data, u64 val)
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 705) {
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 706) *(size_t *)data = val;
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 707) return 0;
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 708) }
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 709) static int debugfs_size_t_get(void *data, u64 *val)
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 710) {
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 711) *val = *(size_t *)data;
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 712) return 0;
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 713) }
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 714) DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t, debugfs_size_t_get, debugfs_size_t_set,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 715) "%llu\n"); /* %llu and %zu are more or less the same */
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 716) DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t_ro, debugfs_size_t_get, NULL, "%llu\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 717) DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t_wo, NULL, debugfs_size_t_set, "%llu\n");
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 718)
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 719) /**
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 720) * debugfs_create_size_t - create a debugfs file that is used to read and write an size_t value
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 721) * @name: a pointer to a string containing the name of the file to create.
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 722) * @mode: the permission that the file should have
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 723) * @parent: a pointer to the parent dentry for this file. This should be a
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 724) * directory dentry if set. If this parameter is %NULL, then the
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 725) * file will be created in the root of the debugfs filesystem.
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 726) * @value: a pointer to the variable that the file should read to and write
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 727) * from.
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 728) */
8e5802635f0f9 (Greg Kroah-Hartman 2019-10-11 15:29:27 +0200 729) void debugfs_create_size_t(const char *name, umode_t mode,
8e5802635f0f9 (Greg Kroah-Hartman 2019-10-11 15:29:27 +0200 730) struct dentry *parent, size_t *value)
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 731) {
8e5802635f0f9 (Greg Kroah-Hartman 2019-10-11 15:29:27 +0200 732) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_size_t,
8e5802635f0f9 (Greg Kroah-Hartman 2019-10-11 15:29:27 +0200 733) &fops_size_t_ro, &fops_size_t_wo);
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 734) }
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 735) EXPORT_SYMBOL_GPL(debugfs_create_size_t);
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 736)
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 737) static int debugfs_atomic_t_set(void *data, u64 val)
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 738) {
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 739) atomic_set((atomic_t *)data, val);
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 740) return 0;
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 741) }
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 742) static int debugfs_atomic_t_get(void *data, u64 *val)
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 743) {
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 744) *val = atomic_read((atomic_t *)data);
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 745) return 0;
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 746) }
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 747) DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get,
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 748) debugfs_atomic_t_set, "%lld\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 749) DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 750) "%lld\n");
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 751) DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set,
4909f168104b2 (Nicolai Stange 2016-03-22 14:11:17 +0100 752) "%lld\n");
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 753)
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 754) /**
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 755) * debugfs_create_atomic_t - create a debugfs file that is used to read and
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 756) * write an atomic_t value
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 757) * @name: a pointer to a string containing the name of the file to create.
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 758) * @mode: the permission that the file should have
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 759) * @parent: a pointer to the parent dentry for this file. This should be a
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 760) * directory dentry if set. If this parameter is %NULL, then the
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 761) * file will be created in the root of the debugfs filesystem.
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 762) * @value: a pointer to the variable that the file should read to and write
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 763) * from.
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 764) */
9927c6fa3e1d9 (Greg Kroah-Hartman 2019-10-16 06:03:32 -0700 765) void debugfs_create_atomic_t(const char *name, umode_t mode,
9927c6fa3e1d9 (Greg Kroah-Hartman 2019-10-16 06:03:32 -0700 766) struct dentry *parent, atomic_t *value)
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 767) {
9927c6fa3e1d9 (Greg Kroah-Hartman 2019-10-16 06:03:32 -0700 768) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_atomic_t,
9927c6fa3e1d9 (Greg Kroah-Hartman 2019-10-16 06:03:32 -0700 769) &fops_atomic_t_ro, &fops_atomic_t_wo);
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 770) }
3a76e5e09fbb5 (Seth Jennings 2013-06-03 15:33:02 -0500 771) EXPORT_SYMBOL_GPL(debugfs_create_atomic_t);
5e07878787ad0 (Inaky Perez-Gonzalez 2008-12-20 16:57:39 -0800 772)
0642ef6f2992e (Richard Fitzgerald 2015-06-23 14:32:54 +0100 773) ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf,
0642ef6f2992e (Richard Fitzgerald 2015-06-23 14:32:54 +0100 774) size_t count, loff_t *ppos)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 775) {
c8a9c285f136f (Rasmus Villemoes 2021-03-26 16:14:11 +0100 776) char buf[2];
4d45f7974ccf0 (Nicolai Stange 2016-03-22 14:11:18 +0100 777) bool val;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 778) int r;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 779) struct dentry *dentry = F_DENTRY(file);
4d45f7974ccf0 (Nicolai Stange 2016-03-22 14:11:18 +0100 780)
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 781) r = debugfs_file_get(dentry);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 782) if (unlikely(r))
4d45f7974ccf0 (Nicolai Stange 2016-03-22 14:11:18 +0100 783) return r;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 784) val = *(bool *)file->private_data;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 785) debugfs_file_put(dentry);
88e412ea5ebc3 (Rahul Bedarkar 2014-06-06 23:12:04 +0530 786)
4d45f7974ccf0 (Nicolai Stange 2016-03-22 14:11:18 +0100 787) if (val)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 788) buf[0] = 'Y';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 789) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 790) buf[0] = 'N';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 791) buf[1] = '\n';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 792) return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 793) }
0642ef6f2992e (Richard Fitzgerald 2015-06-23 14:32:54 +0100 794) EXPORT_SYMBOL_GPL(debugfs_read_file_bool);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 795)
0642ef6f2992e (Richard Fitzgerald 2015-06-23 14:32:54 +0100 796) ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf,
0642ef6f2992e (Richard Fitzgerald 2015-06-23 14:32:54 +0100 797) size_t count, loff_t *ppos)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 798) {
8705b48e71596 (Jonathan Cameron 2011-04-19 12:43:46 +0100 799) bool bv;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 800) int r;
621a5f7ad9cd1 (Viresh Kumar 2015-09-26 15:04:07 -0700 801) bool *val = file->private_data;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 802) struct dentry *dentry = F_DENTRY(file);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 803)
964f8363a1aba (Andy Shevchenko 2018-05-03 19:17:52 +0300 804) r = kstrtobool_from_user(user_buf, count, &bv);
964f8363a1aba (Andy Shevchenko 2018-05-03 19:17:52 +0300 805) if (!r) {
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 806) r = debugfs_file_get(dentry);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 807) if (unlikely(r))
4d45f7974ccf0 (Nicolai Stange 2016-03-22 14:11:18 +0100 808) return r;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 809) *val = bv;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 810) debugfs_file_put(dentry);
4d45f7974ccf0 (Nicolai Stange 2016-03-22 14:11:18 +0100 811) }
8705b48e71596 (Jonathan Cameron 2011-04-19 12:43:46 +0100 812)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 813) return count;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 814) }
0642ef6f2992e (Richard Fitzgerald 2015-06-23 14:32:54 +0100 815) EXPORT_SYMBOL_GPL(debugfs_write_file_bool);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 816)
4b6f5d20b04dc (Arjan van de Ven 2006-03-28 01:56:42 -0800 817) static const struct file_operations fops_bool = {
0642ef6f2992e (Richard Fitzgerald 2015-06-23 14:32:54 +0100 818) .read = debugfs_read_file_bool,
0642ef6f2992e (Richard Fitzgerald 2015-06-23 14:32:54 +0100 819) .write = debugfs_write_file_bool,
234e340582901 (Stephen Boyd 2012-04-05 14:25:11 -0700 820) .open = simple_open,
6038f373a3dc1 (Arnd Bergmann 2010-08-15 18:52:59 +0200 821) .llseek = default_llseek,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 822) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 823)
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 824) static const struct file_operations fops_bool_ro = {
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 825) .read = debugfs_read_file_bool,
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 826) .open = simple_open,
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 827) .llseek = default_llseek,
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 828) };
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 829)
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 830) static const struct file_operations fops_bool_wo = {
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 831) .write = debugfs_write_file_bool,
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 832) .open = simple_open,
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 833) .llseek = default_llseek,
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 834) };
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 835)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 836) /**
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 837) * debugfs_create_bool - create a debugfs file that is used to read and write a boolean value
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 838) * @name: a pointer to a string containing the name of the file to create.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 839) * @mode: the permission that the file should have
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 840) * @parent: a pointer to the parent dentry for this file. This should be a
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 841) * directory dentry if set. If this parameter is %NULL, then the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 842) * file will be created in the root of the debugfs filesystem.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 843) * @value: a pointer to the variable that the file should read to and write
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 844) * from.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 845) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 846) * This function creates a file in debugfs with the given name that
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 847) * contains the value of the variable @value. If the @mode variable is so
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 848) * set, it can be read from, and written to.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 849) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 850) * This function will return a pointer to a dentry if it succeeds. This
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 851) * pointer must be passed to the debugfs_remove() function when the file is
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 852) * to be removed (no automatic cleanup happens if your module is unloaded,
adc92dd4550ee (Daniel W. S. Almeida 2019-12-26 22:00:33 -0300 853) * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
9abb24990a2bf (Ronald Tschalär 2019-04-15 01:25:05 -0700 854) * returned.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 855) *
adc92dd4550ee (Daniel W. S. Almeida 2019-12-26 22:00:33 -0300 856) * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
9abb24990a2bf (Ronald Tschalär 2019-04-15 01:25:05 -0700 857) * be returned.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 858) */
f4ae40a6a50a9 (Al Viro 2011-07-24 04:33:43 -0400 859) struct dentry *debugfs_create_bool(const char *name, umode_t mode,
621a5f7ad9cd1 (Viresh Kumar 2015-09-26 15:04:07 -0700 860) struct dentry *parent, bool *value)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 861) {
4d45f7974ccf0 (Nicolai Stange 2016-03-22 14:11:18 +0100 862) return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_bool,
6713e8fb54165 (Stephen Boyd 2015-10-12 18:09:12 -0700 863) &fops_bool_ro, &fops_bool_wo);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 864) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 865) EXPORT_SYMBOL_GPL(debugfs_create_bool);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 866)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 867) ssize_t debugfs_read_file_str(struct file *file, char __user *user_buf,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 868) size_t count, loff_t *ppos)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 869) {
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 870) struct dentry *dentry = F_DENTRY(file);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 871) char *str, *copy = NULL;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 872) int copy_len, len;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 873) ssize_t ret;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 874)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 875) ret = debugfs_file_get(dentry);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 876) if (unlikely(ret))
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 877) return ret;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 878)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 879) str = *(char **)file->private_data;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 880) len = strlen(str) + 1;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 881) copy = kmalloc(len, GFP_KERNEL);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 882) if (!copy) {
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 883) debugfs_file_put(dentry);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 884) return -ENOMEM;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 885) }
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 886)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 887) copy_len = strscpy(copy, str, len);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 888) debugfs_file_put(dentry);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 889) if (copy_len < 0) {
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 890) kfree(copy);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 891) return copy_len;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 892) }
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 893)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 894) copy[copy_len] = '\n';
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 895)
f501b6a2312e2 (Dietmar Eggemann 2021-05-27 11:11:05 +0200 896) ret = simple_read_from_buffer(user_buf, count, ppos, copy, len);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 897) kfree(copy);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 898)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 899) return ret;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 900) }
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 901)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 902) static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 903) size_t count, loff_t *ppos)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 904) {
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 905) /* This is really only for read-only strings */
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 906) return -EINVAL;
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 907) }
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 908)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 909) static const struct file_operations fops_str = {
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 910) .read = debugfs_read_file_str,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 911) .write = debugfs_write_file_str,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 912) .open = simple_open,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 913) .llseek = default_llseek,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 914) };
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 915)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 916) static const struct file_operations fops_str_ro = {
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 917) .read = debugfs_read_file_str,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 918) .open = simple_open,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 919) .llseek = default_llseek,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 920) };
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 921)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 922) static const struct file_operations fops_str_wo = {
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 923) .write = debugfs_write_file_str,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 924) .open = simple_open,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 925) .llseek = default_llseek,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 926) };
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 927)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 928) /**
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 929) * debugfs_create_str - create a debugfs file that is used to read and write a string value
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 930) * @name: a pointer to a string containing the name of the file to create.
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 931) * @mode: the permission that the file should have
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 932) * @parent: a pointer to the parent dentry for this file. This should be a
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 933) * directory dentry if set. If this parameter is %NULL, then the
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 934) * file will be created in the root of the debugfs filesystem.
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 935) * @value: a pointer to the variable that the file should read to and write
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 936) * from.
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 937) *
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 938) * This function creates a file in debugfs with the given name that
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 939) * contains the value of the variable @value. If the @mode variable is so
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 940) * set, it can be read from, and written to.
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 941) *
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 942) * This function will return a pointer to a dentry if it succeeds. This
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 943) * pointer must be passed to the debugfs_remove() function when the file is
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 944) * to be removed (no automatic cleanup happens if your module is unloaded,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 945) * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 946) * returned.
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 947) *
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 948) * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 949) * be returned.
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 950) */
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 951) void debugfs_create_str(const char *name, umode_t mode,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 952) struct dentry *parent, char **value)
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 953) {
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 954) debugfs_create_mode_unsafe(name, mode, parent, value, &fops_str,
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 955) &fops_str_ro, &fops_str_wo);
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 956) }
9af0440ec86eb (Peter Zijlstra 2021-03-25 10:53:55 +0100 957)
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 958) static ssize_t read_file_blob(struct file *file, char __user *user_buf,
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 959) size_t count, loff_t *ppos)
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 960) {
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 961) struct debugfs_blob_wrapper *blob = file->private_data;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 962) struct dentry *dentry = F_DENTRY(file);
83b711cbf4ff4 (Nicolai Stange 2016-03-22 14:11:19 +0100 963) ssize_t r;
83b711cbf4ff4 (Nicolai Stange 2016-03-22 14:11:19 +0100 964)
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 965) r = debugfs_file_get(dentry);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 966) if (unlikely(r))
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 967) return r;
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 968) r = simple_read_from_buffer(user_buf, count, ppos, blob->data,
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 969) blob->size);
69d29f9e6a535 (Nicolai Stange 2017-10-31 00:15:50 +0100 970) debugfs_file_put(dentry);
83b711cbf4ff4 (Nicolai Stange 2016-03-22 14:11:19 +0100 971) return r;
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 972) }
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 973)
00977a59b9512 (Arjan van de Ven 2007-02-12 00:55:34 -0800 974) static const struct file_operations fops_blob = {
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 975) .read = read_file_blob,
234e340582901 (Stephen Boyd 2012-04-05 14:25:11 -0700 976) .open = simple_open,
6038f373a3dc1 (Arnd Bergmann 2010-08-15 18:52:59 +0200 977) .llseek = default_llseek,
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 978) };
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 979)
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 980) /**
400ced61fa491 (Jonathan Corbet 2009-05-25 10:15:27 -0600 981) * debugfs_create_blob - create a debugfs file that is used to read a binary blob
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 982) * @name: a pointer to a string containing the name of the file to create.
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 983) * @mode: the permission that the file should have
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 984) * @parent: a pointer to the parent dentry for this file. This should be a
6468b3afa7bcd (Randy Dunlap 2006-07-20 08:16:42 -0700 985) * directory dentry if set. If this parameter is %NULL, then the
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 986) * file will be created in the root of the debugfs filesystem.
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 987) * @blob: a pointer to a struct debugfs_blob_wrapper which contains a pointer
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 988) * to the blob data and the size of the data.
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 989) *
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 990) * This function creates a file in debugfs with the given name that exports
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 991) * @blob->data as a binary blob. If the @mode variable is so set it can be
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 992) * read from. Writing is not supported.
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 993) *
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 994) * This function will return a pointer to a dentry if it succeeds. This
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 995) * pointer must be passed to the debugfs_remove() function when the file is
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 996) * to be removed (no automatic cleanup happens if your module is unloaded,
adc92dd4550ee (Daniel W. S. Almeida 2019-12-26 22:00:33 -0300 997) * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
9abb24990a2bf (Ronald Tschalär 2019-04-15 01:25:05 -0700 998) * returned.
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 999) *
adc92dd4550ee (Daniel W. S. Almeida 2019-12-26 22:00:33 -0300 1000) * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
9abb24990a2bf (Ronald Tschalär 2019-04-15 01:25:05 -0700 1001) * be returned.
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 1002) */
f4ae40a6a50a9 (Al Viro 2011-07-24 04:33:43 -0400 1003) struct dentry *debugfs_create_blob(const char *name, umode_t mode,
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 1004) struct dentry *parent,
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 1005) struct debugfs_blob_wrapper *blob)
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 1006) {
83b711cbf4ff4 (Nicolai Stange 2016-03-22 14:11:19 +0100 1007) return debugfs_create_file_unsafe(name, mode, parent, blob, &fops_blob);
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 1008) }
dd308bc355a1a (Michael Ellerman 2006-03-07 21:41:59 +1100 1009) EXPORT_SYMBOL_GPL(debugfs_create_blob);
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1010)
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1011) static size_t u32_format_array(char *buf, size_t bufsize,
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1012) u32 *array, int array_size)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1013) {
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1014) size_t ret = 0;
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1015)
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1016) while (--array_size >= 0) {
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1017) size_t len;
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1018) char term = array_size ? ' ' : '\n';
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1019)
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1020) len = snprintf(buf, bufsize, "%u%c", *array++, term);
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1021) ret += len;
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1022)
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1023) buf += len;
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1024) bufsize -= len;
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1025) }
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1026) return ret;
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1027) }
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1028)
36048853c5257 (David Rientjes 2012-09-21 02:16:29 -0700 1029) static int u32_array_open(struct inode *inode, struct file *file)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1030) {
a2b992c828f76 (Jakub Kicinski 2020-07-09 17:42:44 -0700 1031) struct debugfs_u32_array *data = inode->i_private;
a2b992c828f76 (Jakub Kicinski 2020-07-09 17:42:44 -0700 1032) int size, elements = data->n_elements;
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1033) char *buf;
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1034)
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1035) /*
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1036) * Max size:
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1037) * - 10 digits + ' '/'\n' = 11 bytes per number
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1038) * - terminating NUL character
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1039) */
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1040) size = elements*11;
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1041) buf = kmalloc(size+1, GFP_KERNEL);
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1042) if (!buf)
36048853c5257 (David Rientjes 2012-09-21 02:16:29 -0700 1043) return -ENOMEM;
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1044) buf[size] = 0;
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1045)
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1046) file->private_data = buf;
a2b992c828f76 (Jakub Kicinski 2020-07-09 17:42:44 -0700 1047) u32_format_array(buf, size, data->array, data->n_elements);
e05e279e6fc94 (Linus Torvalds 2012-09-21 11:48:05 -0700 1048)
36048853c5257 (David Rientjes 2012-09-21 02:16:29 -0700 1049) return nonseekable_open(inode, file);
36048853c5257 (David Rientjes 2012-09-21 02:16:29 -0700 1050) }
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1051)
36048853c5257 (David Rientjes 2012-09-21 02:16:29 -0700 1052) static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
36048853c5257 (David Rientjes 2012-09-21 02:16:29 -0700 1053) loff_t *ppos)
36048853c5257 (David Rientjes 2012-09-21 02:16:29 -0700 1054) {
36048853c5257 (David Rientjes 2012-09-21 02:16:29 -0700 1055) size_t size = strlen(file->private_data);
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1056)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1057) return simple_read_from_buffer(buf, len, ppos,
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1058) file->private_data, size);
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1059) }
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1060)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1061) static int u32_array_release(struct inode *inode, struct file *file)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1062) {
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1063) kfree(file->private_data);
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1064)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1065) return 0;
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1066) }
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1067)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1068) static const struct file_operations u32_array_fops = {
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1069) .owner = THIS_MODULE,
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1070) .open = u32_array_open,
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1071) .release = u32_array_release,
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1072) .read = u32_array_read,
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1073) .llseek = no_llseek,
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1074) };
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1075)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1076) /**
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1077) * debugfs_create_u32_array - create a debugfs file that is used to read u32
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1078) * array.
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1079) * @name: a pointer to a string containing the name of the file to create.
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1080) * @mode: the permission that the file should have.
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1081) * @parent: a pointer to the parent dentry for this file. This should be a
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1082) * directory dentry if set. If this parameter is %NULL, then the
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1083) * file will be created in the root of the debugfs filesystem.
a2b992c828f76 (Jakub Kicinski 2020-07-09 17:42:44 -0700 1084) * @array: wrapper struct containing data pointer and size of the array.
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1085) *
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1086) * This function creates a file in debugfs with the given name that exports
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1087) * @array as data. If the @mode variable is so set it can be read from.
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1088) * Writing is not supported. Seek within the file is also not supported.
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1089) * Once array is created its size can not be changed.
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1090) */
c9c2c27d7ceca (Greg Kroah-Hartman 2019-04-16 15:46:55 +0200 1091) void debugfs_create_u32_array(const char *name, umode_t mode,
a2b992c828f76 (Jakub Kicinski 2020-07-09 17:42:44 -0700 1092) struct dentry *parent,
a2b992c828f76 (Jakub Kicinski 2020-07-09 17:42:44 -0700 1093) struct debugfs_u32_array *array)
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1094) {
a2b992c828f76 (Jakub Kicinski 2020-07-09 17:42:44 -0700 1095) debugfs_create_file_unsafe(name, mode, parent, array, &u32_array_fops);
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1096) }
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1097) EXPORT_SYMBOL_GPL(debugfs_create_u32_array);
9fe2a7015393d (Srivatsa Vaddagiri 2012-03-23 13:36:28 +0530 1098)
3b85e4ab2ec1d (Heiko Carstens 2011-12-27 15:08:28 +0100 1099) #ifdef CONFIG_HAS_IOMEM
3b85e4ab2ec1d (Heiko Carstens 2011-12-27 15:08:28 +0100 1100)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1101) /*
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1102) * The regset32 stuff is used to print 32-bit registers using the
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1103) * seq_file utilities. We offer printing a register set in an already-opened
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1104) * sequential file or create a debugfs file that only prints a regset32.
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1105) */
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1106)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1107) /**
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1108) * debugfs_print_regs32 - use seq_print to describe a set of registers
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1109) * @s: the seq_file structure being used to generate output
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1110) * @regs: an array if struct debugfs_reg32 structures
b5763accd3b5f (Randy Dunlap 2012-01-21 11:02:42 -0800 1111) * @nregs: the length of the above array
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1112) * @base: the base address to be used in reading the registers
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1113) * @prefix: a string to be prefixed to every output line
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1114) *
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1115) * This function outputs a text block describing the current values of
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1116) * some 32-bit hardware registers. It is meant to be used within debugfs
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1117) * files based on seq_file that need to show registers, intermixed with other
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1118) * information. The prefix argument may be used to specify a leading string,
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1119) * because some peripherals have several blocks of identical registers,
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1120) * for example configuration of dma channels
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1121) */
9761536e1d9e9 (Joe Perches 2014-09-29 16:08:26 -0700 1122) void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
9761536e1d9e9 (Joe Perches 2014-09-29 16:08:26 -0700 1123) int nregs, void __iomem *base, char *prefix)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1124) {
9761536e1d9e9 (Joe Perches 2014-09-29 16:08:26 -0700 1125) int i;
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1126)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1127) for (i = 0; i < nregs; i++, regs++) {
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1128) if (prefix)
9761536e1d9e9 (Joe Perches 2014-09-29 16:08:26 -0700 1129) seq_printf(s, "%s", prefix);
9761536e1d9e9 (Joe Perches 2014-09-29 16:08:26 -0700 1130) seq_printf(s, "%s = 0x%08x\n", regs->name,
9761536e1d9e9 (Joe Perches 2014-09-29 16:08:26 -0700 1131) readl(base + regs->offset));
9761536e1d9e9 (Joe Perches 2014-09-29 16:08:26 -0700 1132) if (seq_has_overflowed(s))
9761536e1d9e9 (Joe Perches 2014-09-29 16:08:26 -0700 1133) break;
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1134) }
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1135) }
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1136) EXPORT_SYMBOL_GPL(debugfs_print_regs32);
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1137)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1138) static int debugfs_show_regset32(struct seq_file *s, void *data)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1139) {
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1140) struct debugfs_regset32 *regset = s->private;
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1141)
30332eeefec8f (Geert Uytterhoeven 2020-02-11 19:18:55 +0100 1142) if (regset->dev)
30332eeefec8f (Geert Uytterhoeven 2020-02-11 19:18:55 +0100 1143) pm_runtime_get_sync(regset->dev);
30332eeefec8f (Geert Uytterhoeven 2020-02-11 19:18:55 +0100 1144)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1145) debugfs_print_regs32(s, regset->regs, regset->nregs, regset->base, "");
30332eeefec8f (Geert Uytterhoeven 2020-02-11 19:18:55 +0100 1146)
30332eeefec8f (Geert Uytterhoeven 2020-02-11 19:18:55 +0100 1147) if (regset->dev)
30332eeefec8f (Geert Uytterhoeven 2020-02-11 19:18:55 +0100 1148) pm_runtime_put(regset->dev);
30332eeefec8f (Geert Uytterhoeven 2020-02-11 19:18:55 +0100 1149)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1150) return 0;
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1151) }
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1152)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1153) static int debugfs_open_regset32(struct inode *inode, struct file *file)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1154) {
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1155) return single_open(file, debugfs_show_regset32, inode->i_private);
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1156) }
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1157)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1158) static const struct file_operations fops_regset32 = {
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1159) .open = debugfs_open_regset32,
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1160) .read = seq_read,
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1161) .llseek = seq_lseek,
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1162) .release = single_release,
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1163) };
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1164)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1165) /**
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1166) * debugfs_create_regset32 - create a debugfs file that returns register values
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1167) * @name: a pointer to a string containing the name of the file to create.
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1168) * @mode: the permission that the file should have
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1169) * @parent: a pointer to the parent dentry for this file. This should be a
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1170) * directory dentry if set. If this parameter is %NULL, then the
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1171) * file will be created in the root of the debugfs filesystem.
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1172) * @regset: a pointer to a struct debugfs_regset32, which contains a pointer
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1173) * to an array of register definitions, the array size and the base
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1174) * address where the register bank is to be found.
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1175) *
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1176) * This function creates a file in debugfs with the given name that reports
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1177) * the names and values of a set of 32-bit registers. If the @mode variable
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1178) * is so set it can be read from. Writing is not supported.
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1179) */
ae91c92565494 (Greg Kroah-Hartman 2019-11-22 11:44:53 +0100 1180) void debugfs_create_regset32(const char *name, umode_t mode,
ae91c92565494 (Greg Kroah-Hartman 2019-11-22 11:44:53 +0100 1181) struct dentry *parent,
ae91c92565494 (Greg Kroah-Hartman 2019-11-22 11:44:53 +0100 1182) struct debugfs_regset32 *regset)
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1183) {
ae91c92565494 (Greg Kroah-Hartman 2019-11-22 11:44:53 +0100 1184) debugfs_create_file(name, mode, parent, regset, &fops_regset32);
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1185) }
1a087c6ad975b (Alessandro Rubini 2011-11-18 14:50:21 +0100 1186) EXPORT_SYMBOL_GPL(debugfs_create_regset32);
3b85e4ab2ec1d (Heiko Carstens 2011-12-27 15:08:28 +0100 1187)
3b85e4ab2ec1d (Heiko Carstens 2011-12-27 15:08:28 +0100 1188) #endif /* CONFIG_HAS_IOMEM */
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1189)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1190) struct debugfs_devm_entry {
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1191) int (*read)(struct seq_file *seq, void *data);
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1192) struct device *dev;
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1193) };
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1194)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1195) static int debugfs_devm_entry_open(struct inode *inode, struct file *f)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1196) {
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1197) struct debugfs_devm_entry *entry = inode->i_private;
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1198)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1199) return single_open(f, entry->read, entry->dev);
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1200) }
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1201)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1202) static const struct file_operations debugfs_devm_entry_ops = {
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1203) .owner = THIS_MODULE,
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1204) .open = debugfs_devm_entry_open,
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1205) .release = single_release,
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1206) .read = seq_read,
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1207) .llseek = seq_lseek
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1208) };
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1209)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1210) /**
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1211) * debugfs_create_devm_seqfile - create a debugfs file that is bound to device.
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1212) *
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1213) * @dev: device related to this debugfs file.
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1214) * @name: name of the debugfs file.
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1215) * @parent: a pointer to the parent dentry for this file. This should be a
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1216) * directory dentry if set. If this parameter is %NULL, then the
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1217) * file will be created in the root of the debugfs filesystem.
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1218) * @read_fn: function pointer called to print the seq_file content.
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1219) */
0d519cbf38eed (Greg Kroah-Hartman 2020-10-23 15:10:37 +0200 1220) void debugfs_create_devm_seqfile(struct device *dev, const char *name,
0d519cbf38eed (Greg Kroah-Hartman 2020-10-23 15:10:37 +0200 1221) struct dentry *parent,
0d519cbf38eed (Greg Kroah-Hartman 2020-10-23 15:10:37 +0200 1222) int (*read_fn)(struct seq_file *s, void *data))
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1223) {
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1224) struct debugfs_devm_entry *entry;
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1225)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1226) if (IS_ERR(parent))
0d519cbf38eed (Greg Kroah-Hartman 2020-10-23 15:10:37 +0200 1227) return;
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1228)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1229) entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1230) if (!entry)
0d519cbf38eed (Greg Kroah-Hartman 2020-10-23 15:10:37 +0200 1231) return;
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1232)
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1233) entry->read = read_fn;
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1234) entry->dev = dev;
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1235)
0d519cbf38eed (Greg Kroah-Hartman 2020-10-23 15:10:37 +0200 1236) debugfs_create_file(name, S_IRUGO, parent, entry,
0d519cbf38eed (Greg Kroah-Hartman 2020-10-23 15:10:37 +0200 1237) &debugfs_devm_entry_ops);
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1238) }
98210b7f73f1d (Arend van Spriel 2014-11-09 11:31:58 +0100 1239) EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile);