VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
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);