xref: /linux-6.15/fs/debugfs/file.c (revision 98210b7f)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  file.c - part of debugfs, a tiny little debug file system
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (C) 2004 Greg Kroah-Hartman <[email protected]>
51da177e4SLinus Torvalds  *  Copyright (C) 2004 IBM Inc.
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *	This program is free software; you can redistribute it and/or
81da177e4SLinus Torvalds  *	modify it under the terms of the GNU General Public License version
91da177e4SLinus Torvalds  *	2 as published by the Free Software Foundation.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  *  debugfs is for people to use instead of /proc or /sys.
12883ce42eSRobert P. J. Day  *  See Documentation/DocBook/filesystems for more details.
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  */
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #include <linux/module.h>
171da177e4SLinus Torvalds #include <linux/fs.h>
181a087c6aSAlessandro Rubini #include <linux/seq_file.h>
191da177e4SLinus Torvalds #include <linux/pagemap.h>
2066f54963SPeter Oberparleiter #include <linux/namei.h>
211da177e4SLinus Torvalds #include <linux/debugfs.h>
2203e099fbSAlessandro Rubini #include <linux/io.h>
239fe2a701SSrivatsa Vaddagiri #include <linux/slab.h>
243a76e5e0SSeth Jennings #include <linux/atomic.h>
25*98210b7fSArend van Spriel #include <linux/device.h>
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds static ssize_t default_read_file(struct file *file, char __user *buf,
281da177e4SLinus Torvalds 				 size_t count, loff_t *ppos)
291da177e4SLinus Torvalds {
301da177e4SLinus Torvalds 	return 0;
311da177e4SLinus Torvalds }
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds static ssize_t default_write_file(struct file *file, const char __user *buf,
341da177e4SLinus Torvalds 				   size_t count, loff_t *ppos)
351da177e4SLinus Torvalds {
361da177e4SLinus Torvalds 	return count;
371da177e4SLinus Torvalds }
381da177e4SLinus Torvalds 
394b6f5d20SArjan van de Ven const struct file_operations debugfs_file_operations = {
401da177e4SLinus Torvalds 	.read =		default_read_file,
411da177e4SLinus Torvalds 	.write =	default_write_file,
42234e3405SStephen Boyd 	.open =		simple_open,
436038f373SArnd Bergmann 	.llseek =	noop_llseek,
441da177e4SLinus Torvalds };
451da177e4SLinus Torvalds 
4666f54963SPeter Oberparleiter static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
4766f54963SPeter Oberparleiter {
4866f54963SPeter Oberparleiter 	nd_set_link(nd, dentry->d_inode->i_private);
4966f54963SPeter Oberparleiter 	return NULL;
5066f54963SPeter Oberparleiter }
5166f54963SPeter Oberparleiter 
5266f54963SPeter Oberparleiter const struct inode_operations debugfs_link_operations = {
5366f54963SPeter Oberparleiter 	.readlink       = generic_readlink,
5466f54963SPeter Oberparleiter 	.follow_link    = debugfs_follow_link,
5566f54963SPeter Oberparleiter };
5666f54963SPeter Oberparleiter 
578b88b099SChristoph Hellwig static int debugfs_u8_set(void *data, u64 val)
58acaefc25SArnd Bergmann {
59acaefc25SArnd Bergmann 	*(u8 *)data = val;
608b88b099SChristoph Hellwig 	return 0;
61acaefc25SArnd Bergmann }
628b88b099SChristoph Hellwig static int debugfs_u8_get(void *data, u64 *val)
63acaefc25SArnd Bergmann {
648b88b099SChristoph Hellwig 	*val = *(u8 *)data;
658b88b099SChristoph Hellwig 	return 0;
66acaefc25SArnd Bergmann }
67acaefc25SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
68e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n");
69e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n");
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds /**
726468b3afSRandy Dunlap  * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value
731da177e4SLinus Torvalds  * @name: a pointer to a string containing the name of the file to create.
741da177e4SLinus Torvalds  * @mode: the permission that the file should have
751da177e4SLinus Torvalds  * @parent: a pointer to the parent dentry for this file.  This should be a
766468b3afSRandy Dunlap  *          directory dentry if set.  If this parameter is %NULL, then the
771da177e4SLinus Torvalds  *          file will be created in the root of the debugfs filesystem.
781da177e4SLinus Torvalds  * @value: a pointer to the variable that the file should read to and write
791da177e4SLinus Torvalds  *         from.
801da177e4SLinus Torvalds  *
811da177e4SLinus Torvalds  * This function creates a file in debugfs with the given name that
821da177e4SLinus Torvalds  * contains the value of the variable @value.  If the @mode variable is so
831da177e4SLinus Torvalds  * set, it can be read from, and written to.
841da177e4SLinus Torvalds  *
851da177e4SLinus Torvalds  * This function will return a pointer to a dentry if it succeeds.  This
861da177e4SLinus Torvalds  * pointer must be passed to the debugfs_remove() function when the file is
871da177e4SLinus Torvalds  * to be removed (no automatic cleanup happens if your module is unloaded,
886468b3afSRandy Dunlap  * you are responsible here.)  If an error occurs, %NULL will be returned.
891da177e4SLinus Torvalds  *
906468b3afSRandy Dunlap  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
911da177e4SLinus Torvalds  * returned.  It is not wise to check for this value, but rather, check for
926468b3afSRandy Dunlap  * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
931da177e4SLinus Torvalds  * code.
941da177e4SLinus Torvalds  */
95f4ae40a6SAl Viro struct dentry *debugfs_create_u8(const char *name, umode_t mode,
961da177e4SLinus Torvalds 				 struct dentry *parent, u8 *value)
971da177e4SLinus Torvalds {
98e4792aa3SRobin Getz 	/* if there are no write bits set, make read only */
99e4792aa3SRobin Getz 	if (!(mode & S_IWUGO))
100e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_u8_ro);
101e4792aa3SRobin Getz 	/* if there are no read bits set, make write only */
102e4792aa3SRobin Getz 	if (!(mode & S_IRUGO))
103e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_u8_wo);
104e4792aa3SRobin Getz 
1051da177e4SLinus Torvalds 	return debugfs_create_file(name, mode, parent, value, &fops_u8);
1061da177e4SLinus Torvalds }
1071da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u8);
1081da177e4SLinus Torvalds 
1098b88b099SChristoph Hellwig static int debugfs_u16_set(void *data, u64 val)
110acaefc25SArnd Bergmann {
111acaefc25SArnd Bergmann 	*(u16 *)data = val;
1128b88b099SChristoph Hellwig 	return 0;
113acaefc25SArnd Bergmann }
1148b88b099SChristoph Hellwig static int debugfs_u16_get(void *data, u64 *val)
115acaefc25SArnd Bergmann {
1168b88b099SChristoph Hellwig 	*val = *(u16 *)data;
1178b88b099SChristoph Hellwig 	return 0;
118acaefc25SArnd Bergmann }
119acaefc25SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
120e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n");
121e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n");
122acaefc25SArnd Bergmann 
1231da177e4SLinus Torvalds /**
1246468b3afSRandy Dunlap  * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value
1251da177e4SLinus Torvalds  * @name: a pointer to a string containing the name of the file to create.
1261da177e4SLinus Torvalds  * @mode: the permission that the file should have
1271da177e4SLinus Torvalds  * @parent: a pointer to the parent dentry for this file.  This should be a
1286468b3afSRandy Dunlap  *          directory dentry if set.  If this parameter is %NULL, then the
1291da177e4SLinus Torvalds  *          file will be created in the root of the debugfs filesystem.
1301da177e4SLinus Torvalds  * @value: a pointer to the variable that the file should read to and write
1311da177e4SLinus Torvalds  *         from.
1321da177e4SLinus Torvalds  *
1331da177e4SLinus Torvalds  * This function creates a file in debugfs with the given name that
1341da177e4SLinus Torvalds  * contains the value of the variable @value.  If the @mode variable is so
1351da177e4SLinus Torvalds  * set, it can be read from, and written to.
1361da177e4SLinus Torvalds  *
1371da177e4SLinus Torvalds  * This function will return a pointer to a dentry if it succeeds.  This
1381da177e4SLinus Torvalds  * pointer must be passed to the debugfs_remove() function when the file is
1391da177e4SLinus Torvalds  * to be removed (no automatic cleanup happens if your module is unloaded,
1406468b3afSRandy Dunlap  * you are responsible here.)  If an error occurs, %NULL will be returned.
1411da177e4SLinus Torvalds  *
1426468b3afSRandy Dunlap  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
1431da177e4SLinus Torvalds  * returned.  It is not wise to check for this value, but rather, check for
1446468b3afSRandy Dunlap  * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
1451da177e4SLinus Torvalds  * code.
1461da177e4SLinus Torvalds  */
147f4ae40a6SAl Viro struct dentry *debugfs_create_u16(const char *name, umode_t mode,
1481da177e4SLinus Torvalds 				  struct dentry *parent, u16 *value)
1491da177e4SLinus Torvalds {
150e4792aa3SRobin Getz 	/* if there are no write bits set, make read only */
151e4792aa3SRobin Getz 	if (!(mode & S_IWUGO))
152e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_u16_ro);
153e4792aa3SRobin Getz 	/* if there are no read bits set, make write only */
154e4792aa3SRobin Getz 	if (!(mode & S_IRUGO))
155e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_u16_wo);
156e4792aa3SRobin Getz 
1571da177e4SLinus Torvalds 	return debugfs_create_file(name, mode, parent, value, &fops_u16);
1581da177e4SLinus Torvalds }
1591da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u16);
1601da177e4SLinus Torvalds 
1618b88b099SChristoph Hellwig static int debugfs_u32_set(void *data, u64 val)
162acaefc25SArnd Bergmann {
163acaefc25SArnd Bergmann 	*(u32 *)data = val;
1648b88b099SChristoph Hellwig 	return 0;
165acaefc25SArnd Bergmann }
1668b88b099SChristoph Hellwig static int debugfs_u32_get(void *data, u64 *val)
167acaefc25SArnd Bergmann {
1688b88b099SChristoph Hellwig 	*val = *(u32 *)data;
1698b88b099SChristoph Hellwig 	return 0;
170acaefc25SArnd Bergmann }
171acaefc25SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
172e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n");
173e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n");
174acaefc25SArnd Bergmann 
1751da177e4SLinus Torvalds /**
1766468b3afSRandy Dunlap  * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value
1771da177e4SLinus Torvalds  * @name: a pointer to a string containing the name of the file to create.
1781da177e4SLinus Torvalds  * @mode: the permission that the file should have
1791da177e4SLinus Torvalds  * @parent: a pointer to the parent dentry for this file.  This should be a
1806468b3afSRandy Dunlap  *          directory dentry if set.  If this parameter is %NULL, then the
1811da177e4SLinus Torvalds  *          file will be created in the root of the debugfs filesystem.
1821da177e4SLinus Torvalds  * @value: a pointer to the variable that the file should read to and write
1831da177e4SLinus Torvalds  *         from.
1841da177e4SLinus Torvalds  *
1851da177e4SLinus Torvalds  * This function creates a file in debugfs with the given name that
1861da177e4SLinus Torvalds  * contains the value of the variable @value.  If the @mode variable is so
1871da177e4SLinus Torvalds  * set, it can be read from, and written to.
1881da177e4SLinus Torvalds  *
1891da177e4SLinus Torvalds  * This function will return a pointer to a dentry if it succeeds.  This
1901da177e4SLinus Torvalds  * pointer must be passed to the debugfs_remove() function when the file is
1911da177e4SLinus Torvalds  * to be removed (no automatic cleanup happens if your module is unloaded,
1926468b3afSRandy Dunlap  * you are responsible here.)  If an error occurs, %NULL will be returned.
1931da177e4SLinus Torvalds  *
1946468b3afSRandy Dunlap  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
1951da177e4SLinus Torvalds  * returned.  It is not wise to check for this value, but rather, check for
1966468b3afSRandy Dunlap  * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
1971da177e4SLinus Torvalds  * code.
1981da177e4SLinus Torvalds  */
199f4ae40a6SAl Viro struct dentry *debugfs_create_u32(const char *name, umode_t mode,
2001da177e4SLinus Torvalds 				 struct dentry *parent, u32 *value)
2011da177e4SLinus Torvalds {
202e4792aa3SRobin Getz 	/* if there are no write bits set, make read only */
203e4792aa3SRobin Getz 	if (!(mode & S_IWUGO))
204e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_u32_ro);
205e4792aa3SRobin Getz 	/* if there are no read bits set, make write only */
206e4792aa3SRobin Getz 	if (!(mode & S_IRUGO))
207e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_u32_wo);
208e4792aa3SRobin Getz 
2091da177e4SLinus Torvalds 	return debugfs_create_file(name, mode, parent, value, &fops_u32);
2101da177e4SLinus Torvalds }
2111da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u32);
2121da177e4SLinus Torvalds 
2138b88b099SChristoph Hellwig static int debugfs_u64_set(void *data, u64 val)
2148447891fSMichael Ellerman {
2158447891fSMichael Ellerman 	*(u64 *)data = val;
2168b88b099SChristoph Hellwig 	return 0;
2178447891fSMichael Ellerman }
2188447891fSMichael Ellerman 
2198b88b099SChristoph Hellwig static int debugfs_u64_get(void *data, u64 *val)
2208447891fSMichael Ellerman {
2218b88b099SChristoph Hellwig 	*val = *(u64 *)data;
2228b88b099SChristoph Hellwig 	return 0;
2238447891fSMichael Ellerman }
2248447891fSMichael Ellerman DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n");
225e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n");
226e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n");
2278447891fSMichael Ellerman 
2288447891fSMichael Ellerman /**
2298447891fSMichael Ellerman  * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value
2308447891fSMichael Ellerman  * @name: a pointer to a string containing the name of the file to create.
2318447891fSMichael Ellerman  * @mode: the permission that the file should have
2328447891fSMichael Ellerman  * @parent: a pointer to the parent dentry for this file.  This should be a
2338447891fSMichael Ellerman  *          directory dentry if set.  If this parameter is %NULL, then the
2348447891fSMichael Ellerman  *          file will be created in the root of the debugfs filesystem.
2358447891fSMichael Ellerman  * @value: a pointer to the variable that the file should read to and write
2368447891fSMichael Ellerman  *         from.
2378447891fSMichael Ellerman  *
2388447891fSMichael Ellerman  * This function creates a file in debugfs with the given name that
2398447891fSMichael Ellerman  * contains the value of the variable @value.  If the @mode variable is so
2408447891fSMichael Ellerman  * set, it can be read from, and written to.
2418447891fSMichael Ellerman  *
2428447891fSMichael Ellerman  * This function will return a pointer to a dentry if it succeeds.  This
2438447891fSMichael Ellerman  * pointer must be passed to the debugfs_remove() function when the file is
2448447891fSMichael Ellerman  * to be removed (no automatic cleanup happens if your module is unloaded,
2458447891fSMichael Ellerman  * you are responsible here.)  If an error occurs, %NULL will be returned.
2468447891fSMichael Ellerman  *
2478447891fSMichael Ellerman  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
2488447891fSMichael Ellerman  * returned.  It is not wise to check for this value, but rather, check for
2498447891fSMichael Ellerman  * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
2508447891fSMichael Ellerman  * code.
2518447891fSMichael Ellerman  */
252f4ae40a6SAl Viro struct dentry *debugfs_create_u64(const char *name, umode_t mode,
2538447891fSMichael Ellerman 				 struct dentry *parent, u64 *value)
2548447891fSMichael Ellerman {
255e4792aa3SRobin Getz 	/* if there are no write bits set, make read only */
256e4792aa3SRobin Getz 	if (!(mode & S_IWUGO))
257e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_u64_ro);
258e4792aa3SRobin Getz 	/* if there are no read bits set, make write only */
259e4792aa3SRobin Getz 	if (!(mode & S_IRUGO))
260e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_u64_wo);
261e4792aa3SRobin Getz 
2628447891fSMichael Ellerman 	return debugfs_create_file(name, mode, parent, value, &fops_u64);
2638447891fSMichael Ellerman }
2648447891fSMichael Ellerman EXPORT_SYMBOL_GPL(debugfs_create_u64);
2658447891fSMichael Ellerman 
2662ebefc50SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n");
267e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n");
268e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n");
2692ebefc50SRobin Getz 
2702ebefc50SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n");
271e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n");
272e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n");
2732ebefc50SRobin Getz 
2742ebefc50SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n");
275e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n");
276e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n");
2772ebefc50SRobin Getz 
27815b0beaaSHuang Ying DEFINE_SIMPLE_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, "0x%016llx\n");
27915b0beaaSHuang Ying 
280e6716b87SRandy Dunlap /*
28115b0beaaSHuang Ying  * 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
282e6716b87SRandy Dunlap  *
283e6716b87SRandy Dunlap  * These functions are exactly the same as the above functions (but use a hex
284e6716b87SRandy Dunlap  * output for the decimal challenged). For details look at the above unsigned
285e6716b87SRandy Dunlap  * decimal functions.
286e6716b87SRandy Dunlap  */
287e6716b87SRandy Dunlap 
2882ebefc50SRobin Getz /**
2892ebefc50SRobin Getz  * debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8-bit value
290e6716b87SRandy Dunlap  * @name: a pointer to a string containing the name of the file to create.
291e6716b87SRandy Dunlap  * @mode: the permission that the file should have
292e6716b87SRandy Dunlap  * @parent: a pointer to the parent dentry for this file.  This should be a
293e6716b87SRandy Dunlap  *          directory dentry if set.  If this parameter is %NULL, then the
294e6716b87SRandy Dunlap  *          file will be created in the root of the debugfs filesystem.
295e6716b87SRandy Dunlap  * @value: a pointer to the variable that the file should read to and write
296e6716b87SRandy Dunlap  *         from.
2972ebefc50SRobin Getz  */
298f4ae40a6SAl Viro struct dentry *debugfs_create_x8(const char *name, umode_t mode,
2992ebefc50SRobin Getz 				 struct dentry *parent, u8 *value)
3002ebefc50SRobin Getz {
301e4792aa3SRobin Getz 	/* if there are no write bits set, make read only */
302e4792aa3SRobin Getz 	if (!(mode & S_IWUGO))
303e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_x8_ro);
304e4792aa3SRobin Getz 	/* if there are no read bits set, make write only */
305e4792aa3SRobin Getz 	if (!(mode & S_IRUGO))
306e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_x8_wo);
307e4792aa3SRobin Getz 
3082ebefc50SRobin Getz 	return debugfs_create_file(name, mode, parent, value, &fops_x8);
3092ebefc50SRobin Getz }
3102ebefc50SRobin Getz EXPORT_SYMBOL_GPL(debugfs_create_x8);
3112ebefc50SRobin Getz 
312e6716b87SRandy Dunlap /**
313e6716b87SRandy Dunlap  * debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16-bit value
314e6716b87SRandy Dunlap  * @name: a pointer to a string containing the name of the file to create.
315e6716b87SRandy Dunlap  * @mode: the permission that the file should have
316e6716b87SRandy Dunlap  * @parent: a pointer to the parent dentry for this file.  This should be a
317e6716b87SRandy Dunlap  *          directory dentry if set.  If this parameter is %NULL, then the
318e6716b87SRandy Dunlap  *          file will be created in the root of the debugfs filesystem.
319e6716b87SRandy Dunlap  * @value: a pointer to the variable that the file should read to and write
320e6716b87SRandy Dunlap  *         from.
321e6716b87SRandy Dunlap  */
322f4ae40a6SAl Viro struct dentry *debugfs_create_x16(const char *name, umode_t mode,
3232ebefc50SRobin Getz 				 struct dentry *parent, u16 *value)
3242ebefc50SRobin Getz {
325e4792aa3SRobin Getz 	/* if there are no write bits set, make read only */
326e4792aa3SRobin Getz 	if (!(mode & S_IWUGO))
327e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_x16_ro);
328e4792aa3SRobin Getz 	/* if there are no read bits set, make write only */
329e4792aa3SRobin Getz 	if (!(mode & S_IRUGO))
330e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_x16_wo);
331e4792aa3SRobin Getz 
3322ebefc50SRobin Getz 	return debugfs_create_file(name, mode, parent, value, &fops_x16);
3332ebefc50SRobin Getz }
3342ebefc50SRobin Getz EXPORT_SYMBOL_GPL(debugfs_create_x16);
3352ebefc50SRobin Getz 
336e6716b87SRandy Dunlap /**
337e6716b87SRandy Dunlap  * debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32-bit value
338e6716b87SRandy Dunlap  * @name: a pointer to a string containing the name of the file to create.
339e6716b87SRandy Dunlap  * @mode: the permission that the file should have
340e6716b87SRandy Dunlap  * @parent: a pointer to the parent dentry for this file.  This should be a
341e6716b87SRandy Dunlap  *          directory dentry if set.  If this parameter is %NULL, then the
342e6716b87SRandy Dunlap  *          file will be created in the root of the debugfs filesystem.
343e6716b87SRandy Dunlap  * @value: a pointer to the variable that the file should read to and write
344e6716b87SRandy Dunlap  *         from.
345e6716b87SRandy Dunlap  */
346f4ae40a6SAl Viro struct dentry *debugfs_create_x32(const char *name, umode_t mode,
3472ebefc50SRobin Getz 				 struct dentry *parent, u32 *value)
3482ebefc50SRobin Getz {
349e4792aa3SRobin Getz 	/* if there are no write bits set, make read only */
350e4792aa3SRobin Getz 	if (!(mode & S_IWUGO))
351e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_x32_ro);
352e4792aa3SRobin Getz 	/* if there are no read bits set, make write only */
353e4792aa3SRobin Getz 	if (!(mode & S_IRUGO))
354e4792aa3SRobin Getz 		return debugfs_create_file(name, mode, parent, value, &fops_x32_wo);
355e4792aa3SRobin Getz 
3562ebefc50SRobin Getz 	return debugfs_create_file(name, mode, parent, value, &fops_x32);
3572ebefc50SRobin Getz }
3582ebefc50SRobin Getz EXPORT_SYMBOL_GPL(debugfs_create_x32);
3592ebefc50SRobin Getz 
36015b0beaaSHuang Ying /**
36115b0beaaSHuang Ying  * debugfs_create_x64 - create a debugfs file that is used to read and write an unsigned 64-bit value
36215b0beaaSHuang Ying  * @name: a pointer to a string containing the name of the file to create.
36315b0beaaSHuang Ying  * @mode: the permission that the file should have
36415b0beaaSHuang Ying  * @parent: a pointer to the parent dentry for this file.  This should be a
36515b0beaaSHuang Ying  *          directory dentry if set.  If this parameter is %NULL, then the
36615b0beaaSHuang Ying  *          file will be created in the root of the debugfs filesystem.
36715b0beaaSHuang Ying  * @value: a pointer to the variable that the file should read to and write
36815b0beaaSHuang Ying  *         from.
36915b0beaaSHuang Ying  */
370f4ae40a6SAl Viro struct dentry *debugfs_create_x64(const char *name, umode_t mode,
37115b0beaaSHuang Ying 				 struct dentry *parent, u64 *value)
37215b0beaaSHuang Ying {
37315b0beaaSHuang Ying 	return debugfs_create_file(name, mode, parent, value, &fops_x64);
37415b0beaaSHuang Ying }
37515b0beaaSHuang Ying EXPORT_SYMBOL_GPL(debugfs_create_x64);
37615b0beaaSHuang Ying 
3775e078787SInaky Perez-Gonzalez 
3785e078787SInaky Perez-Gonzalez static int debugfs_size_t_set(void *data, u64 val)
3795e078787SInaky Perez-Gonzalez {
3805e078787SInaky Perez-Gonzalez 	*(size_t *)data = val;
3815e078787SInaky Perez-Gonzalez 	return 0;
3825e078787SInaky Perez-Gonzalez }
3835e078787SInaky Perez-Gonzalez static int debugfs_size_t_get(void *data, u64 *val)
3845e078787SInaky Perez-Gonzalez {
3855e078787SInaky Perez-Gonzalez 	*val = *(size_t *)data;
3865e078787SInaky Perez-Gonzalez 	return 0;
3875e078787SInaky Perez-Gonzalez }
3885e078787SInaky Perez-Gonzalez DEFINE_SIMPLE_ATTRIBUTE(fops_size_t, debugfs_size_t_get, debugfs_size_t_set,
3895e078787SInaky Perez-Gonzalez 			"%llu\n");	/* %llu and %zu are more or less the same */
3905e078787SInaky Perez-Gonzalez 
3915e078787SInaky Perez-Gonzalez /**
3925e078787SInaky Perez-Gonzalez  * debugfs_create_size_t - create a debugfs file that is used to read and write an size_t value
3935e078787SInaky Perez-Gonzalez  * @name: a pointer to a string containing the name of the file to create.
3945e078787SInaky Perez-Gonzalez  * @mode: the permission that the file should have
3955e078787SInaky Perez-Gonzalez  * @parent: a pointer to the parent dentry for this file.  This should be a
3965e078787SInaky Perez-Gonzalez  *          directory dentry if set.  If this parameter is %NULL, then the
3975e078787SInaky Perez-Gonzalez  *          file will be created in the root of the debugfs filesystem.
3985e078787SInaky Perez-Gonzalez  * @value: a pointer to the variable that the file should read to and write
3995e078787SInaky Perez-Gonzalez  *         from.
4005e078787SInaky Perez-Gonzalez  */
401f4ae40a6SAl Viro struct dentry *debugfs_create_size_t(const char *name, umode_t mode,
4025e078787SInaky Perez-Gonzalez 				     struct dentry *parent, size_t *value)
4035e078787SInaky Perez-Gonzalez {
4045e078787SInaky Perez-Gonzalez 	return debugfs_create_file(name, mode, parent, value, &fops_size_t);
4055e078787SInaky Perez-Gonzalez }
4065e078787SInaky Perez-Gonzalez EXPORT_SYMBOL_GPL(debugfs_create_size_t);
4075e078787SInaky Perez-Gonzalez 
4083a76e5e0SSeth Jennings static int debugfs_atomic_t_set(void *data, u64 val)
4093a76e5e0SSeth Jennings {
4103a76e5e0SSeth Jennings 	atomic_set((atomic_t *)data, val);
4113a76e5e0SSeth Jennings 	return 0;
4123a76e5e0SSeth Jennings }
4133a76e5e0SSeth Jennings static int debugfs_atomic_t_get(void *data, u64 *val)
4143a76e5e0SSeth Jennings {
4153a76e5e0SSeth Jennings 	*val = atomic_read((atomic_t *)data);
4163a76e5e0SSeth Jennings 	return 0;
4173a76e5e0SSeth Jennings }
4183a76e5e0SSeth Jennings DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get,
4193a76e5e0SSeth Jennings 			debugfs_atomic_t_set, "%lld\n");
4203a76e5e0SSeth Jennings DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, "%lld\n");
4213a76e5e0SSeth Jennings DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%lld\n");
4223a76e5e0SSeth Jennings 
4233a76e5e0SSeth Jennings /**
4243a76e5e0SSeth Jennings  * debugfs_create_atomic_t - create a debugfs file that is used to read and
4253a76e5e0SSeth Jennings  * write an atomic_t value
4263a76e5e0SSeth Jennings  * @name: a pointer to a string containing the name of the file to create.
4273a76e5e0SSeth Jennings  * @mode: the permission that the file should have
4283a76e5e0SSeth Jennings  * @parent: a pointer to the parent dentry for this file.  This should be a
4293a76e5e0SSeth Jennings  *          directory dentry if set.  If this parameter is %NULL, then the
4303a76e5e0SSeth Jennings  *          file will be created in the root of the debugfs filesystem.
4313a76e5e0SSeth Jennings  * @value: a pointer to the variable that the file should read to and write
4323a76e5e0SSeth Jennings  *         from.
4333a76e5e0SSeth Jennings  */
4343a76e5e0SSeth Jennings struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode,
4353a76e5e0SSeth Jennings 				 struct dentry *parent, atomic_t *value)
4363a76e5e0SSeth Jennings {
4373a76e5e0SSeth Jennings 	/* if there are no write bits set, make read only */
4383a76e5e0SSeth Jennings 	if (!(mode & S_IWUGO))
4393a76e5e0SSeth Jennings 		return debugfs_create_file(name, mode, parent, value,
4403a76e5e0SSeth Jennings 					&fops_atomic_t_ro);
4413a76e5e0SSeth Jennings 	/* if there are no read bits set, make write only */
4423a76e5e0SSeth Jennings 	if (!(mode & S_IRUGO))
4433a76e5e0SSeth Jennings 		return debugfs_create_file(name, mode, parent, value,
4443a76e5e0SSeth Jennings 					&fops_atomic_t_wo);
4453a76e5e0SSeth Jennings 
4463a76e5e0SSeth Jennings 	return debugfs_create_file(name, mode, parent, value, &fops_atomic_t);
4473a76e5e0SSeth Jennings }
4483a76e5e0SSeth Jennings EXPORT_SYMBOL_GPL(debugfs_create_atomic_t);
4495e078787SInaky Perez-Gonzalez 
4501da177e4SLinus Torvalds static ssize_t read_file_bool(struct file *file, char __user *user_buf,
4511da177e4SLinus Torvalds 			      size_t count, loff_t *ppos)
4521da177e4SLinus Torvalds {
4531da177e4SLinus Torvalds 	char buf[3];
4541da177e4SLinus Torvalds 	u32 *val = file->private_data;
4551da177e4SLinus Torvalds 
4561da177e4SLinus Torvalds 	if (*val)
4571da177e4SLinus Torvalds 		buf[0] = 'Y';
4581da177e4SLinus Torvalds 	else
4591da177e4SLinus Torvalds 		buf[0] = 'N';
4601da177e4SLinus Torvalds 	buf[1] = '\n';
4611da177e4SLinus Torvalds 	buf[2] = 0x00;
4621da177e4SLinus Torvalds 	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
4631da177e4SLinus Torvalds }
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
4661da177e4SLinus Torvalds 			       size_t count, loff_t *ppos)
4671da177e4SLinus Torvalds {
4681da177e4SLinus Torvalds 	char buf[32];
469c42d2237SStephen Boyd 	size_t buf_size;
4708705b48eSJonathan Cameron 	bool bv;
4711da177e4SLinus Torvalds 	u32 *val = file->private_data;
4721da177e4SLinus Torvalds 
4731da177e4SLinus Torvalds 	buf_size = min(count, (sizeof(buf)-1));
4741da177e4SLinus Torvalds 	if (copy_from_user(buf, user_buf, buf_size))
4751da177e4SLinus Torvalds 		return -EFAULT;
4761da177e4SLinus Torvalds 
477a3b2c8c7SMathias Krause 	buf[buf_size] = '\0';
4788705b48eSJonathan Cameron 	if (strtobool(buf, &bv) == 0)
4798705b48eSJonathan Cameron 		*val = bv;
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds 	return count;
4821da177e4SLinus Torvalds }
4831da177e4SLinus Torvalds 
4844b6f5d20SArjan van de Ven static const struct file_operations fops_bool = {
4851da177e4SLinus Torvalds 	.read =		read_file_bool,
4861da177e4SLinus Torvalds 	.write =	write_file_bool,
487234e3405SStephen Boyd 	.open =		simple_open,
4886038f373SArnd Bergmann 	.llseek =	default_llseek,
4891da177e4SLinus Torvalds };
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds /**
4926468b3afSRandy Dunlap  * debugfs_create_bool - create a debugfs file that is used to read and write a boolean value
4931da177e4SLinus Torvalds  * @name: a pointer to a string containing the name of the file to create.
4941da177e4SLinus Torvalds  * @mode: the permission that the file should have
4951da177e4SLinus Torvalds  * @parent: a pointer to the parent dentry for this file.  This should be a
4966468b3afSRandy Dunlap  *          directory dentry if set.  If this parameter is %NULL, then the
4971da177e4SLinus Torvalds  *          file will be created in the root of the debugfs filesystem.
4981da177e4SLinus Torvalds  * @value: a pointer to the variable that the file should read to and write
4991da177e4SLinus Torvalds  *         from.
5001da177e4SLinus Torvalds  *
5011da177e4SLinus Torvalds  * This function creates a file in debugfs with the given name that
5021da177e4SLinus Torvalds  * contains the value of the variable @value.  If the @mode variable is so
5031da177e4SLinus Torvalds  * set, it can be read from, and written to.
5041da177e4SLinus Torvalds  *
5051da177e4SLinus Torvalds  * This function will return a pointer to a dentry if it succeeds.  This
5061da177e4SLinus Torvalds  * pointer must be passed to the debugfs_remove() function when the file is
5071da177e4SLinus Torvalds  * to be removed (no automatic cleanup happens if your module is unloaded,
5086468b3afSRandy Dunlap  * you are responsible here.)  If an error occurs, %NULL will be returned.
5091da177e4SLinus Torvalds  *
5106468b3afSRandy Dunlap  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
5111da177e4SLinus Torvalds  * returned.  It is not wise to check for this value, but rather, check for
5126468b3afSRandy Dunlap  * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
5131da177e4SLinus Torvalds  * code.
5141da177e4SLinus Torvalds  */
515f4ae40a6SAl Viro struct dentry *debugfs_create_bool(const char *name, umode_t mode,
5161da177e4SLinus Torvalds 				   struct dentry *parent, u32 *value)
5171da177e4SLinus Torvalds {
5181da177e4SLinus Torvalds 	return debugfs_create_file(name, mode, parent, value, &fops_bool);
5191da177e4SLinus Torvalds }
5201da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_bool);
5211da177e4SLinus Torvalds 
522dd308bc3SMichael Ellerman static ssize_t read_file_blob(struct file *file, char __user *user_buf,
523dd308bc3SMichael Ellerman 			      size_t count, loff_t *ppos)
524dd308bc3SMichael Ellerman {
525dd308bc3SMichael Ellerman 	struct debugfs_blob_wrapper *blob = file->private_data;
526dd308bc3SMichael Ellerman 	return simple_read_from_buffer(user_buf, count, ppos, blob->data,
527dd308bc3SMichael Ellerman 			blob->size);
528dd308bc3SMichael Ellerman }
529dd308bc3SMichael Ellerman 
53000977a59SArjan van de Ven static const struct file_operations fops_blob = {
531dd308bc3SMichael Ellerman 	.read =		read_file_blob,
532234e3405SStephen Boyd 	.open =		simple_open,
5336038f373SArnd Bergmann 	.llseek =	default_llseek,
534dd308bc3SMichael Ellerman };
535dd308bc3SMichael Ellerman 
536dd308bc3SMichael Ellerman /**
537400ced61SJonathan Corbet  * debugfs_create_blob - create a debugfs file that is used to read a binary blob
538dd308bc3SMichael Ellerman  * @name: a pointer to a string containing the name of the file to create.
539dd308bc3SMichael Ellerman  * @mode: the permission that the file should have
540dd308bc3SMichael Ellerman  * @parent: a pointer to the parent dentry for this file.  This should be a
5416468b3afSRandy Dunlap  *          directory dentry if set.  If this parameter is %NULL, then the
542dd308bc3SMichael Ellerman  *          file will be created in the root of the debugfs filesystem.
543dd308bc3SMichael Ellerman  * @blob: a pointer to a struct debugfs_blob_wrapper which contains a pointer
544dd308bc3SMichael Ellerman  *        to the blob data and the size of the data.
545dd308bc3SMichael Ellerman  *
546dd308bc3SMichael Ellerman  * This function creates a file in debugfs with the given name that exports
547dd308bc3SMichael Ellerman  * @blob->data as a binary blob. If the @mode variable is so set it can be
548dd308bc3SMichael Ellerman  * read from. Writing is not supported.
549dd308bc3SMichael Ellerman  *
550dd308bc3SMichael Ellerman  * This function will return a pointer to a dentry if it succeeds.  This
551dd308bc3SMichael Ellerman  * pointer must be passed to the debugfs_remove() function when the file is
552dd308bc3SMichael Ellerman  * to be removed (no automatic cleanup happens if your module is unloaded,
5536468b3afSRandy Dunlap  * you are responsible here.)  If an error occurs, %NULL will be returned.
554dd308bc3SMichael Ellerman  *
5556468b3afSRandy Dunlap  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
556dd308bc3SMichael Ellerman  * returned.  It is not wise to check for this value, but rather, check for
5576468b3afSRandy Dunlap  * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
558dd308bc3SMichael Ellerman  * code.
559dd308bc3SMichael Ellerman  */
560f4ae40a6SAl Viro struct dentry *debugfs_create_blob(const char *name, umode_t mode,
561dd308bc3SMichael Ellerman 				   struct dentry *parent,
562dd308bc3SMichael Ellerman 				   struct debugfs_blob_wrapper *blob)
563dd308bc3SMichael Ellerman {
564dd308bc3SMichael Ellerman 	return debugfs_create_file(name, mode, parent, blob, &fops_blob);
565dd308bc3SMichael Ellerman }
566dd308bc3SMichael Ellerman EXPORT_SYMBOL_GPL(debugfs_create_blob);
5671a087c6aSAlessandro Rubini 
5689fe2a701SSrivatsa Vaddagiri struct array_data {
5699fe2a701SSrivatsa Vaddagiri 	void *array;
5709fe2a701SSrivatsa Vaddagiri 	u32 elements;
5719fe2a701SSrivatsa Vaddagiri };
5729fe2a701SSrivatsa Vaddagiri 
573e05e279eSLinus Torvalds static size_t u32_format_array(char *buf, size_t bufsize,
574e05e279eSLinus Torvalds 			       u32 *array, int array_size)
5759fe2a701SSrivatsa Vaddagiri {
5769fe2a701SSrivatsa Vaddagiri 	size_t ret = 0;
5779fe2a701SSrivatsa Vaddagiri 
578e05e279eSLinus Torvalds 	while (--array_size >= 0) {
5799fe2a701SSrivatsa Vaddagiri 		size_t len;
580e05e279eSLinus Torvalds 		char term = array_size ? ' ' : '\n';
5819fe2a701SSrivatsa Vaddagiri 
582e05e279eSLinus Torvalds 		len = snprintf(buf, bufsize, "%u%c", *array++, term);
5839fe2a701SSrivatsa Vaddagiri 		ret += len;
5849fe2a701SSrivatsa Vaddagiri 
5859fe2a701SSrivatsa Vaddagiri 		buf += len;
5869fe2a701SSrivatsa Vaddagiri 		bufsize -= len;
5879fe2a701SSrivatsa Vaddagiri 	}
5889fe2a701SSrivatsa Vaddagiri 	return ret;
5899fe2a701SSrivatsa Vaddagiri }
5909fe2a701SSrivatsa Vaddagiri 
59136048853SDavid Rientjes static int u32_array_open(struct inode *inode, struct file *file)
5929fe2a701SSrivatsa Vaddagiri {
5939fe2a701SSrivatsa Vaddagiri 	struct array_data *data = inode->i_private;
594e05e279eSLinus Torvalds 	int size, elements = data->elements;
595e05e279eSLinus Torvalds 	char *buf;
5969fe2a701SSrivatsa Vaddagiri 
597e05e279eSLinus Torvalds 	/*
598e05e279eSLinus Torvalds 	 * Max size:
599e05e279eSLinus Torvalds 	 *  - 10 digits + ' '/'\n' = 11 bytes per number
600e05e279eSLinus Torvalds 	 *  - terminating NUL character
601e05e279eSLinus Torvalds 	 */
602e05e279eSLinus Torvalds 	size = elements*11;
603e05e279eSLinus Torvalds 	buf = kmalloc(size+1, GFP_KERNEL);
604e05e279eSLinus Torvalds 	if (!buf)
60536048853SDavid Rientjes 		return -ENOMEM;
606e05e279eSLinus Torvalds 	buf[size] = 0;
607e05e279eSLinus Torvalds 
608e05e279eSLinus Torvalds 	file->private_data = buf;
609e05e279eSLinus Torvalds 	u32_format_array(buf, size, data->array, data->elements);
610e05e279eSLinus Torvalds 
61136048853SDavid Rientjes 	return nonseekable_open(inode, file);
6129fe2a701SSrivatsa Vaddagiri }
6139fe2a701SSrivatsa Vaddagiri 
61436048853SDavid Rientjes static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
61536048853SDavid Rientjes 			      loff_t *ppos)
61636048853SDavid Rientjes {
61736048853SDavid Rientjes 	size_t size = strlen(file->private_data);
6189fe2a701SSrivatsa Vaddagiri 
6199fe2a701SSrivatsa Vaddagiri 	return simple_read_from_buffer(buf, len, ppos,
6209fe2a701SSrivatsa Vaddagiri 					file->private_data, size);
6219fe2a701SSrivatsa Vaddagiri }
6229fe2a701SSrivatsa Vaddagiri 
6239fe2a701SSrivatsa Vaddagiri static int u32_array_release(struct inode *inode, struct file *file)
6249fe2a701SSrivatsa Vaddagiri {
6259fe2a701SSrivatsa Vaddagiri 	kfree(file->private_data);
6269fe2a701SSrivatsa Vaddagiri 
6279fe2a701SSrivatsa Vaddagiri 	return 0;
6289fe2a701SSrivatsa Vaddagiri }
6299fe2a701SSrivatsa Vaddagiri 
6309fe2a701SSrivatsa Vaddagiri static const struct file_operations u32_array_fops = {
6319fe2a701SSrivatsa Vaddagiri 	.owner	 = THIS_MODULE,
6329fe2a701SSrivatsa Vaddagiri 	.open	 = u32_array_open,
6339fe2a701SSrivatsa Vaddagiri 	.release = u32_array_release,
6349fe2a701SSrivatsa Vaddagiri 	.read	 = u32_array_read,
6359fe2a701SSrivatsa Vaddagiri 	.llseek  = no_llseek,
6369fe2a701SSrivatsa Vaddagiri };
6379fe2a701SSrivatsa Vaddagiri 
6389fe2a701SSrivatsa Vaddagiri /**
6399fe2a701SSrivatsa Vaddagiri  * debugfs_create_u32_array - create a debugfs file that is used to read u32
6409fe2a701SSrivatsa Vaddagiri  * array.
6419fe2a701SSrivatsa Vaddagiri  * @name: a pointer to a string containing the name of the file to create.
6429fe2a701SSrivatsa Vaddagiri  * @mode: the permission that the file should have.
6439fe2a701SSrivatsa Vaddagiri  * @parent: a pointer to the parent dentry for this file.  This should be a
6449fe2a701SSrivatsa Vaddagiri  *          directory dentry if set.  If this parameter is %NULL, then the
6459fe2a701SSrivatsa Vaddagiri  *          file will be created in the root of the debugfs filesystem.
6469fe2a701SSrivatsa Vaddagiri  * @array: u32 array that provides data.
6479fe2a701SSrivatsa Vaddagiri  * @elements: total number of elements in the array.
6489fe2a701SSrivatsa Vaddagiri  *
6499fe2a701SSrivatsa Vaddagiri  * This function creates a file in debugfs with the given name that exports
6509fe2a701SSrivatsa Vaddagiri  * @array as data. If the @mode variable is so set it can be read from.
6519fe2a701SSrivatsa Vaddagiri  * Writing is not supported. Seek within the file is also not supported.
6529fe2a701SSrivatsa Vaddagiri  * Once array is created its size can not be changed.
6539fe2a701SSrivatsa Vaddagiri  *
6549fe2a701SSrivatsa Vaddagiri  * The function returns a pointer to dentry on success. If debugfs is not
6559fe2a701SSrivatsa Vaddagiri  * enabled in the kernel, the value -%ENODEV will be returned.
6569fe2a701SSrivatsa Vaddagiri  */
6579fe2a701SSrivatsa Vaddagiri struct dentry *debugfs_create_u32_array(const char *name, umode_t mode,
6589fe2a701SSrivatsa Vaddagiri 					    struct dentry *parent,
6599fe2a701SSrivatsa Vaddagiri 					    u32 *array, u32 elements)
6609fe2a701SSrivatsa Vaddagiri {
6619fe2a701SSrivatsa Vaddagiri 	struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
6629fe2a701SSrivatsa Vaddagiri 
6639fe2a701SSrivatsa Vaddagiri 	if (data == NULL)
6649fe2a701SSrivatsa Vaddagiri 		return NULL;
6659fe2a701SSrivatsa Vaddagiri 
6669fe2a701SSrivatsa Vaddagiri 	data->array = array;
6679fe2a701SSrivatsa Vaddagiri 	data->elements = elements;
6689fe2a701SSrivatsa Vaddagiri 
6699fe2a701SSrivatsa Vaddagiri 	return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
6709fe2a701SSrivatsa Vaddagiri }
6719fe2a701SSrivatsa Vaddagiri EXPORT_SYMBOL_GPL(debugfs_create_u32_array);
6729fe2a701SSrivatsa Vaddagiri 
6733b85e4abSHeiko Carstens #ifdef CONFIG_HAS_IOMEM
6743b85e4abSHeiko Carstens 
6751a087c6aSAlessandro Rubini /*
6761a087c6aSAlessandro Rubini  * The regset32 stuff is used to print 32-bit registers using the
6771a087c6aSAlessandro Rubini  * seq_file utilities. We offer printing a register set in an already-opened
6781a087c6aSAlessandro Rubini  * sequential file or create a debugfs file that only prints a regset32.
6791a087c6aSAlessandro Rubini  */
6801a087c6aSAlessandro Rubini 
6811a087c6aSAlessandro Rubini /**
6821a087c6aSAlessandro Rubini  * debugfs_print_regs32 - use seq_print to describe a set of registers
6831a087c6aSAlessandro Rubini  * @s: the seq_file structure being used to generate output
6841a087c6aSAlessandro Rubini  * @regs: an array if struct debugfs_reg32 structures
685b5763accSRandy Dunlap  * @nregs: the length of the above array
6861a087c6aSAlessandro Rubini  * @base: the base address to be used in reading the registers
6871a087c6aSAlessandro Rubini  * @prefix: a string to be prefixed to every output line
6881a087c6aSAlessandro Rubini  *
6891a087c6aSAlessandro Rubini  * This function outputs a text block describing the current values of
6901a087c6aSAlessandro Rubini  * some 32-bit hardware registers. It is meant to be used within debugfs
6911a087c6aSAlessandro Rubini  * files based on seq_file that need to show registers, intermixed with other
6921a087c6aSAlessandro Rubini  * information. The prefix argument may be used to specify a leading string,
6931a087c6aSAlessandro Rubini  * because some peripherals have several blocks of identical registers,
6941a087c6aSAlessandro Rubini  * for example configuration of dma channels
6951a087c6aSAlessandro Rubini  */
6968ee4dd9fSAlessandro Rubini int debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
6971a087c6aSAlessandro Rubini 			   int nregs, void __iomem *base, char *prefix)
6981a087c6aSAlessandro Rubini {
6991a087c6aSAlessandro Rubini 	int i, ret = 0;
7001a087c6aSAlessandro Rubini 
7011a087c6aSAlessandro Rubini 	for (i = 0; i < nregs; i++, regs++) {
7021a087c6aSAlessandro Rubini 		if (prefix)
7031a087c6aSAlessandro Rubini 			ret += seq_printf(s, "%s", prefix);
7041a087c6aSAlessandro Rubini 		ret += seq_printf(s, "%s = 0x%08x\n", regs->name,
7055858441cSDan Carpenter 				  readl(base + regs->offset));
7061a087c6aSAlessandro Rubini 	}
7071a087c6aSAlessandro Rubini 	return ret;
7081a087c6aSAlessandro Rubini }
7091a087c6aSAlessandro Rubini EXPORT_SYMBOL_GPL(debugfs_print_regs32);
7101a087c6aSAlessandro Rubini 
7111a087c6aSAlessandro Rubini static int debugfs_show_regset32(struct seq_file *s, void *data)
7121a087c6aSAlessandro Rubini {
7131a087c6aSAlessandro Rubini 	struct debugfs_regset32 *regset = s->private;
7141a087c6aSAlessandro Rubini 
7151a087c6aSAlessandro Rubini 	debugfs_print_regs32(s, regset->regs, regset->nregs, regset->base, "");
7161a087c6aSAlessandro Rubini 	return 0;
7171a087c6aSAlessandro Rubini }
7181a087c6aSAlessandro Rubini 
7191a087c6aSAlessandro Rubini static int debugfs_open_regset32(struct inode *inode, struct file *file)
7201a087c6aSAlessandro Rubini {
7211a087c6aSAlessandro Rubini 	return single_open(file, debugfs_show_regset32, inode->i_private);
7221a087c6aSAlessandro Rubini }
7231a087c6aSAlessandro Rubini 
7241a087c6aSAlessandro Rubini static const struct file_operations fops_regset32 = {
7251a087c6aSAlessandro Rubini 	.open =		debugfs_open_regset32,
7261a087c6aSAlessandro Rubini 	.read =		seq_read,
7271a087c6aSAlessandro Rubini 	.llseek =	seq_lseek,
7281a087c6aSAlessandro Rubini 	.release =	single_release,
7291a087c6aSAlessandro Rubini };
7301a087c6aSAlessandro Rubini 
7311a087c6aSAlessandro Rubini /**
7321a087c6aSAlessandro Rubini  * debugfs_create_regset32 - create a debugfs file that returns register values
7331a087c6aSAlessandro Rubini  * @name: a pointer to a string containing the name of the file to create.
7341a087c6aSAlessandro Rubini  * @mode: the permission that the file should have
7351a087c6aSAlessandro Rubini  * @parent: a pointer to the parent dentry for this file.  This should be a
7361a087c6aSAlessandro Rubini  *          directory dentry if set.  If this parameter is %NULL, then the
7371a087c6aSAlessandro Rubini  *          file will be created in the root of the debugfs filesystem.
7381a087c6aSAlessandro Rubini  * @regset: a pointer to a struct debugfs_regset32, which contains a pointer
7391a087c6aSAlessandro Rubini  *          to an array of register definitions, the array size and the base
7401a087c6aSAlessandro Rubini  *          address where the register bank is to be found.
7411a087c6aSAlessandro Rubini  *
7421a087c6aSAlessandro Rubini  * This function creates a file in debugfs with the given name that reports
7431a087c6aSAlessandro Rubini  * the names and values of a set of 32-bit registers. If the @mode variable
7441a087c6aSAlessandro Rubini  * is so set it can be read from. Writing is not supported.
7451a087c6aSAlessandro Rubini  *
7461a087c6aSAlessandro Rubini  * This function will return a pointer to a dentry if it succeeds.  This
7471a087c6aSAlessandro Rubini  * pointer must be passed to the debugfs_remove() function when the file is
7481a087c6aSAlessandro Rubini  * to be removed (no automatic cleanup happens if your module is unloaded,
7491a087c6aSAlessandro Rubini  * you are responsible here.)  If an error occurs, %NULL will be returned.
7501a087c6aSAlessandro Rubini  *
7511a087c6aSAlessandro Rubini  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
7521a087c6aSAlessandro Rubini  * returned.  It is not wise to check for this value, but rather, check for
7531a087c6aSAlessandro Rubini  * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
7541a087c6aSAlessandro Rubini  * code.
7551a087c6aSAlessandro Rubini  */
75688187398SAl Viro struct dentry *debugfs_create_regset32(const char *name, umode_t mode,
7571a087c6aSAlessandro Rubini 				       struct dentry *parent,
7581a087c6aSAlessandro Rubini 				       struct debugfs_regset32 *regset)
7591a087c6aSAlessandro Rubini {
7601a087c6aSAlessandro Rubini 	return debugfs_create_file(name, mode, parent, regset, &fops_regset32);
7611a087c6aSAlessandro Rubini }
7621a087c6aSAlessandro Rubini EXPORT_SYMBOL_GPL(debugfs_create_regset32);
7633b85e4abSHeiko Carstens 
7643b85e4abSHeiko Carstens #endif /* CONFIG_HAS_IOMEM */
765*98210b7fSArend van Spriel 
766*98210b7fSArend van Spriel struct debugfs_devm_entry {
767*98210b7fSArend van Spriel 	int (*read)(struct seq_file *seq, void *data);
768*98210b7fSArend van Spriel 	struct device *dev;
769*98210b7fSArend van Spriel };
770*98210b7fSArend van Spriel 
771*98210b7fSArend van Spriel static int debugfs_devm_entry_open(struct inode *inode, struct file *f)
772*98210b7fSArend van Spriel {
773*98210b7fSArend van Spriel 	struct debugfs_devm_entry *entry = inode->i_private;
774*98210b7fSArend van Spriel 
775*98210b7fSArend van Spriel 	return single_open(f, entry->read, entry->dev);
776*98210b7fSArend van Spriel }
777*98210b7fSArend van Spriel 
778*98210b7fSArend van Spriel static const struct file_operations debugfs_devm_entry_ops = {
779*98210b7fSArend van Spriel 	.owner = THIS_MODULE,
780*98210b7fSArend van Spriel 	.open = debugfs_devm_entry_open,
781*98210b7fSArend van Spriel 	.release = single_release,
782*98210b7fSArend van Spriel 	.read = seq_read,
783*98210b7fSArend van Spriel 	.llseek = seq_lseek
784*98210b7fSArend van Spriel };
785*98210b7fSArend van Spriel 
786*98210b7fSArend van Spriel /**
787*98210b7fSArend van Spriel  * debugfs_create_devm_seqfile - create a debugfs file that is bound to device.
788*98210b7fSArend van Spriel  *
789*98210b7fSArend van Spriel  * @dev: device related to this debugfs file.
790*98210b7fSArend van Spriel  * @name: name of the debugfs file.
791*98210b7fSArend van Spriel  * @parent: a pointer to the parent dentry for this file.  This should be a
792*98210b7fSArend van Spriel  *	directory dentry if set.  If this parameter is %NULL, then the
793*98210b7fSArend van Spriel  *	file will be created in the root of the debugfs filesystem.
794*98210b7fSArend van Spriel  * @read_fn: function pointer called to print the seq_file content.
795*98210b7fSArend van Spriel  */
796*98210b7fSArend van Spriel struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
797*98210b7fSArend van Spriel 					   struct dentry *parent,
798*98210b7fSArend van Spriel 					   int (*read_fn)(struct seq_file *s,
799*98210b7fSArend van Spriel 							  void *data))
800*98210b7fSArend van Spriel {
801*98210b7fSArend van Spriel 	struct debugfs_devm_entry *entry;
802*98210b7fSArend van Spriel 
803*98210b7fSArend van Spriel 	if (IS_ERR(parent))
804*98210b7fSArend van Spriel 		return ERR_PTR(-ENOENT);
805*98210b7fSArend van Spriel 
806*98210b7fSArend van Spriel 	entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
807*98210b7fSArend van Spriel 	if (!entry)
808*98210b7fSArend van Spriel 		return ERR_PTR(-ENOMEM);
809*98210b7fSArend van Spriel 
810*98210b7fSArend van Spriel 	entry->read = read_fn;
811*98210b7fSArend van Spriel 	entry->dev = dev;
812*98210b7fSArend van Spriel 
813*98210b7fSArend van Spriel 	return debugfs_create_file(name, S_IRUGO, parent, entry,
814*98210b7fSArend van Spriel 				   &debugfs_devm_entry_ops);
815*98210b7fSArend van Spriel }
816*98210b7fSArend van Spriel EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile);
817*98210b7fSArend van Spriel 
818