ledtrig-panic.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  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. #include <linux/kernel.h>
  8. #include <linux/init.h>
  9. #include <linux/notifier.h>
  10. #include <linux/panic_notifier.h>
  11. #include <linux/leds.h>
  12. #include "../leds.h"
  13. static struct led_trigger *trigger;
  14. /*
  15. * This is called in a special context by the atomic panic
  16. * notifier. This means the trigger can be changed without
  17. * worrying about locking.
  18. */
  19. static void led_trigger_set_panic(struct led_classdev *led_cdev)
  20. {
  21. if (led_cdev->trigger)
  22. list_del(&led_cdev->trig_list);
  23. list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
  24. /* Avoid the delayed blink path */
  25. led_cdev->blink_delay_on = 0;
  26. led_cdev->blink_delay_off = 0;
  27. led_cdev->trigger = trigger;
  28. }
  29. static int led_trigger_panic_notifier(struct notifier_block *nb,
  30. unsigned long code, void *unused)
  31. {
  32. struct led_classdev *led_cdev;
  33. list_for_each_entry(led_cdev, &leds_list, node)
  34. if (led_cdev->flags & LED_PANIC_INDICATOR)
  35. led_trigger_set_panic(led_cdev);
  36. return NOTIFY_DONE;
  37. }
  38. static struct notifier_block led_trigger_panic_nb = {
  39. .notifier_call = led_trigger_panic_notifier,
  40. };
  41. static long led_panic_blink(int state)
  42. {
  43. led_trigger_event(trigger, state ? LED_FULL : LED_OFF);
  44. return 0;
  45. }
  46. static int __init ledtrig_panic_init(void)
  47. {
  48. led_trigger_register_simple("panic", &trigger);
  49. if (!trigger)
  50. return -ENOMEM;
  51. atomic_notifier_chain_register(&panic_notifier_list,
  52. &led_trigger_panic_nb);
  53. panic_blink = led_panic_blink;
  54. return 0;
  55. }
  56. device_initcall(ledtrig_panic_init);