2005-04-17 02:20:36 +04:00
/*
* file . c - part of debugfs , a tiny little debug file system
*
* Copyright ( C ) 2004 Greg Kroah - Hartman < greg @ kroah . com >
* Copyright ( C ) 2004 IBM Inc .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation .
*
* debugfs is for people to use instead of / proc or / sys .
* See Documentation / DocBook / kernel - api for more details .
*
*/
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/pagemap.h>
2007-02-13 14:13:54 +03:00
# include <linux/namei.h>
2005-04-17 02:20:36 +04:00
# include <linux/debugfs.h>
static ssize_t default_read_file ( struct file * file , char __user * buf ,
size_t count , loff_t * ppos )
{
return 0 ;
}
static ssize_t default_write_file ( struct file * file , const char __user * buf ,
size_t count , loff_t * ppos )
{
return count ;
}
static int default_open ( struct inode * inode , struct file * file )
{
2006-09-27 12:50:46 +04:00
if ( inode - > i_private )
file - > private_data = inode - > i_private ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-03-28 13:56:42 +04:00
const struct file_operations debugfs_file_operations = {
2005-04-17 02:20:36 +04:00
. read = default_read_file ,
. write = default_write_file ,
. open = default_open ,
} ;
2007-02-13 14:13:54 +03:00
static void * debugfs_follow_link ( struct dentry * dentry , struct nameidata * nd )
{
nd_set_link ( nd , dentry - > d_inode - > i_private ) ;
return NULL ;
}
const struct inode_operations debugfs_link_operations = {
. readlink = generic_readlink ,
. follow_link = debugfs_follow_link ,
} ;
2008-02-08 15:20:26 +03:00
static int debugfs_u8_set ( void * data , u64 val )
2005-05-18 16:40:59 +04:00
{
* ( u8 * ) data = val ;
2008-02-08 15:20:26 +03:00
return 0 ;
2005-05-18 16:40:59 +04:00
}
2008-02-08 15:20:26 +03:00
static int debugfs_u8_get ( void * data , u64 * val )
2005-05-18 16:40:59 +04:00
{
2008-02-08 15:20:26 +03:00
* val = * ( u8 * ) data ;
return 0 ;
2005-05-18 16:40:59 +04:00
}
DEFINE_SIMPLE_ATTRIBUTE ( fops_u8 , debugfs_u8_get , debugfs_u8_set , " %llu \n " ) ;
2005-04-17 02:20:36 +04:00
/**
2006-07-20 19:16:42 +04:00
* debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8 - bit value
2005-04-17 02:20:36 +04:00
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
2006-07-20 19:16:42 +04:00
* directory dentry if set . If this parameter is % NULL , then the
2005-04-17 02:20:36 +04:00
* file will be created in the root of the debugfs filesystem .
* @ value : a pointer to the variable that the file should read to and write
* from .
*
* This function creates a file in debugfs with the given name that
* contains the value of the variable @ value . If the @ mode variable is so
* set , it can be read from , and written to .
*
* This function will return a pointer to a dentry if it succeeds . This
* pointer must be passed to the debugfs_remove ( ) function when the file is
* to be removed ( no automatic cleanup happens if your module is unloaded ,
2006-07-20 19:16:42 +04:00
* you are responsible here . ) If an error occurs , % NULL will be returned .
2005-04-17 02:20:36 +04:00
*
2006-07-20 19:16:42 +04:00
* If debugfs is not enabled in the kernel , the value - % ENODEV will be
2005-04-17 02:20:36 +04:00
* returned . It is not wise to check for this value , but rather , check for
2006-07-20 19:16:42 +04:00
* % NULL or ! % NULL instead as to eliminate the need for # ifdef in the calling
2005-04-17 02:20:36 +04:00
* code .
*/
struct dentry * debugfs_create_u8 ( const char * name , mode_t mode ,
struct dentry * parent , u8 * value )
{
return debugfs_create_file ( name , mode , parent , value , & fops_u8 ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_u8 ) ;
2008-02-08 15:20:26 +03:00
static int debugfs_u16_set ( void * data , u64 val )
2005-05-18 16:40:59 +04:00
{
* ( u16 * ) data = val ;
2008-02-08 15:20:26 +03:00
return 0 ;
2005-05-18 16:40:59 +04:00
}
2008-02-08 15:20:26 +03:00
static int debugfs_u16_get ( void * data , u64 * val )
2005-05-18 16:40:59 +04:00
{
2008-02-08 15:20:26 +03:00
* val = * ( u16 * ) data ;
return 0 ;
2005-05-18 16:40:59 +04:00
}
DEFINE_SIMPLE_ATTRIBUTE ( fops_u16 , debugfs_u16_get , debugfs_u16_set , " %llu \n " ) ;
2005-04-17 02:20:36 +04:00
/**
2006-07-20 19:16:42 +04:00
* debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16 - bit value
2005-04-17 02:20:36 +04:00
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
2006-07-20 19:16:42 +04:00
* directory dentry if set . If this parameter is % NULL , then the
2005-04-17 02:20:36 +04:00
* file will be created in the root of the debugfs filesystem .
* @ value : a pointer to the variable that the file should read to and write
* from .
*
* This function creates a file in debugfs with the given name that
* contains the value of the variable @ value . If the @ mode variable is so
* set , it can be read from , and written to .
*
* This function will return a pointer to a dentry if it succeeds . This
* pointer must be passed to the debugfs_remove ( ) function when the file is
* to be removed ( no automatic cleanup happens if your module is unloaded ,
2006-07-20 19:16:42 +04:00
* you are responsible here . ) If an error occurs , % NULL will be returned .
2005-04-17 02:20:36 +04:00
*
2006-07-20 19:16:42 +04:00
* If debugfs is not enabled in the kernel , the value - % ENODEV will be
2005-04-17 02:20:36 +04:00
* returned . It is not wise to check for this value , but rather , check for
2006-07-20 19:16:42 +04:00
* % NULL or ! % NULL instead as to eliminate the need for # ifdef in the calling
2005-04-17 02:20:36 +04:00
* code .
*/
struct dentry * debugfs_create_u16 ( const char * name , mode_t mode ,
struct dentry * parent , u16 * value )
{
return debugfs_create_file ( name , mode , parent , value , & fops_u16 ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_u16 ) ;
2008-02-08 15:20:26 +03:00
static int debugfs_u32_set ( void * data , u64 val )
2005-05-18 16:40:59 +04:00
{
* ( u32 * ) data = val ;
2008-02-08 15:20:26 +03:00
return 0 ;
2005-05-18 16:40:59 +04:00
}
2008-02-08 15:20:26 +03:00
static int debugfs_u32_get ( void * data , u64 * val )
2005-05-18 16:40:59 +04:00
{
2008-02-08 15:20:26 +03:00
* val = * ( u32 * ) data ;
return 0 ;
2005-05-18 16:40:59 +04:00
}
DEFINE_SIMPLE_ATTRIBUTE ( fops_u32 , debugfs_u32_get , debugfs_u32_set , " %llu \n " ) ;
2005-04-17 02:20:36 +04:00
/**
2006-07-20 19:16:42 +04:00
* debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32 - bit value
2005-04-17 02:20:36 +04:00
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
2006-07-20 19:16:42 +04:00
* directory dentry if set . If this parameter is % NULL , then the
2005-04-17 02:20:36 +04:00
* file will be created in the root of the debugfs filesystem .
* @ value : a pointer to the variable that the file should read to and write
* from .
*
* This function creates a file in debugfs with the given name that
* contains the value of the variable @ value . If the @ mode variable is so
* set , it can be read from , and written to .
*
* This function will return a pointer to a dentry if it succeeds . This
* pointer must be passed to the debugfs_remove ( ) function when the file is
* to be removed ( no automatic cleanup happens if your module is unloaded ,
2006-07-20 19:16:42 +04:00
* you are responsible here . ) If an error occurs , % NULL will be returned .
2005-04-17 02:20:36 +04:00
*
2006-07-20 19:16:42 +04:00
* If debugfs is not enabled in the kernel , the value - % ENODEV will be
2005-04-17 02:20:36 +04:00
* returned . It is not wise to check for this value , but rather , check for
2006-07-20 19:16:42 +04:00
* % NULL or ! % NULL instead as to eliminate the need for # ifdef in the calling
2005-04-17 02:20:36 +04:00
* code .
*/
struct dentry * debugfs_create_u32 ( const char * name , mode_t mode ,
struct dentry * parent , u32 * value )
{
return debugfs_create_file ( name , mode , parent , value , & fops_u32 ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_u32 ) ;
2008-02-08 15:20:26 +03:00
static int debugfs_u64_set ( void * data , u64 val )
2007-04-17 09:59:36 +04:00
{
* ( u64 * ) data = val ;
2008-02-08 15:20:26 +03:00
return 0 ;
2007-04-17 09:59:36 +04:00
}
2008-02-08 15:20:26 +03:00
static int debugfs_u64_get ( void * data , u64 * val )
2007-04-17 09:59:36 +04:00
{
2008-02-08 15:20:26 +03:00
* val = * ( u64 * ) data ;
return 0 ;
2007-04-17 09:59:36 +04:00
}
DEFINE_SIMPLE_ATTRIBUTE ( fops_u64 , debugfs_u64_get , debugfs_u64_set , " %llu \n " ) ;
/**
* debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64 - bit value
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
* directory dentry if set . If this parameter is % NULL , then the
* file will be created in the root of the debugfs filesystem .
* @ value : a pointer to the variable that the file should read to and write
* from .
*
* This function creates a file in debugfs with the given name that
* contains the value of the variable @ value . If the @ mode variable is so
* set , it can be read from , and written to .
*
* This function will return a pointer to a dentry if it succeeds . This
* pointer must be passed to the debugfs_remove ( ) function when the file is
* to be removed ( no automatic cleanup happens if your module is unloaded ,
* you are responsible here . ) If an error occurs , % NULL will be returned .
*
* If debugfs is not enabled in the kernel , the value - % ENODEV will be
* returned . It is not wise to check for this value , but rather , check for
* % NULL or ! % NULL instead as to eliminate the need for # ifdef in the calling
* code .
*/
struct dentry * debugfs_create_u64 ( const char * name , mode_t mode ,
struct dentry * parent , u64 * value )
{
return debugfs_create_file ( name , mode , parent , value , & fops_u64 ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_u64 ) ;
2007-08-03 02:23:50 +04:00
DEFINE_SIMPLE_ATTRIBUTE ( fops_x8 , debugfs_u8_get , debugfs_u8_set , " 0x%02llx \n " ) ;
DEFINE_SIMPLE_ATTRIBUTE ( fops_x16 , debugfs_u16_get , debugfs_u16_set , " 0x%04llx \n " ) ;
DEFINE_SIMPLE_ATTRIBUTE ( fops_x32 , debugfs_u32_get , debugfs_u32_set , " 0x%08llx \n " ) ;
2007-10-16 04:30:19 +04:00
/*
* debugfs_create_x { 8 , 16 , 32 } - create a debugfs file that is used to read and write an unsigned { 8 , 16 , 32 } - bit value
2007-08-03 02:23:50 +04:00
*
2007-10-16 04:30:19 +04:00
* These functions are exactly the same as the above functions ( but use a hex
* output for the decimal challenged ) . For details look at the above unsigned
2007-08-03 02:23:50 +04:00
* decimal functions .
*/
2007-10-16 04:30:19 +04:00
/**
* debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8 - bit value
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
* directory dentry if set . If this parameter is % NULL , then the
* file will be created in the root of the debugfs filesystem .
* @ value : a pointer to the variable that the file should read to and write
* from .
*/
2007-08-03 02:23:50 +04:00
struct dentry * debugfs_create_x8 ( const char * name , mode_t mode ,
struct dentry * parent , u8 * value )
{
return debugfs_create_file ( name , mode , parent , value , & fops_x8 ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_x8 ) ;
2007-10-16 04:30:19 +04:00
/**
* debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16 - bit value
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
* directory dentry if set . If this parameter is % NULL , then the
* file will be created in the root of the debugfs filesystem .
* @ value : a pointer to the variable that the file should read to and write
* from .
*/
2007-08-03 02:23:50 +04:00
struct dentry * debugfs_create_x16 ( const char * name , mode_t mode ,
struct dentry * parent , u16 * value )
{
return debugfs_create_file ( name , mode , parent , value , & fops_x16 ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_x16 ) ;
2007-10-16 04:30:19 +04:00
/**
* debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32 - bit value
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
* directory dentry if set . If this parameter is % NULL , then the
* file will be created in the root of the debugfs filesystem .
* @ value : a pointer to the variable that the file should read to and write
* from .
*/
2007-08-03 02:23:50 +04:00
struct dentry * debugfs_create_x32 ( const char * name , mode_t mode ,
struct dentry * parent , u32 * value )
{
return debugfs_create_file ( name , mode , parent , value , & fops_x32 ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_x32 ) ;
2005-04-17 02:20:36 +04:00
static ssize_t read_file_bool ( struct file * file , char __user * user_buf ,
size_t count , loff_t * ppos )
{
char buf [ 3 ] ;
u32 * val = file - > private_data ;
if ( * val )
buf [ 0 ] = ' Y ' ;
else
buf [ 0 ] = ' N ' ;
buf [ 1 ] = ' \n ' ;
buf [ 2 ] = 0x00 ;
return simple_read_from_buffer ( user_buf , count , ppos , buf , 2 ) ;
}
static ssize_t write_file_bool ( struct file * file , const char __user * user_buf ,
size_t count , loff_t * ppos )
{
char buf [ 32 ] ;
int buf_size ;
u32 * val = file - > private_data ;
buf_size = min ( count , ( sizeof ( buf ) - 1 ) ) ;
if ( copy_from_user ( buf , user_buf , buf_size ) )
return - EFAULT ;
switch ( buf [ 0 ] ) {
case ' y ' :
case ' Y ' :
case ' 1 ' :
* val = 1 ;
break ;
case ' n ' :
case ' N ' :
case ' 0 ' :
* val = 0 ;
break ;
}
return count ;
}
2006-03-28 13:56:42 +04:00
static const struct file_operations fops_bool = {
2005-04-17 02:20:36 +04:00
. read = read_file_bool ,
. write = write_file_bool ,
. open = default_open ,
} ;
/**
2006-07-20 19:16:42 +04:00
* debugfs_create_bool - create a debugfs file that is used to read and write a boolean value
2005-04-17 02:20:36 +04:00
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
2006-07-20 19:16:42 +04:00
* directory dentry if set . If this parameter is % NULL , then the
2005-04-17 02:20:36 +04:00
* file will be created in the root of the debugfs filesystem .
* @ value : a pointer to the variable that the file should read to and write
* from .
*
* This function creates a file in debugfs with the given name that
* contains the value of the variable @ value . If the @ mode variable is so
* set , it can be read from , and written to .
*
* This function will return a pointer to a dentry if it succeeds . This
* pointer must be passed to the debugfs_remove ( ) function when the file is
* to be removed ( no automatic cleanup happens if your module is unloaded ,
2006-07-20 19:16:42 +04:00
* you are responsible here . ) If an error occurs , % NULL will be returned .
2005-04-17 02:20:36 +04:00
*
2006-07-20 19:16:42 +04:00
* If debugfs is not enabled in the kernel , the value - % ENODEV will be
2005-04-17 02:20:36 +04:00
* returned . It is not wise to check for this value , but rather , check for
2006-07-20 19:16:42 +04:00
* % NULL or ! % NULL instead as to eliminate the need for # ifdef in the calling
2005-04-17 02:20:36 +04:00
* code .
*/
struct dentry * debugfs_create_bool ( const char * name , mode_t mode ,
struct dentry * parent , u32 * value )
{
return debugfs_create_file ( name , mode , parent , value , & fops_bool ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_bool ) ;
2006-03-07 13:41:59 +03:00
static ssize_t read_file_blob ( struct file * file , char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct debugfs_blob_wrapper * blob = file - > private_data ;
return simple_read_from_buffer ( user_buf , count , ppos , blob - > data ,
blob - > size ) ;
}
2007-02-12 11:55:34 +03:00
static const struct file_operations fops_blob = {
2006-03-07 13:41:59 +03:00
. read = read_file_blob ,
. open = default_open ,
} ;
/**
2006-07-20 19:16:42 +04:00
* debugfs_create_blob - create a debugfs file that is used to read and write a binary blob
2006-03-07 13:41:59 +03:00
* @ name : a pointer to a string containing the name of the file to create .
* @ mode : the permission that the file should have
* @ parent : a pointer to the parent dentry for this file . This should be a
2006-07-20 19:16:42 +04:00
* directory dentry if set . If this parameter is % NULL , then the
2006-03-07 13:41:59 +03:00
* file will be created in the root of the debugfs filesystem .
* @ blob : a pointer to a struct debugfs_blob_wrapper which contains a pointer
* to the blob data and the size of the data .
*
* This function creates a file in debugfs with the given name that exports
* @ blob - > data as a binary blob . If the @ mode variable is so set it can be
* read from . Writing is not supported .
*
* This function will return a pointer to a dentry if it succeeds . This
* pointer must be passed to the debugfs_remove ( ) function when the file is
* to be removed ( no automatic cleanup happens if your module is unloaded ,
2006-07-20 19:16:42 +04:00
* you are responsible here . ) If an error occurs , % NULL will be returned .
2006-03-07 13:41:59 +03:00
*
2006-07-20 19:16:42 +04:00
* If debugfs is not enabled in the kernel , the value - % ENODEV will be
2006-03-07 13:41:59 +03:00
* returned . It is not wise to check for this value , but rather , check for
2006-07-20 19:16:42 +04:00
* % NULL or ! % NULL instead as to eliminate the need for # ifdef in the calling
2006-03-07 13:41:59 +03:00
* code .
*/
struct dentry * debugfs_create_blob ( const char * name , mode_t mode ,
struct dentry * parent ,
struct debugfs_blob_wrapper * blob )
{
return debugfs_create_file ( name , mode , parent , blob , & fops_blob ) ;
}
EXPORT_SYMBOL_GPL ( debugfs_create_blob ) ;