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