2008-09-23 14:32:08 +04:00
/*
* ring buffer based initcalls tracer
*
* Copyright ( C ) 2008 Frederic Weisbecker < fweisbec @ gmail . com >
*
*/
# include <linux/init.h>
# include <linux/debugfs.h>
# include <linux/ftrace.h>
# include "trace.h"
static struct trace_array * boot_trace ;
static int trace_boot_enabled ;
/* Should be started after do_pre_smp_initcalls() in init/main.c */
void start_boot_trace ( void )
{
trace_boot_enabled = 1 ;
}
void stop_boot_trace ( struct trace_array * tr )
{
trace_boot_enabled = 0 ;
}
static void boot_trace_init ( struct trace_array * tr )
{
int cpu ;
boot_trace = tr ;
trace_boot_enabled = 0 ;
for_each_cpu_mask ( cpu , cpu_possible_map )
2008-09-30 07:02:41 +04:00
tracing_reset ( tr , cpu ) ;
2008-09-23 14:32:08 +04:00
}
static void boot_trace_ctrl_update ( struct trace_array * tr )
{
if ( tr - > ctrl )
start_boot_trace ( ) ;
else
stop_boot_trace ( tr ) ;
}
2008-09-29 22:31:58 +04:00
static enum print_line_t initcall_print_line ( struct trace_iterator * iter )
2008-09-23 14:32:08 +04:00
{
2008-09-29 22:31:58 +04:00
int ret ;
2008-09-23 14:32:08 +04:00
struct trace_entry * entry = iter - > ent ;
2008-09-30 07:02:42 +04:00
struct trace_boot * field = ( struct trace_boot * ) entry ;
struct boot_trace * it = & field - > initcall ;
2008-09-23 14:32:08 +04:00
struct trace_seq * s = & iter - > seq ;
2008-09-29 22:31:58 +04:00
if ( entry - > type = = TRACE_BOOT ) {
2008-09-23 14:32:08 +04:00
ret = trace_seq_printf ( s , " %pF called from %i "
" returned %d after %lld msecs \n " ,
it - > func , it - > caller , it - > result ,
it - > duration ) ;
2008-09-29 22:31:58 +04:00
if ( ret )
return TRACE_TYPE_HANDLED ;
else
return TRACE_TYPE_PARTIAL_LINE ;
}
return TRACE_TYPE_UNHANDLED ;
2008-09-23 14:32:08 +04:00
}
struct tracer boot_tracer __read_mostly =
{
. name = " initcall " ,
. init = boot_trace_init ,
. reset = stop_boot_trace ,
. ctrl_update = boot_trace_ctrl_update ,
. print_line = initcall_print_line ,
} ;
void trace_boot ( struct boot_trace * it )
{
2008-09-30 07:02:41 +04:00
struct ring_buffer_event * event ;
2008-09-30 07:02:42 +04:00
struct trace_boot * entry ;
2008-09-23 14:32:08 +04:00
struct trace_array_cpu * data ;
unsigned long irq_flags ;
struct trace_array * tr = boot_trace ;
if ( ! trace_boot_enabled )
return ;
preempt_disable ( ) ;
data = tr - > data [ smp_processor_id ( ) ] ;
2008-09-30 07:02:41 +04:00
event = ring_buffer_lock_reserve ( tr - > buffer , sizeof ( * entry ) ,
& irq_flags ) ;
if ( ! event )
goto out ;
entry = ring_buffer_event_data ( event ) ;
2008-09-30 07:02:42 +04:00
tracing_generic_entry_update ( & entry - > ent , 0 ) ;
entry - > ent . type = TRACE_BOOT ;
entry - > initcall = * it ;
2008-09-30 07:02:41 +04:00
ring_buffer_unlock_commit ( tr - > buffer , event , irq_flags ) ;
2008-09-23 14:32:08 +04:00
trace_wake_up ( ) ;
2008-09-30 07:02:41 +04:00
out :
2008-09-23 14:32:08 +04:00
preempt_enable ( ) ;
}