drm_client_sysrq.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. // SPDX-License-Identifier: GPL-2.0 or MIT
  2. #include <linux/sysrq.h>
  3. #include <drm/drm_client_event.h>
  4. #include <drm/drm_device.h>
  5. #include <drm/drm_print.h>
  6. #include "drm_internal.h"
  7. #ifdef CONFIG_MAGIC_SYSRQ
  8. static LIST_HEAD(drm_client_sysrq_dev_list);
  9. static DEFINE_MUTEX(drm_client_sysrq_dev_lock);
  10. /* emergency restore, don't bother with error reporting */
  11. static void drm_client_sysrq_restore_work_fn(struct work_struct *ignored)
  12. {
  13. struct drm_device *dev;
  14. guard(mutex)(&drm_client_sysrq_dev_lock);
  15. list_for_each_entry(dev, &drm_client_sysrq_dev_list, client_sysrq_list) {
  16. if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
  17. continue;
  18. drm_client_dev_restore(dev, true);
  19. }
  20. }
  21. static DECLARE_WORK(drm_client_sysrq_restore_work, drm_client_sysrq_restore_work_fn);
  22. static void drm_client_sysrq_restore_handler(u8 ignored)
  23. {
  24. schedule_work(&drm_client_sysrq_restore_work);
  25. }
  26. static const struct sysrq_key_op drm_client_sysrq_restore_op = {
  27. .handler = drm_client_sysrq_restore_handler,
  28. .help_msg = "force-fb(v)",
  29. .action_msg = "Restore framebuffer console",
  30. };
  31. void drm_client_sysrq_register(struct drm_device *dev)
  32. {
  33. guard(mutex)(&drm_client_sysrq_dev_lock);
  34. if (list_empty(&drm_client_sysrq_dev_list))
  35. register_sysrq_key('v', &drm_client_sysrq_restore_op);
  36. list_add(&dev->client_sysrq_list, &drm_client_sysrq_dev_list);
  37. }
  38. void drm_client_sysrq_unregister(struct drm_device *dev)
  39. {
  40. guard(mutex)(&drm_client_sysrq_dev_lock);
  41. /* remove device from global restore list */
  42. if (!drm_WARN_ON(dev, list_empty(&dev->client_sysrq_list)))
  43. list_del(&dev->client_sysrq_list);
  44. /* no devices left; unregister key */
  45. if (list_empty(&drm_client_sysrq_dev_list))
  46. unregister_sysrq_key('v', &drm_client_sysrq_restore_op);
  47. }
  48. #endif