2005-04-16 15:20:36 -07:00
/*
* debug . c - ACPI debug interface to userspace .
*/
# include <linux/proc_fs.h>
2009-09-18 12:41:08 -07:00
# include <linux/seq_file.h>
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/moduleparam.h>
2009-12-02 13:31:00 +08:00
# include <linux/debugfs.h>
2005-04-16 15:20:36 -07:00
# include <asm/uaccess.h>
# include <acpi/acpi_drivers.h>
# define _COMPONENT ACPI_SYSTEM_COMPONENT
2007-02-12 22:42:12 -05:00
ACPI_MODULE_NAME ( " debug " ) ;
2007-01-29 11:02:38 +08:00
2005-04-16 15:20:36 -07:00
struct acpi_dlayer {
const char * name ;
unsigned long value ;
} ;
struct acpi_dlevel {
const char * name ;
unsigned long value ;
} ;
# define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
2005-08-05 00:44:28 -04:00
static const struct acpi_dlayer acpi_debug_layers [ ] = {
2005-04-16 15:20:36 -07:00
ACPI_DEBUG_INIT ( ACPI_UTILITIES ) ,
ACPI_DEBUG_INIT ( ACPI_HARDWARE ) ,
ACPI_DEBUG_INIT ( ACPI_EVENTS ) ,
ACPI_DEBUG_INIT ( ACPI_TABLES ) ,
ACPI_DEBUG_INIT ( ACPI_NAMESPACE ) ,
ACPI_DEBUG_INIT ( ACPI_PARSER ) ,
ACPI_DEBUG_INIT ( ACPI_DISPATCHER ) ,
ACPI_DEBUG_INIT ( ACPI_EXECUTER ) ,
ACPI_DEBUG_INIT ( ACPI_RESOURCES ) ,
ACPI_DEBUG_INIT ( ACPI_CA_DEBUGGER ) ,
ACPI_DEBUG_INIT ( ACPI_OS_SERVICES ) ,
ACPI_DEBUG_INIT ( ACPI_CA_DISASSEMBLER ) ,
ACPI_DEBUG_INIT ( ACPI_COMPILER ) ,
ACPI_DEBUG_INIT ( ACPI_TOOLS ) ,
2008-11-07 16:57:55 -07:00
ACPI_DEBUG_INIT ( ACPI_BUS_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_AC_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_BATTERY_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_BUTTON_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_SBS_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_FAN_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_PCI_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_POWER_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_CONTAINER_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_SYSTEM_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_THERMAL_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_MEMORY_DEVICE_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_VIDEO_COMPONENT ) ,
ACPI_DEBUG_INIT ( ACPI_PROCESSOR_COMPONENT ) ,
2005-04-16 15:20:36 -07:00
} ;
2005-08-05 00:44:28 -04:00
static const struct acpi_dlevel acpi_debug_levels [ ] = {
2005-04-16 15:20:36 -07:00
ACPI_DEBUG_INIT ( ACPI_LV_INIT ) ,
ACPI_DEBUG_INIT ( ACPI_LV_DEBUG_OBJECT ) ,
ACPI_DEBUG_INIT ( ACPI_LV_INFO ) ,
ACPI_DEBUG_INIT ( ACPI_LV_INIT_NAMES ) ,
ACPI_DEBUG_INIT ( ACPI_LV_PARSE ) ,
ACPI_DEBUG_INIT ( ACPI_LV_LOAD ) ,
ACPI_DEBUG_INIT ( ACPI_LV_DISPATCH ) ,
ACPI_DEBUG_INIT ( ACPI_LV_EXEC ) ,
ACPI_DEBUG_INIT ( ACPI_LV_NAMES ) ,
ACPI_DEBUG_INIT ( ACPI_LV_OPREGION ) ,
ACPI_DEBUG_INIT ( ACPI_LV_BFIELD ) ,
ACPI_DEBUG_INIT ( ACPI_LV_TABLES ) ,
ACPI_DEBUG_INIT ( ACPI_LV_VALUES ) ,
ACPI_DEBUG_INIT ( ACPI_LV_OBJECTS ) ,
ACPI_DEBUG_INIT ( ACPI_LV_RESOURCES ) ,
ACPI_DEBUG_INIT ( ACPI_LV_USER_REQUESTS ) ,
ACPI_DEBUG_INIT ( ACPI_LV_PACKAGE ) ,
ACPI_DEBUG_INIT ( ACPI_LV_ALLOCATIONS ) ,
ACPI_DEBUG_INIT ( ACPI_LV_FUNCTIONS ) ,
ACPI_DEBUG_INIT ( ACPI_LV_OPTIMIZATIONS ) ,
ACPI_DEBUG_INIT ( ACPI_LV_MUTEX ) ,
ACPI_DEBUG_INIT ( ACPI_LV_THREADS ) ,
ACPI_DEBUG_INIT ( ACPI_LV_IO ) ,
ACPI_DEBUG_INIT ( ACPI_LV_INTERRUPTS ) ,
ACPI_DEBUG_INIT ( ACPI_LV_AML_DISASSEMBLE ) ,
ACPI_DEBUG_INIT ( ACPI_LV_VERBOSE_INFO ) ,
ACPI_DEBUG_INIT ( ACPI_LV_FULL_TABLES ) ,
2005-08-05 00:44:28 -04:00
ACPI_DEBUG_INIT ( ACPI_LV_EVENTS ) ,
2005-04-16 15:20:36 -07:00
} ;
2007-01-29 11:02:38 +08:00
/* --------------------------------------------------------------------------
FS Interface ( / sys )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static int param_get_debug_layer ( char * buffer , struct kernel_param * kp ) {
int result = 0 ;
int i ;
result = sprintf ( buffer , " %-25s \t Hex SET \n " , " Description " ) ;
for ( i = 0 ; i < ARRAY_SIZE ( acpi_debug_layers ) ; i + + ) {
result + = sprintf ( buffer + result , " %-25s \t 0x%08lX [%c] \n " ,
acpi_debug_layers [ i ] . name ,
acpi_debug_layers [ i ] . value ,
( acpi_dbg_layer & acpi_debug_layers [ i ] . value ) ? ' * ' : ' ' ) ;
}
result + = sprintf ( buffer + result , " %-25s \t 0x%08X [%c] \n " , " ACPI_ALL_DRIVERS " ,
ACPI_ALL_DRIVERS ,
( acpi_dbg_layer & ACPI_ALL_DRIVERS ) = =
ACPI_ALL_DRIVERS ? ' * ' : ( acpi_dbg_layer &
ACPI_ALL_DRIVERS ) = = 0 ? ' ' : ' - ' ) ;
result + = sprintf ( buffer + result , " -- \n debug_layer = 0x%08X ( * = enabled) \n " , acpi_dbg_layer ) ;
return result ;
}
static int param_get_debug_level ( char * buffer , struct kernel_param * kp ) {
int result = 0 ;
int i ;
result = sprintf ( buffer , " %-25s \t Hex SET \n " , " Description " ) ;
for ( i = 0 ; i < ARRAY_SIZE ( acpi_debug_levels ) ; i + + ) {
result + = sprintf ( buffer + result , " %-25s \t 0x%08lX [%c] \n " ,
acpi_debug_levels [ i ] . name ,
acpi_debug_levels [ i ] . value ,
( acpi_dbg_level & acpi_debug_levels [ i ] .
value ) ? ' * ' : ' ' ) ;
}
result + = sprintf ( buffer + result , " -- \n debug_level = 0x%08X (* = enabled) \n " ,
acpi_dbg_level ) ;
return result ;
}
module_param_call ( debug_layer , param_set_uint , param_get_debug_layer , & acpi_dbg_layer , 0644 ) ;
module_param_call ( debug_level , param_set_uint , param_get_debug_level , & acpi_dbg_level , 0644 ) ;
2007-11-14 19:38:40 -05:00
static char trace_method_name [ 6 ] ;
module_param_string ( trace_method_name , trace_method_name , 6 , 0644 ) ;
static unsigned int trace_debug_layer ;
module_param ( trace_debug_layer , uint , 0644 ) ;
static unsigned int trace_debug_level ;
module_param ( trace_debug_level , uint , 0644 ) ;
static int param_set_trace_state ( const char * val , struct kernel_param * kp )
{
int result = 0 ;
if ( ! strncmp ( val , " enable " , strlen ( " enable " ) - 1 ) ) {
result = acpi_debug_trace ( trace_method_name , trace_debug_level ,
trace_debug_layer , 0 ) ;
if ( result )
result = - EBUSY ;
goto exit ;
}
if ( ! strncmp ( val , " disable " , strlen ( " disable " ) - 1 ) ) {
int name = 0 ;
result = acpi_debug_trace ( ( char * ) & name , trace_debug_level ,
trace_debug_layer , 0 ) ;
if ( result )
result = - EBUSY ;
goto exit ;
}
if ( ! strncmp ( val , " 1 " , 1 ) ) {
result = acpi_debug_trace ( trace_method_name , trace_debug_level ,
trace_debug_layer , 1 ) ;
if ( result )
result = - EBUSY ;
goto exit ;
}
result = - EINVAL ;
exit :
return result ;
}
static int param_get_trace_state ( char * buffer , struct kernel_param * kp )
{
if ( ! acpi_gbl_trace_method_name )
return sprintf ( buffer , " disable " ) ;
else {
if ( acpi_gbl_trace_flags & 1 )
return sprintf ( buffer , " 1 " ) ;
else
return sprintf ( buffer , " enable " ) ;
}
return 0 ;
}
module_param_call ( trace_state , param_set_trace_state , param_get_trace_state ,
NULL , 0644 ) ;
2009-12-02 13:31:00 +08:00
/* --------------------------------------------------------------------------
DebugFS Interface
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static ssize_t cm_write ( struct file * file , const char __user * user_buf ,
size_t count , loff_t * ppos )
{
static char * buf ;
static int uncopied_bytes ;
struct acpi_table_header table ;
acpi_status status ;
if ( ! ( * ppos ) ) {
/* parse the table header to get the table length */
if ( count < = sizeof ( struct acpi_table_header ) )
return - EINVAL ;
if ( copy_from_user ( & table , user_buf ,
sizeof ( struct acpi_table_header ) ) )
return - EFAULT ;
uncopied_bytes = table . length ;
buf = kzalloc ( uncopied_bytes , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
}
if ( uncopied_bytes < count ) {
kfree ( buf ) ;
return - EINVAL ;
}
if ( copy_from_user ( buf + ( * ppos ) , user_buf , count ) ) {
kfree ( buf ) ;
return - EFAULT ;
}
uncopied_bytes - = count ;
* ppos + = count ;
if ( ! uncopied_bytes ) {
status = acpi_install_method ( buf ) ;
kfree ( buf ) ;
if ( ACPI_FAILURE ( status ) )
return - EINVAL ;
2009-12-14 11:24:18 +08:00
add_taint ( TAINT_OVERRIDDEN_ACPI_TABLE ) ;
2009-12-02 13:31:00 +08:00
}
return count ;
}
static const struct file_operations cm_fops = {
. write = cm_write ,
} ;
static int acpi_debugfs_init ( void )
{
struct dentry * acpi_dir , * cm_dentry ;
acpi_dir = debugfs_create_dir ( " acpi " , NULL ) ;
if ( ! acpi_dir )
goto err ;
cm_dentry = debugfs_create_file ( " custom_method " , S_IWUGO ,
acpi_dir , NULL , & cm_fops ) ;
if ( ! cm_dentry )
goto err ;
return 0 ;
err :
if ( acpi_dir )
debugfs_remove ( acpi_dir ) ;
return - EINVAL ;
}
2007-01-29 11:02:38 +08:00
/* --------------------------------------------------------------------------
FS Interface ( / proc )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
# ifdef CONFIG_ACPI_PROCFS
# define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
# define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
2009-09-18 12:41:08 -07:00
static int acpi_system_debug_proc_show ( struct seq_file * m , void * v )
2005-04-16 15:20:36 -07:00
{
2005-08-05 00:44:28 -04:00
unsigned int i ;
2005-04-16 15:20:36 -07:00
2009-09-18 12:41:08 -07:00
seq_printf ( m , " %-25s \t Hex SET \n " , " Description " ) ;
2005-04-16 15:20:36 -07:00
2009-09-18 12:41:08 -07:00
switch ( ( unsigned long ) m - > private ) {
2005-04-16 15:20:36 -07:00
case 0 :
for ( i = 0 ; i < ARRAY_SIZE ( acpi_debug_layers ) ; i + + ) {
2009-09-18 12:41:08 -07:00
seq_printf ( m , " %-25s \t 0x%08lX [%c] \n " ,
2005-08-05 00:44:28 -04:00
acpi_debug_layers [ i ] . name ,
acpi_debug_layers [ i ] . value ,
( acpi_dbg_layer & acpi_debug_layers [ i ] .
value ) ? ' * ' : ' ' ) ;
2005-04-16 15:20:36 -07:00
}
2009-09-18 12:41:08 -07:00
seq_printf ( m , " %-25s \t 0x%08X [%c] \n " , " ACPI_ALL_DRIVERS " ,
2005-08-05 00:44:28 -04:00
ACPI_ALL_DRIVERS ,
( acpi_dbg_layer & ACPI_ALL_DRIVERS ) = =
ACPI_ALL_DRIVERS ? ' * ' : ( acpi_dbg_layer &
ACPI_ALL_DRIVERS ) = =
0 ? ' ' : ' - ' ) ;
2009-09-18 12:41:08 -07:00
seq_printf ( m ,
2005-08-05 00:44:28 -04:00
" -- \n debug_layer = 0x%08X (* = enabled, - = partial) \n " ,
acpi_dbg_layer ) ;
2005-04-16 15:20:36 -07:00
break ;
case 1 :
for ( i = 0 ; i < ARRAY_SIZE ( acpi_debug_levels ) ; i + + ) {
2009-09-18 12:41:08 -07:00
seq_printf ( m , " %-25s \t 0x%08lX [%c] \n " ,
2005-08-05 00:44:28 -04:00
acpi_debug_levels [ i ] . name ,
acpi_debug_levels [ i ] . value ,
( acpi_dbg_level & acpi_debug_levels [ i ] .
value ) ? ' * ' : ' ' ) ;
2005-04-16 15:20:36 -07:00
}
2009-09-18 12:41:08 -07:00
seq_printf ( m , " -- \n debug_level = 0x%08X (* = enabled) \n " ,
2005-08-05 00:44:28 -04:00
acpi_dbg_level ) ;
2005-04-16 15:20:36 -07:00
break ;
}
2009-09-18 12:41:08 -07:00
return 0 ;
}
2005-08-05 00:44:28 -04:00
2009-09-18 12:41:08 -07:00
static int acpi_system_debug_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , acpi_system_debug_proc_show , PDE ( inode ) - > data ) ;
2005-04-16 15:20:36 -07:00
}
2009-09-18 12:41:08 -07:00
static ssize_t acpi_system_debug_proc_write ( struct file * file ,
2005-08-05 00:44:28 -04:00
const char __user * buffer ,
2009-09-18 12:41:08 -07:00
size_t count , loff_t * pos )
2005-04-16 15:20:36 -07:00
{
2005-08-05 00:44:28 -04:00
char debug_string [ 12 ] = { ' \0 ' } ;
2005-04-16 15:20:36 -07:00
if ( count > sizeof ( debug_string ) - 1 )
2006-06-27 00:41:40 -04:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
if ( copy_from_user ( debug_string , buffer , count ) )
2006-06-27 00:41:40 -04:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
debug_string [ count ] = ' \0 ' ;
2009-09-18 12:41:08 -07:00
switch ( ( unsigned long ) PDE ( file - > f_path . dentry - > d_inode ) - > data ) {
2005-04-16 15:20:36 -07:00
case 0 :
acpi_dbg_layer = simple_strtoul ( debug_string , NULL , 0 ) ;
break ;
case 1 :
acpi_dbg_level = simple_strtoul ( debug_string , NULL , 0 ) ;
break ;
default :
2006-06-27 00:41:40 -04:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2006-06-27 00:41:40 -04:00
return count ;
2005-04-16 15:20:36 -07:00
}
2009-09-18 12:41:08 -07:00
static const struct file_operations acpi_system_debug_proc_fops = {
. owner = THIS_MODULE ,
. open = acpi_system_debug_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = acpi_system_debug_proc_write ,
} ;
2009-03-24 16:50:03 -06:00
# endif
2005-04-16 15:20:36 -07:00
2009-12-02 13:31:00 +08:00
int __init acpi_procfs_init ( void )
2005-04-16 15:20:36 -07:00
{
2009-03-24 16:50:03 -06:00
# ifdef CONFIG_ACPI_PROCFS
2005-08-05 00:44:28 -04:00
struct proc_dir_entry * entry ;
2005-04-16 15:20:36 -07:00
int error = 0 ;
2005-08-05 00:44:28 -04:00
char * name ;
2005-04-16 15:20:36 -07:00
/* 'debug_layer' [R/W] */
name = ACPI_SYSTEM_FILE_DEBUG_LAYER ;
2009-09-18 12:41:08 -07:00
entry = proc_create_data ( name , S_IFREG | S_IRUGO | S_IWUSR ,
acpi_root_dir , & acpi_system_debug_proc_fops ,
( void * ) 0 ) ;
if ( ! entry )
2005-04-16 15:20:36 -07:00
goto Error ;
/* 'debug_level' [R/W] */
name = ACPI_SYSTEM_FILE_DEBUG_LEVEL ;
2009-09-18 12:41:08 -07:00
entry = proc_create_data ( name , S_IFREG | S_IRUGO | S_IWUSR ,
acpi_root_dir , & acpi_system_debug_proc_fops ,
( void * ) 1 ) ;
if ( ! entry )
2005-04-16 15:20:36 -07:00
goto Error ;
2005-08-05 00:44:28 -04:00
Done :
2006-06-27 00:41:40 -04:00
return error ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
Error :
2005-04-16 15:20:36 -07:00
remove_proc_entry ( ACPI_SYSTEM_FILE_DEBUG_LEVEL , acpi_root_dir ) ;
remove_proc_entry ( ACPI_SYSTEM_FILE_DEBUG_LAYER , acpi_root_dir ) ;
2006-06-26 23:58:43 -04:00
error = - ENODEV ;
2005-04-16 15:20:36 -07:00
goto Done ;
2009-03-24 16:50:03 -06:00
# else
return 0 ;
2007-01-29 11:02:38 +08:00
# endif
2009-03-24 16:50:03 -06:00
}
2009-12-02 13:31:00 +08:00
int __init acpi_debug_init ( void )
{
acpi_debugfs_init ( ) ;
acpi_procfs_init ( ) ;
return 0 ;
}