69 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Kernel Panic LED Trigger4 *5 * Copyright 2016 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>6 */7 8#include <linux/kernel.h>9#include <linux/init.h>10#include <linux/notifier.h>11#include <linux/panic_notifier.h>12#include <linux/leds.h>13#include "../leds.h"14 15static struct led_trigger *trigger;16 17/*18 * This is called in a special context by the atomic panic19 * notifier. This means the trigger can be changed without20 * worrying about locking.21 */22static void led_trigger_set_panic(struct led_classdev *led_cdev)23{24 if (led_cdev->trigger)25 list_del(&led_cdev->trig_list);26 list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);27 28 /* Avoid the delayed blink path */29 led_cdev->blink_delay_on = 0;30 led_cdev->blink_delay_off = 0;31 32 led_cdev->trigger = trigger;33}34 35static int led_trigger_panic_notifier(struct notifier_block *nb,36 unsigned long code, void *unused)37{38 struct led_classdev *led_cdev;39 40 list_for_each_entry(led_cdev, &leds_list, node)41 if (led_cdev->flags & LED_PANIC_INDICATOR)42 led_trigger_set_panic(led_cdev);43 return NOTIFY_DONE;44}45 46static struct notifier_block led_trigger_panic_nb = {47 .notifier_call = led_trigger_panic_notifier,48};49 50static long led_panic_blink(int state)51{52 led_trigger_event(trigger, state ? LED_FULL : LED_OFF);53 return 0;54}55 56static int __init ledtrig_panic_init(void)57{58 led_trigger_register_simple("panic", &trigger);59 if (!trigger)60 return -ENOMEM;61 62 atomic_notifier_chain_register(&panic_notifier_list,63 &led_trigger_panic_nb);64 65 panic_blink = led_panic_blink;66 return 0;67}68device_initcall(ledtrig_panic_init);69