diff mbox series

[RFC,drm-next,1/1] drm/hyperv: Add support for drm_panic

Message ID 20250402084351.1545536-2-ryasuoka@redhat.com (mailing list archive)
State New
Headers show
Series Add support for drm_panic | expand

Commit Message

Ryosuke Yasuoka April 2, 2025, 8:43 a.m. UTC
Add drm_panic module supports for hyperv drm so that panic screen can be
displayed on panic.

Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
---
 drivers/gpu/drm/drm_simple_kms_helper.c     | 26 +++++++++++++
 drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 42 +++++++++++++++++++++
 include/drm/drm_simple_kms_helper.h         | 22 +++++++++++
 3 files changed, 90 insertions(+)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 250819fbc5ce..508a5961d2b0 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -14,6 +14,7 @@ 
 #include <drm/drm_managed.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_panic.h>
 
 /**
  * DOC: overview
@@ -316,6 +317,29 @@  static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
 	return modifier == DRM_FORMAT_MOD_LINEAR;
 }
 
+static int drm_simple_kms_plane_get_scanout_buffer(struct drm_plane *plane,
+						   struct drm_scanout_buffer *sb)
+{
+	struct drm_simple_display_pipe *pipe;
+
+	pipe = container_of(plane, struct drm_simple_display_pipe, plane);
+	if (!pipe->funcs || !pipe->funcs->get_scanout_buffer)
+		return -EINVAL;
+
+	return pipe->funcs->get_scanout_buffer(pipe, sb);
+}
+
+static void drm_simple_kms_plane_panic_flush(struct drm_plane *plane)
+{
+	struct drm_simple_display_pipe *pipe;
+
+	pipe = container_of(plane, struct drm_simple_display_pipe, plane);
+	if (!pipe->funcs || !pipe->funcs->panic_flush)
+		return;
+
+	pipe->funcs->panic_flush(pipe);
+}
+
 static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
 	.prepare_fb = drm_simple_kms_plane_prepare_fb,
 	.cleanup_fb = drm_simple_kms_plane_cleanup_fb,
@@ -323,6 +347,8 @@  static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
 	.end_fb_access = drm_simple_kms_plane_end_fb_access,
 	.atomic_check = drm_simple_kms_plane_atomic_check,
 	.atomic_update = drm_simple_kms_plane_atomic_update,
+	.get_scanout_buffer = drm_simple_kms_plane_get_scanout_buffer,
+	.panic_flush = drm_simple_kms_plane_panic_flush,
 };
 
 static void drm_simple_kms_plane_reset(struct drm_plane *plane)
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
index 6c6b57298797..8e8eacb0d07f 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
@@ -16,6 +16,7 @@ 
 #include <drm/drm_gem_shmem_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_panic.h>
 
 #include "hyperv_drm.h"
 
@@ -146,10 +147,51 @@  static void hyperv_pipe_update(struct drm_simple_display_pipe *pipe,
 	}
 }
 
+static int hyperv_pipe_get_scanout_buffer(struct drm_simple_display_pipe *pipe,
+					  struct drm_scanout_buffer *sb)
+{
+	struct drm_plane_state *state = pipe->plane.state;
+	struct hyperv_drm_device *hv;
+	struct drm_framebuffer *fb;
+
+	if (!state || !state->fb || !state->visible)
+		return -ENODEV;
+
+	fb = state->fb;
+	hv = to_hv(fb->dev);
+
+	iosys_map_set_vaddr_iomem(&sb->map[0], hv->vram);
+	sb->format = fb->format;
+	sb->height = fb->height;
+	sb->width = fb->width;
+	sb->pitch[0] = fb->pitches[0];
+	return 0;
+}
+
+static void hyperv_pipe_panic_flush(struct drm_simple_display_pipe *pipe)
+{
+	struct drm_plane_state *state = pipe->plane.state;
+	struct hyperv_drm_device *hv;
+	struct drm_rect rect;
+
+	if (!state || !state->fb)
+		return;
+
+	rect.x1 = 0;
+	rect.y1 = 0;
+	rect.x2 = state->fb->width;
+	rect.y2 = state->fb->height;
+
+	hv = to_hv(state->fb->dev);
+	hyperv_update_dirt(hv->hdev, &rect);
+}
+
 static const struct drm_simple_display_pipe_funcs hyperv_pipe_funcs = {
 	.enable	= hyperv_pipe_enable,
 	.check = hyperv_pipe_check,
 	.update	= hyperv_pipe_update,
+	.get_scanout_buffer = hyperv_pipe_get_scanout_buffer,
+	.panic_flush = hyperv_pipe_panic_flush,
 	DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
 };
 
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index b2486d073763..126d0d170e81 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -10,6 +10,7 @@ 
 #include <drm/drm_encoder.h>
 #include <drm/drm_plane.h>
 
+struct drm_scanout_buffer;
 struct drm_simple_display_pipe;
 
 /**
@@ -226,6 +227,27 @@  struct drm_simple_display_pipe_funcs {
 	 */
 	void (*destroy_plane_state)(struct drm_simple_display_pipe *pipe,
 				    struct drm_plane_state *plane_state);
+
+	/**
+	 * @get_scanout_buffer:
+	 *
+	 * Optional, called by &drm_plane_funcs.get_scanout_buffer. Please
+	 * read the documentation for the &drm_plane_funcs.get_scanout_buffer
+	 * hook for more details.
+	 *
+	 */
+	int (*get_scanout_buffer)(struct drm_simple_display_pipe *pipe,
+				  struct drm_scanout_buffer *sb);
+
+	/**
+	 * @panic_flush:
+	 *
+	 * Optional, called by &drm_plane_funcs.panic_flush. Please read the
+	 * documentation for the &drm_plane_funcs.get_scanout_buffer hook for
+	 * more details.
+	 *
+	 */
+	void (*panic_flush)(struct drm_simple_display_pipe *pipe);
 };
 
 /**