ledtrig-panic.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Kernel Panic LED Trigger
  4. *
  5. * Copyright 2016 Ezequiel Garcia <[email protected]>
  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. struct led_trigger *trig;
  22. list_for_each_entry(trig, &trigger_list, next_trig) {
  23. if (strcmp("panic", trig->name))
  24. continue;
  25. if (led_cdev->trigger)
  26. list_del(&led_cdev->trig_list);
  27. list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
  28. /* Avoid the delayed blink path */
  29. led_cdev->blink_delay_on = 0;
  30. led_cdev->blink_delay_off = 0;
  31. led_cdev->trigger = trig;
  32. if (trig->activate)
  33. trig->activate(led_cdev);
  34. break;
  35. }
  36. }
  37. static int led_trigger_panic_notifier(struct notifier_block *nb,
  38. unsigned long code, void *unused)
  39. {
  40. struct led_classdev *led_cdev;
  41. list_for_each_entry(led_cdev, &leds_list, node)
  42. if (led_cdev->flags & LED_PANIC_INDICATOR)
  43. led_trigger_set_panic(led_cdev);
  44. return NOTIFY_DONE;
  45. }
  46. static struct notifier_block led_trigger_panic_nb = {
  47. .notifier_call = led_trigger_panic_notifier,
  48. };
  49. static long led_panic_blink(int state)
  50. {
  51. led_trigger_event(trigger, state ? LED_FULL : LED_OFF);
  52. return 0;
  53. }
  54. static int __init ledtrig_panic_init(void)
  55. {
  56. atomic_notifier_chain_register(&panic_notifier_list,
  57. &led_trigger_panic_nb);
  58. led_trigger_register_simple("panic", &trigger);
  59. panic_blink = led_panic_blink;
  60. return 0;
  61. }
  62. device_initcall(ledtrig_panic_init);