ledtrig-panic.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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. #include <linux/kernel.h>
  12. #include <linux/init.h>
  13. #include <linux/notifier.h>
  14. #include <linux/leds.h>
  15. #include "../leds.h"
  16. static struct led_trigger *trigger;
  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. */
  22. static void led_trigger_set_panic(struct led_classdev *led_cdev)
  23. {
  24. struct led_trigger *trig;
  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. /* Avoid the delayed blink path */
  32. led_cdev->blink_delay_on = 0;
  33. led_cdev->blink_delay_off = 0;
  34. led_cdev->trigger = trig;
  35. if (trig->activate)
  36. trig->activate(led_cdev);
  37. break;
  38. }
  39. }
  40. static int led_trigger_panic_notifier(struct notifier_block *nb,
  41. unsigned long code, void *unused)
  42. {
  43. struct led_classdev *led_cdev;
  44. list_for_each_entry(led_cdev, &leds_list, node)
  45. if (led_cdev->flags & LED_PANIC_INDICATOR)
  46. led_trigger_set_panic(led_cdev);
  47. return NOTIFY_DONE;
  48. }
  49. static struct notifier_block led_trigger_panic_nb = {
  50. .notifier_call = led_trigger_panic_notifier,
  51. };
  52. static long led_panic_blink(int state)
  53. {
  54. led_trigger_event(trigger, state ? LED_FULL : LED_OFF);
  55. return 0;
  56. }
  57. static int __init ledtrig_panic_init(void)
  58. {
  59. atomic_notifier_chain_register(&panic_notifier_list,
  60. &led_trigger_panic_nb);
  61. led_trigger_register_simple("panic", &trigger);
  62. panic_blink = led_panic_blink;
  63. return 0;
  64. }
  65. device_initcall(ledtrig_panic_init);