linux/drivers/leds/trigger/ledtrig-panic.c
<<
>>
Prefs
   1/*
   2 * Kernel Panic LED Trigger
   3 *
   4 * Copyright 2016 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/init.h>
  14#include <linux/notifier.h>
  15#include <linux/leds.h>
  16#include "../leds.h"
  17
  18static struct led_trigger *trigger;
  19
  20/*
  21 * This is called in a special context by the atomic panic
  22 * notifier. This means the trigger can be changed without
  23 * worrying about locking.
  24 */
  25static void led_trigger_set_panic(struct led_classdev *led_cdev)
  26{
  27        struct led_trigger *trig;
  28
  29        list_for_each_entry(trig, &trigger_list, next_trig) {
  30                if (strcmp("panic", trig->name))
  31                        continue;
  32                if (led_cdev->trigger)
  33                        list_del(&led_cdev->trig_list);
  34                list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
  35
  36                /* Avoid the delayed blink path */
  37                led_cdev->blink_delay_on = 0;
  38                led_cdev->blink_delay_off = 0;
  39
  40                led_cdev->trigger = trig;
  41                if (trig->activate)
  42                        trig->activate(led_cdev);
  43                break;
  44        }
  45}
  46
  47static int led_trigger_panic_notifier(struct notifier_block *nb,
  48                                      unsigned long code, void *unused)
  49{
  50        struct led_classdev *led_cdev;
  51
  52        list_for_each_entry(led_cdev, &leds_list, node)
  53                if (led_cdev->flags & LED_PANIC_INDICATOR)
  54                        led_trigger_set_panic(led_cdev);
  55        return NOTIFY_DONE;
  56}
  57
  58static struct notifier_block led_trigger_panic_nb = {
  59        .notifier_call = led_trigger_panic_notifier,
  60};
  61
  62static long led_panic_blink(int state)
  63{
  64        led_trigger_event(trigger, state ? LED_FULL : LED_OFF);
  65        return 0;
  66}
  67
  68static int __init ledtrig_panic_init(void)
  69{
  70        atomic_notifier_chain_register(&panic_notifier_list,
  71                                       &led_trigger_panic_nb);
  72
  73        led_trigger_register_simple("panic", &trigger);
  74        panic_blink = led_panic_blink;
  75        return 0;
  76}
  77device_initcall(ledtrig_panic_init);
  78