2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2016-03-29 17:35:47 -03:00
/*
* Kernel Panic LED Trigger
*
* Copyright 2016 Ezequiel Garcia < ezequiel @ vanguardiasur . com . ar >
*/
# include <linux/kernel.h>
# include <linux/init.h>
2016-04-28 19:03:38 -03:00
# include <linux/notifier.h>
2021-06-30 18:54:59 -07:00
# include <linux/panic_notifier.h>
2016-03-29 17:35:47 -03:00
# include <linux/leds.h>
2016-04-28 19:03:38 -03:00
# include "../leds.h"
2016-03-29 17:35:47 -03:00
static struct led_trigger * trigger ;
2016-04-28 19:03:38 -03:00
/*
* This is called in a special context by the atomic panic
* notifier . This means the trigger can be changed without
* worrying about locking .
*/
static void led_trigger_set_panic ( struct led_classdev * led_cdev )
{
struct led_trigger * trig ;
list_for_each_entry ( trig , & trigger_list , next_trig ) {
if ( strcmp ( " panic " , trig - > name ) )
continue ;
if ( led_cdev - > trigger )
list_del ( & led_cdev - > trig_list ) ;
list_add_tail ( & led_cdev - > trig_list , & trig - > led_cdevs ) ;
/* Avoid the delayed blink path */
led_cdev - > blink_delay_on = 0 ;
led_cdev - > blink_delay_off = 0 ;
led_cdev - > trigger = trig ;
if ( trig - > activate )
trig - > activate ( led_cdev ) ;
break ;
}
}
static int led_trigger_panic_notifier ( struct notifier_block * nb ,
unsigned long code , void * unused )
{
struct led_classdev * led_cdev ;
list_for_each_entry ( led_cdev , & leds_list , node )
if ( led_cdev - > flags & LED_PANIC_INDICATOR )
led_trigger_set_panic ( led_cdev ) ;
return NOTIFY_DONE ;
}
static struct notifier_block led_trigger_panic_nb = {
. notifier_call = led_trigger_panic_notifier ,
} ;
2016-03-29 17:35:47 -03:00
static long led_panic_blink ( int state )
{
led_trigger_event ( trigger , state ? LED_FULL : LED_OFF ) ;
return 0 ;
}
static int __init ledtrig_panic_init ( void )
{
2016-04-28 19:03:38 -03:00
atomic_notifier_chain_register ( & panic_notifier_list ,
& led_trigger_panic_nb ) ;
2016-03-29 17:35:47 -03:00
led_trigger_register_simple ( " panic " , & trigger ) ;
panic_blink = led_panic_blink ;
return 0 ;
}
device_initcall ( ledtrig_panic_init ) ;