linux/drivers/leds/trigger/ledtrig-panic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Kernel Panic LED Trigger
   4 *
   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/leds.h>
  12#include "../leds.h"
  13
  14static struct led_trigger *trigger;
  15
  16/*
  17 * This is called in a special context by the atomic panic
  18 * notifier. This means the trigger can be changed without
  19 * worrying about locking.
  20 */
  21static void led_trigger_set_panic(struct led_classdev *led_cdev)
  22{
  23        struct led_trigger *trig;
  24
  25        list_for_each_entry(trig, &trigger_list, next_trig) {
  26                if (strcmp("panic", trig->name))
  27                        continue;
  28                if (led_cdev->trigger)
  29                        list_del(&led_cdev->trig_list);
  30                list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
  31
  32                /* Avoid the delayed blink path */
  33                led_cdev->blink_delay_on = 0;
  34                led_cdev->blink_delay_off = 0;
  35
  36                led_cdev->trigger = trig;
  37                if (trig->activate)
  38                        trig->activate(led_cdev);
  39                break;
  40        }
  41}
  42
  43static int led_trigger_panic_notifier(struct notifier_block *nb,
  44                                      unsigned long code, void *unused)
  45{
  46        struct led_classdev *led_cdev;
  47
  48        list_for_each_entry(led_cdev, &leds_list, node)
  49                if (led_cdev->flags & LED_PANIC_INDICATOR)
  50                        led_trigger_set_panic(led_cdev);
  51        return NOTIFY_DONE;
  52}
  53
  54static struct notifier_block led_trigger_panic_nb = {
  55        .notifier_call = led_trigger_panic_notifier,
  56};
  57
  58static long led_panic_blink(int state)
  59{
  60        led_trigger_event(trigger, state ? LED_FULL : LED_OFF);
  61        return 0;
  62}
  63
  64static int __init ledtrig_panic_init(void)
  65{
  66        atomic_notifier_chain_register(&panic_notifier_list,
  67                                       &led_trigger_panic_nb);
  68
  69        led_trigger_register_simple("panic", &trigger);
  70        panic_blink = led_panic_blink;
  71        return 0;
  72}
  73device_initcall(ledtrig_panic_init);
  74