[PATCH 04/12] drm/panic: Return errno codes if panic output fails
Jocelyn Falempe
jfalempe at redhat.com
Thu Aug 20 10:05:57 PDT 2026
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 <jfalempe at redhat.com>
>
> Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
> ---
> 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)
More information about the linux-arm-kernel
mailing list