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/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 panic
  19 * notifier. This means the trigger can be changed without
  20 * worrying about locking.
  21 */
  22static void led_trigger_set_panic(struct led_classdev *led_cdev)
  23{
  24        struct led_trigger *trig;
  25
  26        list_for_each_entry(trig, &trigger_list, next_trig) {
  27                if (strcmp("panic", trig->name))
  28                        continue;
  29                if (led_cdev->trigger)
  30                        list_del(&led_cdev->trig_list);
  31                list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
  32
  33                /* Avoid the delayed blink path */
  34                led_cdev->blink_delay_on = 0;
  35                led_cdev->blink_delay_off = 0;
  36
  37                led_cdev->trigger = trig;
  38                if (trig->activate)
  39                        trig->activate(led_cdev);
  40                break;
  41        }
  42}
  43
  44static int led_trigger_panic_notifier(struct notifier_block *nb,
  45                                      unsigned long code, void *unused)
  46{
  47        struct led_classdev *led_cdev;
  48
  49        list_for_each_entry(led_cdev, &leds_list, node)
  50                if (led_cdev->flags & LED_PANIC_INDICATOR)
  51                        led_trigger_set_panic(led_cdev);
  52        return NOTIFY_DONE;
  53}
  54
  55static struct notifier_block led_trigger_panic_nb = {
  56        .notifier_call = led_trigger_panic_notifier,
  57};
  58
  59static long led_panic_blink(int state)
  60{
  61        led_trigger_event(trigger, state ? LED_FULL : LED_OFF);
  62        return 0;
  63}
  64
  65static int __init ledtrig_panic_init(void)
  66{
  67        atomic_notifier_chain_register(&panic_notifier_list,
  68                                       &led_trigger_panic_nb);
  69
  70        led_trigger_register_simple("panic", &trigger);
  71        panic_blink = led_panic_blink;
  72        return 0;
  73}
  74device_initcall(ledtrig_panic_init);
  75