2018-12-28 00:32:24 -08:00
// SPDX-License-Identifier: GPL-2.0
2009-09-01 17:38:32 +09:00
/*
* Copyright ( C ) 2007 Atmel Corporation
*/
# include <linux/delay.h>
# include <linux/kdebug.h>
# include <linux/notifier.h>
# include <linux/sched.h>
2017-02-08 18:51:35 +01:00
# include <linux/sched/debug.h>
2009-09-01 17:38:32 +09:00
# include <linux/hardirq.h>
enum nmi_action {
NMI_SHOW_STATE = 1 < < 0 ,
NMI_SHOW_REGS = 1 < < 1 ,
NMI_DIE = 1 < < 2 ,
NMI_DEBOUNCE = 1 < < 3 ,
} ;
static unsigned long nmi_actions ;
static int nmi_debug_notify ( struct notifier_block * self ,
unsigned long val , void * data )
{
struct die_args * args = data ;
if ( likely ( val ! = DIE_NMI ) )
return NOTIFY_DONE ;
if ( nmi_actions & NMI_SHOW_STATE )
show_state ( ) ;
if ( nmi_actions & NMI_SHOW_REGS )
show_regs ( args - > regs ) ;
if ( nmi_actions & NMI_DEBOUNCE )
mdelay ( 10 ) ;
if ( nmi_actions & NMI_DIE )
return NOTIFY_BAD ;
return NOTIFY_OK ;
}
static struct notifier_block nmi_debug_nb = {
. notifier_call = nmi_debug_notify ,
} ;
static int __init nmi_debug_setup ( char * str )
{
char * p , * sep ;
register_die_notifier ( & nmi_debug_nb ) ;
if ( * str ! = ' = ' )
return 0 ;
for ( p = str + 1 ; * p ; p = sep + 1 ) {
sep = strchr ( p , ' , ' ) ;
if ( sep )
* sep = 0 ;
if ( strcmp ( p , " state " ) = = 0 )
nmi_actions | = NMI_SHOW_STATE ;
else if ( strcmp ( p , " regs " ) = = 0 )
nmi_actions | = NMI_SHOW_REGS ;
else if ( strcmp ( p , " debounce " ) = = 0 )
nmi_actions | = NMI_DEBOUNCE ;
else if ( strcmp ( p , " die " ) = = 0 )
nmi_actions | = NMI_DIE ;
else
printk ( KERN_WARNING " NMI: Unrecognized action `%s' \n " ,
p ) ;
if ( ! sep )
break ;
}
return 0 ;
}
__setup ( " nmi_debug " , nmi_debug_setup ) ;