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> 201da177e4SLinus Torvalds #include <linux/debugfs.h> 2103e099fbSAlessandro Rubini #include <linux/io.h> 229fe2a701SSrivatsa Vaddagiri #include <linux/slab.h> 233a76e5e0SSeth Jennings #include <linux/atomic.h> 2498210b7fSArend van Spriel #include <linux/device.h> 259fd4dcecSNicolai Stange #include <linux/srcu.h> 26*49d200deSNicolai Stange #include <asm/poll.h> 279fd4dcecSNicolai Stange 289fd4dcecSNicolai Stange #include "internal.h" 291da177e4SLinus Torvalds 30*49d200deSNicolai Stange struct poll_table_struct; 31*49d200deSNicolai Stange 321da177e4SLinus Torvalds static ssize_t default_read_file(struct file *file, char __user *buf, 331da177e4SLinus Torvalds size_t count, loff_t *ppos) 341da177e4SLinus Torvalds { 351da177e4SLinus Torvalds return 0; 361da177e4SLinus Torvalds } 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds static ssize_t default_write_file(struct file *file, const char __user *buf, 391da177e4SLinus Torvalds size_t count, loff_t *ppos) 401da177e4SLinus Torvalds { 411da177e4SLinus Torvalds return count; 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds 449fd4dcecSNicolai Stange const struct file_operations debugfs_noop_file_operations = { 451da177e4SLinus Torvalds .read = default_read_file, 461da177e4SLinus Torvalds .write = default_write_file, 47234e3405SStephen Boyd .open = simple_open, 486038f373SArnd Bergmann .llseek = noop_llseek, 491da177e4SLinus Torvalds }; 501da177e4SLinus Torvalds 519fd4dcecSNicolai Stange /** 529fd4dcecSNicolai Stange * debugfs_use_file_start - mark the beginning of file data access 539fd4dcecSNicolai Stange * @dentry: the dentry object whose data is being accessed. 549fd4dcecSNicolai Stange * @srcu_idx: a pointer to some memory to store a SRCU index in. 559fd4dcecSNicolai Stange * 569fd4dcecSNicolai Stange * Up to a matching call to debugfs_use_file_finish(), any 579fd4dcecSNicolai Stange * successive call into the file removing functions debugfs_remove() 589fd4dcecSNicolai Stange * and debugfs_remove_recursive() will block. Since associated private 599fd4dcecSNicolai Stange * file data may only get freed after a successful return of any of 609fd4dcecSNicolai Stange * the removal functions, you may safely access it after a successful 619fd4dcecSNicolai Stange * call to debugfs_use_file_start() without worrying about 629fd4dcecSNicolai Stange * lifetime issues. 639fd4dcecSNicolai Stange * 649fd4dcecSNicolai Stange * If -%EIO is returned, the file has already been removed and thus, 659fd4dcecSNicolai Stange * it is not safe to access any of its data. If, on the other hand, 669fd4dcecSNicolai Stange * it is allowed to access the file data, zero is returned. 679fd4dcecSNicolai Stange * 689fd4dcecSNicolai Stange * Regardless of the return code, any call to 699fd4dcecSNicolai Stange * debugfs_use_file_start() must be followed by a matching call 709fd4dcecSNicolai Stange * to debugfs_use_file_finish(). 719fd4dcecSNicolai Stange */ 72*49d200deSNicolai Stange int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) 739fd4dcecSNicolai Stange __acquires(&debugfs_srcu) 749fd4dcecSNicolai Stange { 759fd4dcecSNicolai Stange *srcu_idx = srcu_read_lock(&debugfs_srcu); 769fd4dcecSNicolai Stange barrier(); 779fd4dcecSNicolai Stange if (d_unlinked(dentry)) 789fd4dcecSNicolai Stange return -EIO; 799fd4dcecSNicolai Stange return 0; 809fd4dcecSNicolai Stange } 81*49d200deSNicolai Stange EXPORT_SYMBOL_GPL(debugfs_use_file_start); 829fd4dcecSNicolai Stange 839fd4dcecSNicolai Stange /** 849fd4dcecSNicolai Stange * debugfs_use_file_finish - mark the end of file data access 859fd4dcecSNicolai Stange * @srcu_idx: the SRCU index "created" by a former call to 869fd4dcecSNicolai Stange * debugfs_use_file_start(). 879fd4dcecSNicolai Stange * 889fd4dcecSNicolai Stange * Allow any ongoing concurrent call into debugfs_remove() or 899fd4dcecSNicolai Stange * debugfs_remove_recursive() blocked by a former call to 909fd4dcecSNicolai Stange * debugfs_use_file_start() to proceed and return to its caller. 919fd4dcecSNicolai Stange */ 92*49d200deSNicolai Stange void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) 939fd4dcecSNicolai Stange { 949fd4dcecSNicolai Stange srcu_read_unlock(&debugfs_srcu, srcu_idx); 959fd4dcecSNicolai Stange } 96*49d200deSNicolai Stange EXPORT_SYMBOL_GPL(debugfs_use_file_finish); 979fd4dcecSNicolai Stange 989fd4dcecSNicolai Stange #define F_DENTRY(filp) ((filp)->f_path.dentry) 999fd4dcecSNicolai Stange 1009fd4dcecSNicolai Stange #define REAL_FOPS_DEREF(dentry) \ 1019fd4dcecSNicolai Stange ((const struct file_operations *)(dentry)->d_fsdata) 1029fd4dcecSNicolai Stange 1039fd4dcecSNicolai Stange static int open_proxy_open(struct inode *inode, struct file *filp) 1049fd4dcecSNicolai Stange { 1059fd4dcecSNicolai Stange const struct dentry *dentry = F_DENTRY(filp); 1069fd4dcecSNicolai Stange const struct file_operations *real_fops = NULL; 1079fd4dcecSNicolai Stange int srcu_idx, r; 1089fd4dcecSNicolai Stange 1099fd4dcecSNicolai Stange r = debugfs_use_file_start(dentry, &srcu_idx); 1109fd4dcecSNicolai Stange if (r) { 1119fd4dcecSNicolai Stange r = -ENOENT; 1129fd4dcecSNicolai Stange goto out; 1139fd4dcecSNicolai Stange } 1149fd4dcecSNicolai Stange 1159fd4dcecSNicolai Stange real_fops = REAL_FOPS_DEREF(dentry); 1169fd4dcecSNicolai Stange real_fops = fops_get(real_fops); 1179fd4dcecSNicolai Stange if (!real_fops) { 1189fd4dcecSNicolai Stange /* Huh? Module did not clean up after itself at exit? */ 1199fd4dcecSNicolai Stange WARN(1, "debugfs file owner did not clean up at exit: %pd", 1209fd4dcecSNicolai Stange dentry); 1219fd4dcecSNicolai Stange r = -ENXIO; 1229fd4dcecSNicolai Stange goto out; 1239fd4dcecSNicolai Stange } 1249fd4dcecSNicolai Stange replace_fops(filp, real_fops); 1259fd4dcecSNicolai Stange 1269fd4dcecSNicolai Stange if (real_fops->open) 1279fd4dcecSNicolai Stange r = real_fops->open(inode, filp); 1289fd4dcecSNicolai Stange 1299fd4dcecSNicolai Stange out: 1309fd4dcecSNicolai Stange fops_put(real_fops); 1319fd4dcecSNicolai Stange debugfs_use_file_finish(srcu_idx); 1329fd4dcecSNicolai Stange return r; 1339fd4dcecSNicolai Stange } 1349fd4dcecSNicolai Stange 1359fd4dcecSNicolai Stange const struct file_operations debugfs_open_proxy_file_operations = { 1369fd4dcecSNicolai Stange .open = open_proxy_open, 1379fd4dcecSNicolai Stange }; 1389fd4dcecSNicolai Stange 139*49d200deSNicolai Stange #define PROTO(args...) args 140*49d200deSNicolai Stange #define ARGS(args...) args 141*49d200deSNicolai Stange 142*49d200deSNicolai Stange #define FULL_PROXY_FUNC(name, ret_type, filp, proto, args) \ 143*49d200deSNicolai Stange static ret_type full_proxy_ ## name(proto) \ 144*49d200deSNicolai Stange { \ 145*49d200deSNicolai Stange const struct dentry *dentry = F_DENTRY(filp); \ 146*49d200deSNicolai Stange const struct file_operations *real_fops = \ 147*49d200deSNicolai Stange REAL_FOPS_DEREF(dentry); \ 148*49d200deSNicolai Stange int srcu_idx; \ 149*49d200deSNicolai Stange ret_type r; \ 150*49d200deSNicolai Stange \ 151*49d200deSNicolai Stange r = debugfs_use_file_start(dentry, &srcu_idx); \ 152*49d200deSNicolai Stange if (likely(!r)) \ 153*49d200deSNicolai Stange r = real_fops->name(args); \ 154*49d200deSNicolai Stange debugfs_use_file_finish(srcu_idx); \ 155*49d200deSNicolai Stange return r; \ 156*49d200deSNicolai Stange } 157*49d200deSNicolai Stange 158*49d200deSNicolai Stange FULL_PROXY_FUNC(llseek, loff_t, filp, 159*49d200deSNicolai Stange PROTO(struct file *filp, loff_t offset, int whence), 160*49d200deSNicolai Stange ARGS(filp, offset, whence)); 161*49d200deSNicolai Stange 162*49d200deSNicolai Stange FULL_PROXY_FUNC(read, ssize_t, filp, 163*49d200deSNicolai Stange PROTO(struct file *filp, char __user *buf, size_t size, 164*49d200deSNicolai Stange loff_t *ppos), 165*49d200deSNicolai Stange ARGS(filp, buf, size, ppos)); 166*49d200deSNicolai Stange 167*49d200deSNicolai Stange FULL_PROXY_FUNC(write, ssize_t, filp, 168*49d200deSNicolai Stange PROTO(struct file *filp, const char __user *buf, size_t size, 169*49d200deSNicolai Stange loff_t *ppos), 170*49d200deSNicolai Stange ARGS(filp, buf, size, ppos)); 171*49d200deSNicolai Stange 172*49d200deSNicolai Stange FULL_PROXY_FUNC(unlocked_ioctl, long, filp, 173*49d200deSNicolai Stange PROTO(struct file *filp, unsigned int cmd, unsigned long arg), 174*49d200deSNicolai Stange ARGS(filp, cmd, arg)); 175*49d200deSNicolai Stange 176*49d200deSNicolai Stange static unsigned int full_proxy_poll(struct file *filp, 177*49d200deSNicolai Stange struct poll_table_struct *wait) 178*49d200deSNicolai Stange { 179*49d200deSNicolai Stange const struct dentry *dentry = F_DENTRY(filp); 180*49d200deSNicolai Stange const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry); 181*49d200deSNicolai Stange int srcu_idx; 182*49d200deSNicolai Stange unsigned int r = 0; 183*49d200deSNicolai Stange 184*49d200deSNicolai Stange if (debugfs_use_file_start(dentry, &srcu_idx)) { 185*49d200deSNicolai Stange debugfs_use_file_finish(srcu_idx); 186*49d200deSNicolai Stange return POLLHUP; 187*49d200deSNicolai Stange } 188*49d200deSNicolai Stange 189*49d200deSNicolai Stange r = real_fops->poll(filp, wait); 190*49d200deSNicolai Stange debugfs_use_file_finish(srcu_idx); 191*49d200deSNicolai Stange return r; 192*49d200deSNicolai Stange } 193*49d200deSNicolai Stange 194*49d200deSNicolai Stange static int full_proxy_release(struct inode *inode, struct file *filp) 195*49d200deSNicolai Stange { 196*49d200deSNicolai Stange const struct dentry *dentry = F_DENTRY(filp); 197*49d200deSNicolai Stange const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry); 198*49d200deSNicolai Stange const struct file_operations *proxy_fops = filp->f_op; 199*49d200deSNicolai Stange int r = 0; 200*49d200deSNicolai Stange 201*49d200deSNicolai Stange /* 202*49d200deSNicolai Stange * We must not protect this against removal races here: the 203*49d200deSNicolai Stange * original releaser should be called unconditionally in order 204*49d200deSNicolai Stange * not to leak any resources. Releasers must not assume that 205*49d200deSNicolai Stange * ->i_private is still being meaningful here. 206*49d200deSNicolai Stange */ 207*49d200deSNicolai Stange if (real_fops->release) 208*49d200deSNicolai Stange r = real_fops->release(inode, filp); 209*49d200deSNicolai Stange 210*49d200deSNicolai Stange replace_fops(filp, d_inode(dentry)->i_fop); 211*49d200deSNicolai Stange kfree((void *)proxy_fops); 212*49d200deSNicolai Stange fops_put(real_fops); 213*49d200deSNicolai Stange return 0; 214*49d200deSNicolai Stange } 215*49d200deSNicolai Stange 216*49d200deSNicolai Stange static void __full_proxy_fops_init(struct file_operations *proxy_fops, 217*49d200deSNicolai Stange const struct file_operations *real_fops) 218*49d200deSNicolai Stange { 219*49d200deSNicolai Stange proxy_fops->release = full_proxy_release; 220*49d200deSNicolai Stange if (real_fops->llseek) 221*49d200deSNicolai Stange proxy_fops->llseek = full_proxy_llseek; 222*49d200deSNicolai Stange if (real_fops->read) 223*49d200deSNicolai Stange proxy_fops->read = full_proxy_read; 224*49d200deSNicolai Stange if (real_fops->write) 225*49d200deSNicolai Stange proxy_fops->write = full_proxy_write; 226*49d200deSNicolai Stange if (real_fops->poll) 227*49d200deSNicolai Stange proxy_fops->poll = full_proxy_poll; 228*49d200deSNicolai Stange if (real_fops->unlocked_ioctl) 229*49d200deSNicolai Stange proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl; 230*49d200deSNicolai Stange } 231*49d200deSNicolai Stange 232*49d200deSNicolai Stange static int full_proxy_open(struct inode *inode, struct file *filp) 233*49d200deSNicolai Stange { 234*49d200deSNicolai Stange const struct dentry *dentry = F_DENTRY(filp); 235*49d200deSNicolai Stange const struct file_operations *real_fops = NULL; 236*49d200deSNicolai Stange struct file_operations *proxy_fops = NULL; 237*49d200deSNicolai Stange int srcu_idx, r; 238*49d200deSNicolai Stange 239*49d200deSNicolai Stange r = debugfs_use_file_start(dentry, &srcu_idx); 240*49d200deSNicolai Stange if (r) { 241*49d200deSNicolai Stange r = -ENOENT; 242*49d200deSNicolai Stange goto out; 243*49d200deSNicolai Stange } 244*49d200deSNicolai Stange 245*49d200deSNicolai Stange real_fops = REAL_FOPS_DEREF(dentry); 246*49d200deSNicolai Stange real_fops = fops_get(real_fops); 247*49d200deSNicolai Stange if (!real_fops) { 248*49d200deSNicolai Stange /* Huh? Module did not cleanup after itself at exit? */ 249*49d200deSNicolai Stange WARN(1, "debugfs file owner did not clean up at exit: %pd", 250*49d200deSNicolai Stange dentry); 251*49d200deSNicolai Stange r = -ENXIO; 252*49d200deSNicolai Stange goto out; 253*49d200deSNicolai Stange } 254*49d200deSNicolai Stange 255*49d200deSNicolai Stange proxy_fops = kzalloc(sizeof(*proxy_fops), GFP_KERNEL); 256*49d200deSNicolai Stange if (!proxy_fops) { 257*49d200deSNicolai Stange r = -ENOMEM; 258*49d200deSNicolai Stange goto free_proxy; 259*49d200deSNicolai Stange } 260*49d200deSNicolai Stange __full_proxy_fops_init(proxy_fops, real_fops); 261*49d200deSNicolai Stange replace_fops(filp, proxy_fops); 262*49d200deSNicolai Stange 263*49d200deSNicolai Stange if (real_fops->open) { 264*49d200deSNicolai Stange r = real_fops->open(inode, filp); 265*49d200deSNicolai Stange 266*49d200deSNicolai Stange if (filp->f_op != proxy_fops) { 267*49d200deSNicolai Stange /* No protection against file removal anymore. */ 268*49d200deSNicolai Stange WARN(1, "debugfs file owner replaced proxy fops: %pd", 269*49d200deSNicolai Stange dentry); 270*49d200deSNicolai Stange goto free_proxy; 271*49d200deSNicolai Stange } 272*49d200deSNicolai Stange } 273*49d200deSNicolai Stange 274*49d200deSNicolai Stange goto out; 275*49d200deSNicolai Stange free_proxy: 276*49d200deSNicolai Stange kfree(proxy_fops); 277*49d200deSNicolai Stange fops_put(real_fops); 278*49d200deSNicolai Stange out: 279*49d200deSNicolai Stange debugfs_use_file_finish(srcu_idx); 280*49d200deSNicolai Stange return r; 281*49d200deSNicolai Stange } 282*49d200deSNicolai Stange 283*49d200deSNicolai Stange const struct file_operations debugfs_full_proxy_file_operations = { 284*49d200deSNicolai Stange .open = full_proxy_open, 285*49d200deSNicolai Stange }; 286*49d200deSNicolai Stange 287b97f6799SStephen Boyd static struct dentry *debugfs_create_mode(const char *name, umode_t mode, 288b97f6799SStephen Boyd struct dentry *parent, void *value, 289b97f6799SStephen Boyd const struct file_operations *fops, 290b97f6799SStephen Boyd const struct file_operations *fops_ro, 291b97f6799SStephen Boyd const struct file_operations *fops_wo) 292b97f6799SStephen Boyd { 293b97f6799SStephen Boyd /* if there are no write bits set, make read only */ 294b97f6799SStephen Boyd if (!(mode & S_IWUGO)) 295b97f6799SStephen Boyd return debugfs_create_file(name, mode, parent, value, fops_ro); 296b97f6799SStephen Boyd /* if there are no read bits set, make write only */ 297b97f6799SStephen Boyd if (!(mode & S_IRUGO)) 298b97f6799SStephen Boyd return debugfs_create_file(name, mode, parent, value, fops_wo); 299b97f6799SStephen Boyd 300b97f6799SStephen Boyd return debugfs_create_file(name, mode, parent, value, fops); 301b97f6799SStephen Boyd } 302b97f6799SStephen Boyd 3038b88b099SChristoph Hellwig static int debugfs_u8_set(void *data, u64 val) 304acaefc25SArnd Bergmann { 305acaefc25SArnd Bergmann *(u8 *)data = val; 3068b88b099SChristoph Hellwig return 0; 307acaefc25SArnd Bergmann } 3088b88b099SChristoph Hellwig static int debugfs_u8_get(void *data, u64 *val) 309acaefc25SArnd Bergmann { 3108b88b099SChristoph Hellwig *val = *(u8 *)data; 3118b88b099SChristoph Hellwig return 0; 312acaefc25SArnd Bergmann } 313acaefc25SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); 314e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n"); 315e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds /** 3186468b3afSRandy Dunlap * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value 3191da177e4SLinus Torvalds * @name: a pointer to a string containing the name of the file to create. 3201da177e4SLinus Torvalds * @mode: the permission that the file should have 3211da177e4SLinus Torvalds * @parent: a pointer to the parent dentry for this file. This should be a 3226468b3afSRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 3231da177e4SLinus Torvalds * file will be created in the root of the debugfs filesystem. 3241da177e4SLinus Torvalds * @value: a pointer to the variable that the file should read to and write 3251da177e4SLinus Torvalds * from. 3261da177e4SLinus Torvalds * 3271da177e4SLinus Torvalds * This function creates a file in debugfs with the given name that 3281da177e4SLinus Torvalds * contains the value of the variable @value. If the @mode variable is so 3291da177e4SLinus Torvalds * set, it can be read from, and written to. 3301da177e4SLinus Torvalds * 3311da177e4SLinus Torvalds * This function will return a pointer to a dentry if it succeeds. This 3321da177e4SLinus Torvalds * pointer must be passed to the debugfs_remove() function when the file is 3331da177e4SLinus Torvalds * to be removed (no automatic cleanup happens if your module is unloaded, 3346468b3afSRandy Dunlap * you are responsible here.) If an error occurs, %NULL will be returned. 3351da177e4SLinus Torvalds * 3366468b3afSRandy Dunlap * If debugfs is not enabled in the kernel, the value -%ENODEV will be 3371da177e4SLinus Torvalds * returned. It is not wise to check for this value, but rather, check for 3386468b3afSRandy Dunlap * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 3391da177e4SLinus Torvalds * code. 3401da177e4SLinus Torvalds */ 341f4ae40a6SAl Viro struct dentry *debugfs_create_u8(const char *name, umode_t mode, 3421da177e4SLinus Torvalds struct dentry *parent, u8 *value) 3431da177e4SLinus Torvalds { 344b97f6799SStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_u8, 345b97f6799SStephen Boyd &fops_u8_ro, &fops_u8_wo); 3461da177e4SLinus Torvalds } 3471da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u8); 3481da177e4SLinus Torvalds 3498b88b099SChristoph Hellwig static int debugfs_u16_set(void *data, u64 val) 350acaefc25SArnd Bergmann { 351acaefc25SArnd Bergmann *(u16 *)data = val; 3528b88b099SChristoph Hellwig return 0; 353acaefc25SArnd Bergmann } 3548b88b099SChristoph Hellwig static int debugfs_u16_get(void *data, u64 *val) 355acaefc25SArnd Bergmann { 3568b88b099SChristoph Hellwig *val = *(u16 *)data; 3578b88b099SChristoph Hellwig return 0; 358acaefc25SArnd Bergmann } 359acaefc25SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); 360e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n"); 361e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); 362acaefc25SArnd Bergmann 3631da177e4SLinus Torvalds /** 3646468b3afSRandy Dunlap * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value 3651da177e4SLinus Torvalds * @name: a pointer to a string containing the name of the file to create. 3661da177e4SLinus Torvalds * @mode: the permission that the file should have 3671da177e4SLinus Torvalds * @parent: a pointer to the parent dentry for this file. This should be a 3686468b3afSRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 3691da177e4SLinus Torvalds * file will be created in the root of the debugfs filesystem. 3701da177e4SLinus Torvalds * @value: a pointer to the variable that the file should read to and write 3711da177e4SLinus Torvalds * from. 3721da177e4SLinus Torvalds * 3731da177e4SLinus Torvalds * This function creates a file in debugfs with the given name that 3741da177e4SLinus Torvalds * contains the value of the variable @value. If the @mode variable is so 3751da177e4SLinus Torvalds * set, it can be read from, and written to. 3761da177e4SLinus Torvalds * 3771da177e4SLinus Torvalds * This function will return a pointer to a dentry if it succeeds. This 3781da177e4SLinus Torvalds * pointer must be passed to the debugfs_remove() function when the file is 3791da177e4SLinus Torvalds * to be removed (no automatic cleanup happens if your module is unloaded, 3806468b3afSRandy Dunlap * you are responsible here.) If an error occurs, %NULL will be returned. 3811da177e4SLinus Torvalds * 3826468b3afSRandy Dunlap * If debugfs is not enabled in the kernel, the value -%ENODEV will be 3831da177e4SLinus Torvalds * returned. It is not wise to check for this value, but rather, check for 3846468b3afSRandy Dunlap * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 3851da177e4SLinus Torvalds * code. 3861da177e4SLinus Torvalds */ 387f4ae40a6SAl Viro struct dentry *debugfs_create_u16(const char *name, umode_t mode, 3881da177e4SLinus Torvalds struct dentry *parent, u16 *value) 3891da177e4SLinus Torvalds { 390b97f6799SStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_u16, 391b97f6799SStephen Boyd &fops_u16_ro, &fops_u16_wo); 3921da177e4SLinus Torvalds } 3931da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u16); 3941da177e4SLinus Torvalds 3958b88b099SChristoph Hellwig static int debugfs_u32_set(void *data, u64 val) 396acaefc25SArnd Bergmann { 397acaefc25SArnd Bergmann *(u32 *)data = val; 3988b88b099SChristoph Hellwig return 0; 399acaefc25SArnd Bergmann } 4008b88b099SChristoph Hellwig static int debugfs_u32_get(void *data, u64 *val) 401acaefc25SArnd Bergmann { 4028b88b099SChristoph Hellwig *val = *(u32 *)data; 4038b88b099SChristoph Hellwig return 0; 404acaefc25SArnd Bergmann } 405acaefc25SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); 406e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n"); 407e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); 408acaefc25SArnd Bergmann 4091da177e4SLinus Torvalds /** 4106468b3afSRandy Dunlap * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value 4111da177e4SLinus Torvalds * @name: a pointer to a string containing the name of the file to create. 4121da177e4SLinus Torvalds * @mode: the permission that the file should have 4131da177e4SLinus Torvalds * @parent: a pointer to the parent dentry for this file. This should be a 4146468b3afSRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 4151da177e4SLinus Torvalds * file will be created in the root of the debugfs filesystem. 4161da177e4SLinus Torvalds * @value: a pointer to the variable that the file should read to and write 4171da177e4SLinus Torvalds * from. 4181da177e4SLinus Torvalds * 4191da177e4SLinus Torvalds * This function creates a file in debugfs with the given name that 4201da177e4SLinus Torvalds * contains the value of the variable @value. If the @mode variable is so 4211da177e4SLinus Torvalds * set, it can be read from, and written to. 4221da177e4SLinus Torvalds * 4231da177e4SLinus Torvalds * This function will return a pointer to a dentry if it succeeds. This 4241da177e4SLinus Torvalds * pointer must be passed to the debugfs_remove() function when the file is 4251da177e4SLinus Torvalds * to be removed (no automatic cleanup happens if your module is unloaded, 4266468b3afSRandy Dunlap * you are responsible here.) If an error occurs, %NULL will be returned. 4271da177e4SLinus Torvalds * 4286468b3afSRandy Dunlap * If debugfs is not enabled in the kernel, the value -%ENODEV will be 4291da177e4SLinus Torvalds * returned. It is not wise to check for this value, but rather, check for 4306468b3afSRandy Dunlap * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 4311da177e4SLinus Torvalds * code. 4321da177e4SLinus Torvalds */ 433f4ae40a6SAl Viro struct dentry *debugfs_create_u32(const char *name, umode_t mode, 4341da177e4SLinus Torvalds struct dentry *parent, u32 *value) 4351da177e4SLinus Torvalds { 436b97f6799SStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_u32, 437b97f6799SStephen Boyd &fops_u32_ro, &fops_u32_wo); 4381da177e4SLinus Torvalds } 4391da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u32); 4401da177e4SLinus Torvalds 4418b88b099SChristoph Hellwig static int debugfs_u64_set(void *data, u64 val) 4428447891fSMichael Ellerman { 4438447891fSMichael Ellerman *(u64 *)data = val; 4448b88b099SChristoph Hellwig return 0; 4458447891fSMichael Ellerman } 4468447891fSMichael Ellerman 4478b88b099SChristoph Hellwig static int debugfs_u64_get(void *data, u64 *val) 4488447891fSMichael Ellerman { 4498b88b099SChristoph Hellwig *val = *(u64 *)data; 4508b88b099SChristoph Hellwig return 0; 4518447891fSMichael Ellerman } 4528447891fSMichael Ellerman DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); 453e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n"); 454e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); 4558447891fSMichael Ellerman 4568447891fSMichael Ellerman /** 4578447891fSMichael Ellerman * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value 4588447891fSMichael Ellerman * @name: a pointer to a string containing the name of the file to create. 4598447891fSMichael Ellerman * @mode: the permission that the file should have 4608447891fSMichael Ellerman * @parent: a pointer to the parent dentry for this file. This should be a 4618447891fSMichael Ellerman * directory dentry if set. If this parameter is %NULL, then the 4628447891fSMichael Ellerman * file will be created in the root of the debugfs filesystem. 4638447891fSMichael Ellerman * @value: a pointer to the variable that the file should read to and write 4648447891fSMichael Ellerman * from. 4658447891fSMichael Ellerman * 4668447891fSMichael Ellerman * This function creates a file in debugfs with the given name that 4678447891fSMichael Ellerman * contains the value of the variable @value. If the @mode variable is so 4688447891fSMichael Ellerman * set, it can be read from, and written to. 4698447891fSMichael Ellerman * 4708447891fSMichael Ellerman * This function will return a pointer to a dentry if it succeeds. This 4718447891fSMichael Ellerman * pointer must be passed to the debugfs_remove() function when the file is 4728447891fSMichael Ellerman * to be removed (no automatic cleanup happens if your module is unloaded, 4738447891fSMichael Ellerman * you are responsible here.) If an error occurs, %NULL will be returned. 4748447891fSMichael Ellerman * 4758447891fSMichael Ellerman * If debugfs is not enabled in the kernel, the value -%ENODEV will be 4768447891fSMichael Ellerman * returned. It is not wise to check for this value, but rather, check for 4778447891fSMichael Ellerman * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 4788447891fSMichael Ellerman * code. 4798447891fSMichael Ellerman */ 480f4ae40a6SAl Viro struct dentry *debugfs_create_u64(const char *name, umode_t mode, 4818447891fSMichael Ellerman struct dentry *parent, u64 *value) 4828447891fSMichael Ellerman { 483b97f6799SStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_u64, 484b97f6799SStephen Boyd &fops_u64_ro, &fops_u64_wo); 4858447891fSMichael Ellerman } 4868447891fSMichael Ellerman EXPORT_SYMBOL_GPL(debugfs_create_u64); 4878447891fSMichael Ellerman 488c23fe831SViresh Kumar static int debugfs_ulong_set(void *data, u64 val) 489c23fe831SViresh Kumar { 490c23fe831SViresh Kumar *(unsigned long *)data = val; 491c23fe831SViresh Kumar return 0; 492c23fe831SViresh Kumar } 493c23fe831SViresh Kumar 494c23fe831SViresh Kumar static int debugfs_ulong_get(void *data, u64 *val) 495c23fe831SViresh Kumar { 496c23fe831SViresh Kumar *val = *(unsigned long *)data; 497c23fe831SViresh Kumar return 0; 498c23fe831SViresh Kumar } 499c23fe831SViresh Kumar DEFINE_SIMPLE_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set, "%llu\n"); 500c23fe831SViresh Kumar DEFINE_SIMPLE_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n"); 501c23fe831SViresh Kumar DEFINE_SIMPLE_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n"); 502c23fe831SViresh Kumar 503c23fe831SViresh Kumar /** 504c23fe831SViresh Kumar * debugfs_create_ulong - create a debugfs file that is used to read and write 505c23fe831SViresh Kumar * an unsigned long value. 506c23fe831SViresh Kumar * @name: a pointer to a string containing the name of the file to create. 507c23fe831SViresh Kumar * @mode: the permission that the file should have 508c23fe831SViresh Kumar * @parent: a pointer to the parent dentry for this file. This should be a 509c23fe831SViresh Kumar * directory dentry if set. If this parameter is %NULL, then the 510c23fe831SViresh Kumar * file will be created in the root of the debugfs filesystem. 511c23fe831SViresh Kumar * @value: a pointer to the variable that the file should read to and write 512c23fe831SViresh Kumar * from. 513c23fe831SViresh Kumar * 514c23fe831SViresh Kumar * This function creates a file in debugfs with the given name that 515c23fe831SViresh Kumar * contains the value of the variable @value. If the @mode variable is so 516c23fe831SViresh Kumar * set, it can be read from, and written to. 517c23fe831SViresh Kumar * 518c23fe831SViresh Kumar * This function will return a pointer to a dentry if it succeeds. This 519c23fe831SViresh Kumar * pointer must be passed to the debugfs_remove() function when the file is 520c23fe831SViresh Kumar * to be removed (no automatic cleanup happens if your module is unloaded, 521c23fe831SViresh Kumar * you are responsible here.) If an error occurs, %NULL will be returned. 522c23fe831SViresh Kumar * 523c23fe831SViresh Kumar * If debugfs is not enabled in the kernel, the value -%ENODEV will be 524c23fe831SViresh Kumar * returned. It is not wise to check for this value, but rather, check for 525c23fe831SViresh Kumar * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 526c23fe831SViresh Kumar * code. 527c23fe831SViresh Kumar */ 528c23fe831SViresh Kumar struct dentry *debugfs_create_ulong(const char *name, umode_t mode, 529c23fe831SViresh Kumar struct dentry *parent, unsigned long *value) 530c23fe831SViresh Kumar { 531c23fe831SViresh Kumar return debugfs_create_mode(name, mode, parent, value, &fops_ulong, 532c23fe831SViresh Kumar &fops_ulong_ro, &fops_ulong_wo); 533c23fe831SViresh Kumar } 534c23fe831SViresh Kumar EXPORT_SYMBOL_GPL(debugfs_create_ulong); 535c23fe831SViresh Kumar 5362ebefc50SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); 537e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n"); 538e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n"); 5392ebefc50SRobin Getz 5402ebefc50SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"); 541e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n"); 542e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n"); 5432ebefc50SRobin Getz 5442ebefc50SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n"); 545e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n"); 546e4792aa3SRobin Getz DEFINE_SIMPLE_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n"); 5472ebefc50SRobin Getz 54815b0beaaSHuang Ying DEFINE_SIMPLE_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, "0x%016llx\n"); 54982b7d4fbSStephen Boyd DEFINE_SIMPLE_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n"); 55082b7d4fbSStephen Boyd DEFINE_SIMPLE_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n"); 55115b0beaaSHuang Ying 552e6716b87SRandy Dunlap /* 55315b0beaaSHuang 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 554e6716b87SRandy Dunlap * 555e6716b87SRandy Dunlap * These functions are exactly the same as the above functions (but use a hex 556e6716b87SRandy Dunlap * output for the decimal challenged). For details look at the above unsigned 557e6716b87SRandy Dunlap * decimal functions. 558e6716b87SRandy Dunlap */ 559e6716b87SRandy Dunlap 5602ebefc50SRobin Getz /** 5612ebefc50SRobin Getz * debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8-bit value 562e6716b87SRandy Dunlap * @name: a pointer to a string containing the name of the file to create. 563e6716b87SRandy Dunlap * @mode: the permission that the file should have 564e6716b87SRandy Dunlap * @parent: a pointer to the parent dentry for this file. This should be a 565e6716b87SRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 566e6716b87SRandy Dunlap * file will be created in the root of the debugfs filesystem. 567e6716b87SRandy Dunlap * @value: a pointer to the variable that the file should read to and write 568e6716b87SRandy Dunlap * from. 5692ebefc50SRobin Getz */ 570f4ae40a6SAl Viro struct dentry *debugfs_create_x8(const char *name, umode_t mode, 5712ebefc50SRobin Getz struct dentry *parent, u8 *value) 5722ebefc50SRobin Getz { 573b97f6799SStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_x8, 574b97f6799SStephen Boyd &fops_x8_ro, &fops_x8_wo); 5752ebefc50SRobin Getz } 5762ebefc50SRobin Getz EXPORT_SYMBOL_GPL(debugfs_create_x8); 5772ebefc50SRobin Getz 578e6716b87SRandy Dunlap /** 579e6716b87SRandy Dunlap * debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16-bit value 580e6716b87SRandy Dunlap * @name: a pointer to a string containing the name of the file to create. 581e6716b87SRandy Dunlap * @mode: the permission that the file should have 582e6716b87SRandy Dunlap * @parent: a pointer to the parent dentry for this file. This should be a 583e6716b87SRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 584e6716b87SRandy Dunlap * file will be created in the root of the debugfs filesystem. 585e6716b87SRandy Dunlap * @value: a pointer to the variable that the file should read to and write 586e6716b87SRandy Dunlap * from. 587e6716b87SRandy Dunlap */ 588f4ae40a6SAl Viro struct dentry *debugfs_create_x16(const char *name, umode_t mode, 5892ebefc50SRobin Getz struct dentry *parent, u16 *value) 5902ebefc50SRobin Getz { 591b97f6799SStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_x16, 592b97f6799SStephen Boyd &fops_x16_ro, &fops_x16_wo); 5932ebefc50SRobin Getz } 5942ebefc50SRobin Getz EXPORT_SYMBOL_GPL(debugfs_create_x16); 5952ebefc50SRobin Getz 596e6716b87SRandy Dunlap /** 597e6716b87SRandy Dunlap * debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32-bit value 598e6716b87SRandy Dunlap * @name: a pointer to a string containing the name of the file to create. 599e6716b87SRandy Dunlap * @mode: the permission that the file should have 600e6716b87SRandy Dunlap * @parent: a pointer to the parent dentry for this file. This should be a 601e6716b87SRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 602e6716b87SRandy Dunlap * file will be created in the root of the debugfs filesystem. 603e6716b87SRandy Dunlap * @value: a pointer to the variable that the file should read to and write 604e6716b87SRandy Dunlap * from. 605e6716b87SRandy Dunlap */ 606f4ae40a6SAl Viro struct dentry *debugfs_create_x32(const char *name, umode_t mode, 6072ebefc50SRobin Getz struct dentry *parent, u32 *value) 6082ebefc50SRobin Getz { 609b97f6799SStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_x32, 610b97f6799SStephen Boyd &fops_x32_ro, &fops_x32_wo); 6112ebefc50SRobin Getz } 6122ebefc50SRobin Getz EXPORT_SYMBOL_GPL(debugfs_create_x32); 6132ebefc50SRobin Getz 61415b0beaaSHuang Ying /** 61515b0beaaSHuang Ying * debugfs_create_x64 - create a debugfs file that is used to read and write an unsigned 64-bit value 61615b0beaaSHuang Ying * @name: a pointer to a string containing the name of the file to create. 61715b0beaaSHuang Ying * @mode: the permission that the file should have 61815b0beaaSHuang Ying * @parent: a pointer to the parent dentry for this file. This should be a 61915b0beaaSHuang Ying * directory dentry if set. If this parameter is %NULL, then the 62015b0beaaSHuang Ying * file will be created in the root of the debugfs filesystem. 62115b0beaaSHuang Ying * @value: a pointer to the variable that the file should read to and write 62215b0beaaSHuang Ying * from. 62315b0beaaSHuang Ying */ 624f4ae40a6SAl Viro struct dentry *debugfs_create_x64(const char *name, umode_t mode, 62515b0beaaSHuang Ying struct dentry *parent, u64 *value) 62615b0beaaSHuang Ying { 62782b7d4fbSStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_x64, 62882b7d4fbSStephen Boyd &fops_x64_ro, &fops_x64_wo); 62915b0beaaSHuang Ying } 63015b0beaaSHuang Ying EXPORT_SYMBOL_GPL(debugfs_create_x64); 63115b0beaaSHuang Ying 6325e078787SInaky Perez-Gonzalez 6335e078787SInaky Perez-Gonzalez static int debugfs_size_t_set(void *data, u64 val) 6345e078787SInaky Perez-Gonzalez { 6355e078787SInaky Perez-Gonzalez *(size_t *)data = val; 6365e078787SInaky Perez-Gonzalez return 0; 6375e078787SInaky Perez-Gonzalez } 6385e078787SInaky Perez-Gonzalez static int debugfs_size_t_get(void *data, u64 *val) 6395e078787SInaky Perez-Gonzalez { 6405e078787SInaky Perez-Gonzalez *val = *(size_t *)data; 6415e078787SInaky Perez-Gonzalez return 0; 6425e078787SInaky Perez-Gonzalez } 6435e078787SInaky Perez-Gonzalez DEFINE_SIMPLE_ATTRIBUTE(fops_size_t, debugfs_size_t_get, debugfs_size_t_set, 6445e078787SInaky Perez-Gonzalez "%llu\n"); /* %llu and %zu are more or less the same */ 6456db6652aSStephen Boyd DEFINE_SIMPLE_ATTRIBUTE(fops_size_t_ro, debugfs_size_t_get, NULL, "%llu\n"); 6466db6652aSStephen Boyd DEFINE_SIMPLE_ATTRIBUTE(fops_size_t_wo, NULL, debugfs_size_t_set, "%llu\n"); 6475e078787SInaky Perez-Gonzalez 6485e078787SInaky Perez-Gonzalez /** 6495e078787SInaky Perez-Gonzalez * debugfs_create_size_t - create a debugfs file that is used to read and write an size_t value 6505e078787SInaky Perez-Gonzalez * @name: a pointer to a string containing the name of the file to create. 6515e078787SInaky Perez-Gonzalez * @mode: the permission that the file should have 6525e078787SInaky Perez-Gonzalez * @parent: a pointer to the parent dentry for this file. This should be a 6535e078787SInaky Perez-Gonzalez * directory dentry if set. If this parameter is %NULL, then the 6545e078787SInaky Perez-Gonzalez * file will be created in the root of the debugfs filesystem. 6555e078787SInaky Perez-Gonzalez * @value: a pointer to the variable that the file should read to and write 6565e078787SInaky Perez-Gonzalez * from. 6575e078787SInaky Perez-Gonzalez */ 658f4ae40a6SAl Viro struct dentry *debugfs_create_size_t(const char *name, umode_t mode, 6595e078787SInaky Perez-Gonzalez struct dentry *parent, size_t *value) 6605e078787SInaky Perez-Gonzalez { 6616db6652aSStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_size_t, 6626db6652aSStephen Boyd &fops_size_t_ro, &fops_size_t_wo); 6635e078787SInaky Perez-Gonzalez } 6645e078787SInaky Perez-Gonzalez EXPORT_SYMBOL_GPL(debugfs_create_size_t); 6655e078787SInaky Perez-Gonzalez 6663a76e5e0SSeth Jennings static int debugfs_atomic_t_set(void *data, u64 val) 6673a76e5e0SSeth Jennings { 6683a76e5e0SSeth Jennings atomic_set((atomic_t *)data, val); 6693a76e5e0SSeth Jennings return 0; 6703a76e5e0SSeth Jennings } 6713a76e5e0SSeth Jennings static int debugfs_atomic_t_get(void *data, u64 *val) 6723a76e5e0SSeth Jennings { 6733a76e5e0SSeth Jennings *val = atomic_read((atomic_t *)data); 6743a76e5e0SSeth Jennings return 0; 6753a76e5e0SSeth Jennings } 6763a76e5e0SSeth Jennings DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, 6773a76e5e0SSeth Jennings debugfs_atomic_t_set, "%lld\n"); 6783a76e5e0SSeth Jennings DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, "%lld\n"); 6793a76e5e0SSeth Jennings DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%lld\n"); 6803a76e5e0SSeth Jennings 6813a76e5e0SSeth Jennings /** 6823a76e5e0SSeth Jennings * debugfs_create_atomic_t - create a debugfs file that is used to read and 6833a76e5e0SSeth Jennings * write an atomic_t value 6843a76e5e0SSeth Jennings * @name: a pointer to a string containing the name of the file to create. 6853a76e5e0SSeth Jennings * @mode: the permission that the file should have 6863a76e5e0SSeth Jennings * @parent: a pointer to the parent dentry for this file. This should be a 6873a76e5e0SSeth Jennings * directory dentry if set. If this parameter is %NULL, then the 6883a76e5e0SSeth Jennings * file will be created in the root of the debugfs filesystem. 6893a76e5e0SSeth Jennings * @value: a pointer to the variable that the file should read to and write 6903a76e5e0SSeth Jennings * from. 6913a76e5e0SSeth Jennings */ 6923a76e5e0SSeth Jennings struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode, 6933a76e5e0SSeth Jennings struct dentry *parent, atomic_t *value) 6943a76e5e0SSeth Jennings { 695b97f6799SStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_atomic_t, 696b97f6799SStephen Boyd &fops_atomic_t_ro, &fops_atomic_t_wo); 6973a76e5e0SSeth Jennings } 6983a76e5e0SSeth Jennings EXPORT_SYMBOL_GPL(debugfs_create_atomic_t); 6995e078787SInaky Perez-Gonzalez 7000642ef6fSRichard Fitzgerald ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf, 7011da177e4SLinus Torvalds size_t count, loff_t *ppos) 7021da177e4SLinus Torvalds { 7031da177e4SLinus Torvalds char buf[3]; 704621a5f7aSViresh Kumar bool *val = file->private_data; 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds if (*val) 7071da177e4SLinus Torvalds buf[0] = 'Y'; 7081da177e4SLinus Torvalds else 7091da177e4SLinus Torvalds buf[0] = 'N'; 7101da177e4SLinus Torvalds buf[1] = '\n'; 7111da177e4SLinus Torvalds buf[2] = 0x00; 7121da177e4SLinus Torvalds return simple_read_from_buffer(user_buf, count, ppos, buf, 2); 7131da177e4SLinus Torvalds } 7140642ef6fSRichard Fitzgerald EXPORT_SYMBOL_GPL(debugfs_read_file_bool); 7151da177e4SLinus Torvalds 7160642ef6fSRichard Fitzgerald ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, 7171da177e4SLinus Torvalds size_t count, loff_t *ppos) 7181da177e4SLinus Torvalds { 7191da177e4SLinus Torvalds char buf[32]; 720c42d2237SStephen Boyd size_t buf_size; 7218705b48eSJonathan Cameron bool bv; 722621a5f7aSViresh Kumar bool *val = file->private_data; 7231da177e4SLinus Torvalds 7241da177e4SLinus Torvalds buf_size = min(count, (sizeof(buf)-1)); 7251da177e4SLinus Torvalds if (copy_from_user(buf, user_buf, buf_size)) 7261da177e4SLinus Torvalds return -EFAULT; 7271da177e4SLinus Torvalds 728a3b2c8c7SMathias Krause buf[buf_size] = '\0'; 7298705b48eSJonathan Cameron if (strtobool(buf, &bv) == 0) 7308705b48eSJonathan Cameron *val = bv; 7311da177e4SLinus Torvalds 7321da177e4SLinus Torvalds return count; 7331da177e4SLinus Torvalds } 7340642ef6fSRichard Fitzgerald EXPORT_SYMBOL_GPL(debugfs_write_file_bool); 7351da177e4SLinus Torvalds 7364b6f5d20SArjan van de Ven static const struct file_operations fops_bool = { 7370642ef6fSRichard Fitzgerald .read = debugfs_read_file_bool, 7380642ef6fSRichard Fitzgerald .write = debugfs_write_file_bool, 739234e3405SStephen Boyd .open = simple_open, 7406038f373SArnd Bergmann .llseek = default_llseek, 7411da177e4SLinus Torvalds }; 7421da177e4SLinus Torvalds 7436713e8fbSStephen Boyd static const struct file_operations fops_bool_ro = { 7446713e8fbSStephen Boyd .read = debugfs_read_file_bool, 7456713e8fbSStephen Boyd .open = simple_open, 7466713e8fbSStephen Boyd .llseek = default_llseek, 7476713e8fbSStephen Boyd }; 7486713e8fbSStephen Boyd 7496713e8fbSStephen Boyd static const struct file_operations fops_bool_wo = { 7506713e8fbSStephen Boyd .write = debugfs_write_file_bool, 7516713e8fbSStephen Boyd .open = simple_open, 7526713e8fbSStephen Boyd .llseek = default_llseek, 7536713e8fbSStephen Boyd }; 7546713e8fbSStephen Boyd 7551da177e4SLinus Torvalds /** 7566468b3afSRandy Dunlap * debugfs_create_bool - create a debugfs file that is used to read and write a boolean value 7571da177e4SLinus Torvalds * @name: a pointer to a string containing the name of the file to create. 7581da177e4SLinus Torvalds * @mode: the permission that the file should have 7591da177e4SLinus Torvalds * @parent: a pointer to the parent dentry for this file. This should be a 7606468b3afSRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 7611da177e4SLinus Torvalds * file will be created in the root of the debugfs filesystem. 7621da177e4SLinus Torvalds * @value: a pointer to the variable that the file should read to and write 7631da177e4SLinus Torvalds * from. 7641da177e4SLinus Torvalds * 7651da177e4SLinus Torvalds * This function creates a file in debugfs with the given name that 7661da177e4SLinus Torvalds * contains the value of the variable @value. If the @mode variable is so 7671da177e4SLinus Torvalds * set, it can be read from, and written to. 7681da177e4SLinus Torvalds * 7691da177e4SLinus Torvalds * This function will return a pointer to a dentry if it succeeds. This 7701da177e4SLinus Torvalds * pointer must be passed to the debugfs_remove() function when the file is 7711da177e4SLinus Torvalds * to be removed (no automatic cleanup happens if your module is unloaded, 7726468b3afSRandy Dunlap * you are responsible here.) If an error occurs, %NULL will be returned. 7731da177e4SLinus Torvalds * 7746468b3afSRandy Dunlap * If debugfs is not enabled in the kernel, the value -%ENODEV will be 7751da177e4SLinus Torvalds * returned. It is not wise to check for this value, but rather, check for 7766468b3afSRandy Dunlap * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 7771da177e4SLinus Torvalds * code. 7781da177e4SLinus Torvalds */ 779f4ae40a6SAl Viro struct dentry *debugfs_create_bool(const char *name, umode_t mode, 780621a5f7aSViresh Kumar struct dentry *parent, bool *value) 7811da177e4SLinus Torvalds { 7826713e8fbSStephen Boyd return debugfs_create_mode(name, mode, parent, value, &fops_bool, 7836713e8fbSStephen Boyd &fops_bool_ro, &fops_bool_wo); 7841da177e4SLinus Torvalds } 7851da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_bool); 7861da177e4SLinus Torvalds 787dd308bc3SMichael Ellerman static ssize_t read_file_blob(struct file *file, char __user *user_buf, 788dd308bc3SMichael Ellerman size_t count, loff_t *ppos) 789dd308bc3SMichael Ellerman { 790dd308bc3SMichael Ellerman struct debugfs_blob_wrapper *blob = file->private_data; 791dd308bc3SMichael Ellerman return simple_read_from_buffer(user_buf, count, ppos, blob->data, 792dd308bc3SMichael Ellerman blob->size); 793dd308bc3SMichael Ellerman } 794dd308bc3SMichael Ellerman 79500977a59SArjan van de Ven static const struct file_operations fops_blob = { 796dd308bc3SMichael Ellerman .read = read_file_blob, 797234e3405SStephen Boyd .open = simple_open, 7986038f373SArnd Bergmann .llseek = default_llseek, 799dd308bc3SMichael Ellerman }; 800dd308bc3SMichael Ellerman 801dd308bc3SMichael Ellerman /** 802400ced61SJonathan Corbet * debugfs_create_blob - create a debugfs file that is used to read a binary blob 803dd308bc3SMichael Ellerman * @name: a pointer to a string containing the name of the file to create. 804dd308bc3SMichael Ellerman * @mode: the permission that the file should have 805dd308bc3SMichael Ellerman * @parent: a pointer to the parent dentry for this file. This should be a 8066468b3afSRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 807dd308bc3SMichael Ellerman * file will be created in the root of the debugfs filesystem. 808dd308bc3SMichael Ellerman * @blob: a pointer to a struct debugfs_blob_wrapper which contains a pointer 809dd308bc3SMichael Ellerman * to the blob data and the size of the data. 810dd308bc3SMichael Ellerman * 811dd308bc3SMichael Ellerman * This function creates a file in debugfs with the given name that exports 812dd308bc3SMichael Ellerman * @blob->data as a binary blob. If the @mode variable is so set it can be 813dd308bc3SMichael Ellerman * read from. Writing is not supported. 814dd308bc3SMichael Ellerman * 815dd308bc3SMichael Ellerman * This function will return a pointer to a dentry if it succeeds. This 816dd308bc3SMichael Ellerman * pointer must be passed to the debugfs_remove() function when the file is 817dd308bc3SMichael Ellerman * to be removed (no automatic cleanup happens if your module is unloaded, 8186468b3afSRandy Dunlap * you are responsible here.) If an error occurs, %NULL will be returned. 819dd308bc3SMichael Ellerman * 8206468b3afSRandy Dunlap * If debugfs is not enabled in the kernel, the value -%ENODEV will be 821dd308bc3SMichael Ellerman * returned. It is not wise to check for this value, but rather, check for 8226468b3afSRandy Dunlap * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 823dd308bc3SMichael Ellerman * code. 824dd308bc3SMichael Ellerman */ 825f4ae40a6SAl Viro struct dentry *debugfs_create_blob(const char *name, umode_t mode, 826dd308bc3SMichael Ellerman struct dentry *parent, 827dd308bc3SMichael Ellerman struct debugfs_blob_wrapper *blob) 828dd308bc3SMichael Ellerman { 829dd308bc3SMichael Ellerman return debugfs_create_file(name, mode, parent, blob, &fops_blob); 830dd308bc3SMichael Ellerman } 831dd308bc3SMichael Ellerman EXPORT_SYMBOL_GPL(debugfs_create_blob); 8321a087c6aSAlessandro Rubini 8339fe2a701SSrivatsa Vaddagiri struct array_data { 8349fe2a701SSrivatsa Vaddagiri void *array; 8359fe2a701SSrivatsa Vaddagiri u32 elements; 8369fe2a701SSrivatsa Vaddagiri }; 8379fe2a701SSrivatsa Vaddagiri 838e05e279eSLinus Torvalds static size_t u32_format_array(char *buf, size_t bufsize, 839e05e279eSLinus Torvalds u32 *array, int array_size) 8409fe2a701SSrivatsa Vaddagiri { 8419fe2a701SSrivatsa Vaddagiri size_t ret = 0; 8429fe2a701SSrivatsa Vaddagiri 843e05e279eSLinus Torvalds while (--array_size >= 0) { 8449fe2a701SSrivatsa Vaddagiri size_t len; 845e05e279eSLinus Torvalds char term = array_size ? ' ' : '\n'; 8469fe2a701SSrivatsa Vaddagiri 847e05e279eSLinus Torvalds len = snprintf(buf, bufsize, "%u%c", *array++, term); 8489fe2a701SSrivatsa Vaddagiri ret += len; 8499fe2a701SSrivatsa Vaddagiri 8509fe2a701SSrivatsa Vaddagiri buf += len; 8519fe2a701SSrivatsa Vaddagiri bufsize -= len; 8529fe2a701SSrivatsa Vaddagiri } 8539fe2a701SSrivatsa Vaddagiri return ret; 8549fe2a701SSrivatsa Vaddagiri } 8559fe2a701SSrivatsa Vaddagiri 85636048853SDavid Rientjes static int u32_array_open(struct inode *inode, struct file *file) 8579fe2a701SSrivatsa Vaddagiri { 8589fe2a701SSrivatsa Vaddagiri struct array_data *data = inode->i_private; 859e05e279eSLinus Torvalds int size, elements = data->elements; 860e05e279eSLinus Torvalds char *buf; 8619fe2a701SSrivatsa Vaddagiri 862e05e279eSLinus Torvalds /* 863e05e279eSLinus Torvalds * Max size: 864e05e279eSLinus Torvalds * - 10 digits + ' '/'\n' = 11 bytes per number 865e05e279eSLinus Torvalds * - terminating NUL character 866e05e279eSLinus Torvalds */ 867e05e279eSLinus Torvalds size = elements*11; 868e05e279eSLinus Torvalds buf = kmalloc(size+1, GFP_KERNEL); 869e05e279eSLinus Torvalds if (!buf) 87036048853SDavid Rientjes return -ENOMEM; 871e05e279eSLinus Torvalds buf[size] = 0; 872e05e279eSLinus Torvalds 873e05e279eSLinus Torvalds file->private_data = buf; 874e05e279eSLinus Torvalds u32_format_array(buf, size, data->array, data->elements); 875e05e279eSLinus Torvalds 87636048853SDavid Rientjes return nonseekable_open(inode, file); 8779fe2a701SSrivatsa Vaddagiri } 8789fe2a701SSrivatsa Vaddagiri 87936048853SDavid Rientjes static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len, 88036048853SDavid Rientjes loff_t *ppos) 88136048853SDavid Rientjes { 88236048853SDavid Rientjes size_t size = strlen(file->private_data); 8839fe2a701SSrivatsa Vaddagiri 8849fe2a701SSrivatsa Vaddagiri return simple_read_from_buffer(buf, len, ppos, 8859fe2a701SSrivatsa Vaddagiri file->private_data, size); 8869fe2a701SSrivatsa Vaddagiri } 8879fe2a701SSrivatsa Vaddagiri 8889fe2a701SSrivatsa Vaddagiri static int u32_array_release(struct inode *inode, struct file *file) 8899fe2a701SSrivatsa Vaddagiri { 8909fe2a701SSrivatsa Vaddagiri kfree(file->private_data); 8919fe2a701SSrivatsa Vaddagiri 8929fe2a701SSrivatsa Vaddagiri return 0; 8939fe2a701SSrivatsa Vaddagiri } 8949fe2a701SSrivatsa Vaddagiri 8959fe2a701SSrivatsa Vaddagiri static const struct file_operations u32_array_fops = { 8969fe2a701SSrivatsa Vaddagiri .owner = THIS_MODULE, 8979fe2a701SSrivatsa Vaddagiri .open = u32_array_open, 8989fe2a701SSrivatsa Vaddagiri .release = u32_array_release, 8999fe2a701SSrivatsa Vaddagiri .read = u32_array_read, 9009fe2a701SSrivatsa Vaddagiri .llseek = no_llseek, 9019fe2a701SSrivatsa Vaddagiri }; 9029fe2a701SSrivatsa Vaddagiri 9039fe2a701SSrivatsa Vaddagiri /** 9049fe2a701SSrivatsa Vaddagiri * debugfs_create_u32_array - create a debugfs file that is used to read u32 9059fe2a701SSrivatsa Vaddagiri * array. 9069fe2a701SSrivatsa Vaddagiri * @name: a pointer to a string containing the name of the file to create. 9079fe2a701SSrivatsa Vaddagiri * @mode: the permission that the file should have. 9089fe2a701SSrivatsa Vaddagiri * @parent: a pointer to the parent dentry for this file. This should be a 9099fe2a701SSrivatsa Vaddagiri * directory dentry if set. If this parameter is %NULL, then the 9109fe2a701SSrivatsa Vaddagiri * file will be created in the root of the debugfs filesystem. 9119fe2a701SSrivatsa Vaddagiri * @array: u32 array that provides data. 9129fe2a701SSrivatsa Vaddagiri * @elements: total number of elements in the array. 9139fe2a701SSrivatsa Vaddagiri * 9149fe2a701SSrivatsa Vaddagiri * This function creates a file in debugfs with the given name that exports 9159fe2a701SSrivatsa Vaddagiri * @array as data. If the @mode variable is so set it can be read from. 9169fe2a701SSrivatsa Vaddagiri * Writing is not supported. Seek within the file is also not supported. 9179fe2a701SSrivatsa Vaddagiri * Once array is created its size can not be changed. 9189fe2a701SSrivatsa Vaddagiri * 9199fe2a701SSrivatsa Vaddagiri * The function returns a pointer to dentry on success. If debugfs is not 9209fe2a701SSrivatsa Vaddagiri * enabled in the kernel, the value -%ENODEV will be returned. 9219fe2a701SSrivatsa Vaddagiri */ 9229fe2a701SSrivatsa Vaddagiri struct dentry *debugfs_create_u32_array(const char *name, umode_t mode, 9239fe2a701SSrivatsa Vaddagiri struct dentry *parent, 9249fe2a701SSrivatsa Vaddagiri u32 *array, u32 elements) 9259fe2a701SSrivatsa Vaddagiri { 9269fe2a701SSrivatsa Vaddagiri struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL); 9279fe2a701SSrivatsa Vaddagiri 9289fe2a701SSrivatsa Vaddagiri if (data == NULL) 9299fe2a701SSrivatsa Vaddagiri return NULL; 9309fe2a701SSrivatsa Vaddagiri 9319fe2a701SSrivatsa Vaddagiri data->array = array; 9329fe2a701SSrivatsa Vaddagiri data->elements = elements; 9339fe2a701SSrivatsa Vaddagiri 9349fe2a701SSrivatsa Vaddagiri return debugfs_create_file(name, mode, parent, data, &u32_array_fops); 9359fe2a701SSrivatsa Vaddagiri } 9369fe2a701SSrivatsa Vaddagiri EXPORT_SYMBOL_GPL(debugfs_create_u32_array); 9379fe2a701SSrivatsa Vaddagiri 9383b85e4abSHeiko Carstens #ifdef CONFIG_HAS_IOMEM 9393b85e4abSHeiko Carstens 9401a087c6aSAlessandro Rubini /* 9411a087c6aSAlessandro Rubini * The regset32 stuff is used to print 32-bit registers using the 9421a087c6aSAlessandro Rubini * seq_file utilities. We offer printing a register set in an already-opened 9431a087c6aSAlessandro Rubini * sequential file or create a debugfs file that only prints a regset32. 9441a087c6aSAlessandro Rubini */ 9451a087c6aSAlessandro Rubini 9461a087c6aSAlessandro Rubini /** 9471a087c6aSAlessandro Rubini * debugfs_print_regs32 - use seq_print to describe a set of registers 9481a087c6aSAlessandro Rubini * @s: the seq_file structure being used to generate output 9491a087c6aSAlessandro Rubini * @regs: an array if struct debugfs_reg32 structures 950b5763accSRandy Dunlap * @nregs: the length of the above array 9511a087c6aSAlessandro Rubini * @base: the base address to be used in reading the registers 9521a087c6aSAlessandro Rubini * @prefix: a string to be prefixed to every output line 9531a087c6aSAlessandro Rubini * 9541a087c6aSAlessandro Rubini * This function outputs a text block describing the current values of 9551a087c6aSAlessandro Rubini * some 32-bit hardware registers. It is meant to be used within debugfs 9561a087c6aSAlessandro Rubini * files based on seq_file that need to show registers, intermixed with other 9571a087c6aSAlessandro Rubini * information. The prefix argument may be used to specify a leading string, 9581a087c6aSAlessandro Rubini * because some peripherals have several blocks of identical registers, 9591a087c6aSAlessandro Rubini * for example configuration of dma channels 9601a087c6aSAlessandro Rubini */ 9619761536eSJoe Perches void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs, 9621a087c6aSAlessandro Rubini int nregs, void __iomem *base, char *prefix) 9631a087c6aSAlessandro Rubini { 9649761536eSJoe Perches int i; 9651a087c6aSAlessandro Rubini 9661a087c6aSAlessandro Rubini for (i = 0; i < nregs; i++, regs++) { 9671a087c6aSAlessandro Rubini if (prefix) 9689761536eSJoe Perches seq_printf(s, "%s", prefix); 9699761536eSJoe Perches seq_printf(s, "%s = 0x%08x\n", regs->name, 9705858441cSDan Carpenter readl(base + regs->offset)); 9719761536eSJoe Perches if (seq_has_overflowed(s)) 9729761536eSJoe Perches break; 9731a087c6aSAlessandro Rubini } 9741a087c6aSAlessandro Rubini } 9751a087c6aSAlessandro Rubini EXPORT_SYMBOL_GPL(debugfs_print_regs32); 9761a087c6aSAlessandro Rubini 9771a087c6aSAlessandro Rubini static int debugfs_show_regset32(struct seq_file *s, void *data) 9781a087c6aSAlessandro Rubini { 9791a087c6aSAlessandro Rubini struct debugfs_regset32 *regset = s->private; 9801a087c6aSAlessandro Rubini 9811a087c6aSAlessandro Rubini debugfs_print_regs32(s, regset->regs, regset->nregs, regset->base, ""); 9821a087c6aSAlessandro Rubini return 0; 9831a087c6aSAlessandro Rubini } 9841a087c6aSAlessandro Rubini 9851a087c6aSAlessandro Rubini static int debugfs_open_regset32(struct inode *inode, struct file *file) 9861a087c6aSAlessandro Rubini { 9871a087c6aSAlessandro Rubini return single_open(file, debugfs_show_regset32, inode->i_private); 9881a087c6aSAlessandro Rubini } 9891a087c6aSAlessandro Rubini 9901a087c6aSAlessandro Rubini static const struct file_operations fops_regset32 = { 9911a087c6aSAlessandro Rubini .open = debugfs_open_regset32, 9921a087c6aSAlessandro Rubini .read = seq_read, 9931a087c6aSAlessandro Rubini .llseek = seq_lseek, 9941a087c6aSAlessandro Rubini .release = single_release, 9951a087c6aSAlessandro Rubini }; 9961a087c6aSAlessandro Rubini 9971a087c6aSAlessandro Rubini /** 9981a087c6aSAlessandro Rubini * debugfs_create_regset32 - create a debugfs file that returns register values 9991a087c6aSAlessandro Rubini * @name: a pointer to a string containing the name of the file to create. 10001a087c6aSAlessandro Rubini * @mode: the permission that the file should have 10011a087c6aSAlessandro Rubini * @parent: a pointer to the parent dentry for this file. This should be a 10021a087c6aSAlessandro Rubini * directory dentry if set. If this parameter is %NULL, then the 10031a087c6aSAlessandro Rubini * file will be created in the root of the debugfs filesystem. 10041a087c6aSAlessandro Rubini * @regset: a pointer to a struct debugfs_regset32, which contains a pointer 10051a087c6aSAlessandro Rubini * to an array of register definitions, the array size and the base 10061a087c6aSAlessandro Rubini * address where the register bank is to be found. 10071a087c6aSAlessandro Rubini * 10081a087c6aSAlessandro Rubini * This function creates a file in debugfs with the given name that reports 10091a087c6aSAlessandro Rubini * the names and values of a set of 32-bit registers. If the @mode variable 10101a087c6aSAlessandro Rubini * is so set it can be read from. Writing is not supported. 10111a087c6aSAlessandro Rubini * 10121a087c6aSAlessandro Rubini * This function will return a pointer to a dentry if it succeeds. This 10131a087c6aSAlessandro Rubini * pointer must be passed to the debugfs_remove() function when the file is 10141a087c6aSAlessandro Rubini * to be removed (no automatic cleanup happens if your module is unloaded, 10151a087c6aSAlessandro Rubini * you are responsible here.) If an error occurs, %NULL will be returned. 10161a087c6aSAlessandro Rubini * 10171a087c6aSAlessandro Rubini * If debugfs is not enabled in the kernel, the value -%ENODEV will be 10181a087c6aSAlessandro Rubini * returned. It is not wise to check for this value, but rather, check for 10191a087c6aSAlessandro Rubini * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 10201a087c6aSAlessandro Rubini * code. 10211a087c6aSAlessandro Rubini */ 102288187398SAl Viro struct dentry *debugfs_create_regset32(const char *name, umode_t mode, 10231a087c6aSAlessandro Rubini struct dentry *parent, 10241a087c6aSAlessandro Rubini struct debugfs_regset32 *regset) 10251a087c6aSAlessandro Rubini { 10261a087c6aSAlessandro Rubini return debugfs_create_file(name, mode, parent, regset, &fops_regset32); 10271a087c6aSAlessandro Rubini } 10281a087c6aSAlessandro Rubini EXPORT_SYMBOL_GPL(debugfs_create_regset32); 10293b85e4abSHeiko Carstens 10303b85e4abSHeiko Carstens #endif /* CONFIG_HAS_IOMEM */ 103198210b7fSArend van Spriel 103298210b7fSArend van Spriel struct debugfs_devm_entry { 103398210b7fSArend van Spriel int (*read)(struct seq_file *seq, void *data); 103498210b7fSArend van Spriel struct device *dev; 103598210b7fSArend van Spriel }; 103698210b7fSArend van Spriel 103798210b7fSArend van Spriel static int debugfs_devm_entry_open(struct inode *inode, struct file *f) 103898210b7fSArend van Spriel { 103998210b7fSArend van Spriel struct debugfs_devm_entry *entry = inode->i_private; 104098210b7fSArend van Spriel 104198210b7fSArend van Spriel return single_open(f, entry->read, entry->dev); 104298210b7fSArend van Spriel } 104398210b7fSArend van Spriel 104498210b7fSArend van Spriel static const struct file_operations debugfs_devm_entry_ops = { 104598210b7fSArend van Spriel .owner = THIS_MODULE, 104698210b7fSArend van Spriel .open = debugfs_devm_entry_open, 104798210b7fSArend van Spriel .release = single_release, 104898210b7fSArend van Spriel .read = seq_read, 104998210b7fSArend van Spriel .llseek = seq_lseek 105098210b7fSArend van Spriel }; 105198210b7fSArend van Spriel 105298210b7fSArend van Spriel /** 105398210b7fSArend van Spriel * debugfs_create_devm_seqfile - create a debugfs file that is bound to device. 105498210b7fSArend van Spriel * 105598210b7fSArend van Spriel * @dev: device related to this debugfs file. 105698210b7fSArend van Spriel * @name: name of the debugfs file. 105798210b7fSArend van Spriel * @parent: a pointer to the parent dentry for this file. This should be a 105898210b7fSArend van Spriel * directory dentry if set. If this parameter is %NULL, then the 105998210b7fSArend van Spriel * file will be created in the root of the debugfs filesystem. 106098210b7fSArend van Spriel * @read_fn: function pointer called to print the seq_file content. 106198210b7fSArend van Spriel */ 106298210b7fSArend van Spriel struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name, 106398210b7fSArend van Spriel struct dentry *parent, 106498210b7fSArend van Spriel int (*read_fn)(struct seq_file *s, 106598210b7fSArend van Spriel void *data)) 106698210b7fSArend van Spriel { 106798210b7fSArend van Spriel struct debugfs_devm_entry *entry; 106898210b7fSArend van Spriel 106998210b7fSArend van Spriel if (IS_ERR(parent)) 107098210b7fSArend van Spriel return ERR_PTR(-ENOENT); 107198210b7fSArend van Spriel 107298210b7fSArend van Spriel entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); 107398210b7fSArend van Spriel if (!entry) 107498210b7fSArend van Spriel return ERR_PTR(-ENOMEM); 107598210b7fSArend van Spriel 107698210b7fSArend van Spriel entry->read = read_fn; 107798210b7fSArend van Spriel entry->dev = dev; 107898210b7fSArend van Spriel 107998210b7fSArend van Spriel return debugfs_create_file(name, S_IRUGO, parent, entry, 108098210b7fSArend van Spriel &debugfs_devm_entry_ops); 108198210b7fSArend van Spriel } 108298210b7fSArend van Spriel EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile); 108398210b7fSArend van Spriel 1084