On 18/08/2026 14:28, Thomas Zimmermann wrote:
Return errno codes from the panic output helpers to detect invalid
panic handling. Avoid flushing the display if an error ocured. The
unflushed display output might be helpful in debugging.

For now, test the result values in the panic test cases. A later patch
will add support for retrying failed panic output.

Thanks, it looks good to me.

Reviewed-by: Jocelyn Falempe <[email protected]>

Signed-off-by: Thomas Zimmermann <[email protected]>
---
  drivers/gpu/drm/drm_panic.c            | 41 +++++++++++++++++---------
  drivers/gpu/drm/tests/drm_panic_test.c | 16 ++++++----
  2 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index 96d238bfceee..594235661710 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -478,7 +478,7 @@ static void drm_panic_logo_draw(struct drm_scanout_buffer 
*sb, struct drm_rect *
                                   fg_color);
  }
-static void draw_panic_screen_user(struct drm_scanout_buffer *sb)
+static int draw_panic_screen_user(struct drm_scanout_buffer *sb)
  {
        u32 fg_color = 
drm_draw_color_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR,
                                                    sb->format->format);
@@ -489,7 +489,7 @@ static void draw_panic_screen_user(struct 
drm_scanout_buffer *sb)
        unsigned int msg_width, msg_height;
if (!font)
-               return;
+               return -EINVAL;
r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height);
        drm_panic_logo_rect(&r_logo, font);
@@ -508,6 +508,8 @@ static void draw_panic_screen_user(struct 
drm_scanout_buffer *sb)
                drm_panic_logo_draw(sb, &r_logo, font, fg_color);
draw_txt_rectangle(sb, font, panic_msg, panic_msg_lines, true, &r_msg, fg_color);
+
+       return 0;
  }
/*
@@ -547,7 +549,7 @@ static int draw_line_with_wrap(struct drm_scanout_buffer 
*sb, const struct font_
   * Draw the kmsg buffer to the screen, starting from the youngest message at 
the bottom,
   * and going up until reaching the top of the screen.
   */
-static void draw_panic_screen_kmsg(struct drm_scanout_buffer *sb)
+static int draw_panic_screen_kmsg(struct drm_scanout_buffer *sb)
  {
        u32 fg_color = 
drm_draw_color_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR,
                                                    sb->format->format);
@@ -562,7 +564,7 @@ static void draw_panic_screen_kmsg(struct 
drm_scanout_buffer *sb)
        int yoffset;
if (!font || font->width > sb->width)
-               return;
+               return -EINVAL;
yoffset = sb->height - font->height - (sb->height % font->height) / 2; @@ -589,6 +591,8 @@ static void draw_panic_screen_kmsg(struct drm_scanout_buffer *sb)
                        start--;
                }
        }
+
+       return 0;
  }
#if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
@@ -814,10 +818,11 @@ static int _draw_panic_screen_qr_code(struct 
drm_scanout_buffer *sb)
        return 0;
  }
-static void draw_panic_screen_qr_code(struct drm_scanout_buffer *sb)
+static int draw_panic_screen_qr_code(struct drm_scanout_buffer *sb)
  {
        if (_draw_panic_screen_qr_code(sb))
                draw_panic_screen_user(sb);
+       return 0;
  }
  #else
  static void drm_panic_qr_init(void) {};
@@ -888,23 +893,25 @@ static bool drm_panic_is_format_supported(const struct 
drm_format_info *format)
        return drm_draw_can_convert_from_xrgb8888(format->format);
  }
-static void draw_panic_dispatch(struct drm_scanout_buffer *sb)
+static int draw_panic_dispatch(struct drm_scanout_buffer *sb)
  {
+       int ret;
+
        switch (drm_panic_type) {
        case DRM_PANIC_TYPE_KMSG:
-               draw_panic_screen_kmsg(sb);
+               ret = draw_panic_screen_kmsg(sb);
                break;
-
  #if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
        case DRM_PANIC_TYPE_QR:
-               draw_panic_screen_qr_code(sb);
+               ret = draw_panic_screen_qr_code(sb);
                break;
  #endif
-
        case DRM_PANIC_TYPE_USER:
        default:
-               draw_panic_screen_user(sb);
+               ret = draw_panic_screen_user(sb);
        }
+
+       return ret;
  }
static void drm_panic_set_description(const char *description)
@@ -951,9 +958,15 @@ static void draw_panic_plane(struct drm_plane *plane, 
const char *description)
drm_panic_set_description(description); - draw_panic_dispatch(&sb);
-       if (plane->helper_private->panic_flush)
-               plane->helper_private->panic_flush(plane);
+       ret = draw_panic_dispatch(&sb);
+       if (!ret) {
+               /*
+                * Only flush if we have a panic screen to display. Otherwise
+                * it's probably better to leave the display output as-is.
+                */
+               if (plane->helper_private->panic_flush)
+                       plane->helper_private->panic_flush(plane);
+       }
drm_panic_clear_description(); diff --git a/drivers/gpu/drm/tests/drm_panic_test.c b/drivers/gpu/drm/tests/drm_panic_test.c
index ad2f3a2f93b6..fdd77b0cc54c 100644
--- a/drivers/gpu/drm/tests/drm_panic_test.c
+++ b/drivers/gpu/drm/tests/drm_panic_test.c
@@ -30,7 +30,7 @@ struct drm_test_mode {
        const int width;
        const int height;
        const u32 format;
-       void (*draw_screen)(struct drm_scanout_buffer *sb);
+       int (*draw_screen)(struct drm_scanout_buffer *sb);
        const char *fname;
  };
@@ -87,7 +87,7 @@ static void drm_test_panic_screen_user_map(struct kunit *test)
        const struct drm_test_mode *params = test->param_value;
        char *fb;
        int fb_size;
-       int i;
+       int i, ret;
sb->format = drm_format_info(params->format);
        fb_size = params->width * params->height * sb->format->cpp[0];
@@ -102,7 +102,8 @@ static void drm_test_panic_screen_user_map(struct kunit 
*test)
        sb->height = params->height;
        sb->pitch[0] = params->width * sb->format->cpp[0];
- params->draw_screen(sb);
+       ret = params->draw_screen(sb);
+       KUNIT_ASSERT_EQ(test, ret, 0);
for (i = 0; i < fb_size; i++)
                drm_panic_check_color_byte(test, fb[i]);
@@ -119,7 +120,7 @@ static void drm_test_panic_screen_user_page(struct kunit 
*test)
  {
        struct drm_scanout_buffer *sb = test->priv;
        const struct drm_test_mode *params = test->param_value;
-       int fb_size, p, i, npages;
+       int fb_size, p, i, npages, ret;
        struct page **pages;
        u8 *vaddr;
@@ -146,7 +147,8 @@ static void drm_test_panic_screen_user_page(struct kunit *test)
        sb->height = params->height;
        sb->pitch[0] = params->width * sb->format->cpp[0];
- params->draw_screen(sb);
+       ret = params->draw_screen(sb);
+       KUNIT_ASSERT_EQ(test, ret, 0);
for (p = 0; p < npages; p++) {
                int bytes_in_page = (p == npages - 1) ? fb_size - p * PAGE_SIZE 
: PAGE_SIZE;
@@ -182,6 +184,7 @@ static void drm_test_panic_screen_user_set_pixel(struct 
kunit *test)
  {
        struct drm_scanout_buffer *sb = test->priv;
        const struct drm_test_mode *params = test->param_value;
+       int ret;
sb->format = drm_format_info(params->format);
        sb->set_pixel = drm_test_panic_set_pixel;
@@ -189,7 +192,8 @@ static void drm_test_panic_screen_user_set_pixel(struct 
kunit *test)
        sb->height = params->height;
        sb->private = test;
- params->draw_screen(sb);
+       ret = params->draw_screen(sb);
+       KUNIT_ASSERT_EQ(test, ret, 0);
  }
static void drm_test_panic_desc(const struct drm_test_mode *t, char *desc)


Reply via email to