Add a debugfs file, so you can test drm_panic without freezing
your machine. This is unsafe, and should be enabled only for
developer or tester.

To display the drm_panic screen on the device 0:
echo 1 > /sys/kernel/debug/dri/0/drm_panic_plane_0

v9:
 * Create a debugfs file for each plane in the device's debugfs
   directory. This allows to test for each plane of each GPU
   independently.

Signed-off-by: Jocelyn Falempe <jfale...@redhat.com>
---
 drivers/gpu/drm/Kconfig     |  9 ++++++++
 drivers/gpu/drm/drm_panic.c | 43 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f07ca38d3f98..6e41fbd16b3d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -125,6 +125,15 @@ config DRM_PANIC_BACKGROUND_COLOR
        depends on DRM_PANIC
        default 0x000000
 
+config DRM_PANIC_DEBUG
+       bool "Add a debug fs entry to trigger drm_panic"
+       depends on DRM_PANIC && DEBUG_FS
+       help
+         Add dri/[device]/drm_panic_plane_x in the kernel debugfs, to force the
+         panic handler to write the panic message to this plane scanout buffer.
+         This is unsafe and should not be enabled on a production build.
+         If in doubt, say "N".
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
         bool "Enable refcount backtrace history in the DP MST helpers"
        depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index 7761779a884b..b75e90da7f39 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -493,6 +493,45 @@ static void drm_panic(struct kmsg_dumper *dumper, enum 
kmsg_dump_reason reason)
                draw_panic_plane(plane);
 }
 
+
+/*
+ * DEBUG FS, This is currently unsafe.
+ * Create one file per plane, so it's possible to debug one plane at a time.
+ */
+#ifdef CONFIG_DRM_PANIC_DEBUG
+#include <linux/debugfs.h>
+
+static ssize_t debugfs_trigger_write(struct file *file, const char __user 
*user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       bool run;
+
+       if (kstrtobool_from_user(user_buf, count, &run) == 0 && run) {
+               struct drm_plane *plane = file->private_data;
+
+               draw_panic_plane(plane);
+       }
+       return count;
+}
+
+static const struct file_operations dbg_drm_panic_ops = {
+       .owner = THIS_MODULE,
+       .write = debugfs_trigger_write,
+       .open = simple_open,
+};
+
+static void debugfs_register_plane(struct drm_plane *plane, int index)
+{
+       char fname[32];
+
+       snprintf(fname, 32, "drm_panic_plane_%d", index);
+       debugfs_create_file(fname, 0200, plane->dev->debugfs_root,
+                           plane, &dbg_drm_panic_ops);
+}
+#else
+static void debugfs_register_plane(struct drm_plane *plane, int index) {}
+#endif /* CONFIG_DRM_PANIC_DEBUG */
+
 /**
  * drm_panic_register() - Initialize DRM panic for a device
  * @dev: the drm device on which the panic screen will be displayed.
@@ -512,8 +551,10 @@ void drm_panic_register(struct drm_device *dev)
                plane->kmsg_panic.max_reason = KMSG_DUMP_PANIC;
                if (kmsg_dump_register(&plane->kmsg_panic))
                        drm_warn(dev, "Failed to register panic handler\n");
-               else
+               else {
+                       debugfs_register_plane(plane, registered_plane);
                        registered_plane++;
+               }
        }
        if (registered_plane)
                drm_info(dev, "Registered %d planes with drm panic\n", 
registered_plane);
-- 
2.44.0

Reply via email to