From e85e9ccf3f8404007f62dff9a02273fcdeb44206 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 27 Nov 2025 09:03:49 +0000 Subject: [PATCH] drm/panic: Report invalid or unsupported panic modes Currently the user can write anything into the drm.panic_screen modparam, either at runtime via sysfs, or as a kernel boot time argument. Invalid strings will be silently accepted and ignored at use time by defaulting to the 'user' panic mode. Let instead add some validation in order to have immediate feedback when something has been mistyped, or not compiled in. For example during kernel boot: Booting kernel: `bsod' invalid for parameter `drm.panic_screen' Or at runtime: # echo -n bsod > /sys/module/drm/parameters/panic_screen -bash: echo: write error: Invalid argument Change of behavior is that when invalid mode is attempted to be configured, currently the code will default to the 'user' mode, while with this change the code will ignore it, and default to the mode set at kernel build time via CONFIG_DRM_PANIC_SCREEN. While at it lets also fix the module parameter description to include all compiled in modes. Signed-off-by: Tvrtko Ursulin Cc: Jocelyn Falempe Cc: Javier Martinez Canillas Reviewed-by: Javier Martinez Canillas Reviewed-by: Jocelyn Falempe Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20251127090349.92717-1-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/drm_panic.c | 75 ++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c index 1d6312fa14293..2635f95cbde5a 100644 --- a/drivers/gpu/drm/drm_panic.c +++ b/drivers/gpu/drm/drm_panic.c @@ -39,12 +39,6 @@ MODULE_AUTHOR("Jocelyn Falempe"); MODULE_DESCRIPTION("DRM panic handler"); MODULE_LICENSE("GPL"); -static char drm_panic_screen[16] = CONFIG_DRM_PANIC_SCREEN; -module_param_string(panic_screen, drm_panic_screen, sizeof(drm_panic_screen), 0644); -MODULE_PARM_DESC(panic_screen, - "Choose what will be displayed by drm_panic, 'user' or 'kmsg' [default=" - CONFIG_DRM_PANIC_SCREEN "]"); - /** * DOC: overview * @@ -765,14 +759,59 @@ static void draw_panic_static_qr_code(struct drm_scanout_buffer *sb) draw_panic_static_user(sb); } #else -static void draw_panic_static_qr_code(struct drm_scanout_buffer *sb) +static void drm_panic_qr_init(void) {}; +static void drm_panic_qr_exit(void) {}; +#endif + +enum drm_panic_type { + DRM_PANIC_TYPE_KMSG, + DRM_PANIC_TYPE_USER, + DRM_PANIC_TYPE_QR, +}; + +static enum drm_panic_type drm_panic_type = -1; + +static const char *drm_panic_type_map[] = { + [DRM_PANIC_TYPE_KMSG] = "kmsg", + [DRM_PANIC_TYPE_USER] = "user", +#if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE) + [DRM_PANIC_TYPE_QR] = "qr", +#endif +}; + +static int drm_panic_type_set(const char *val, const struct kernel_param *kp) { - draw_panic_static_user(sb); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(drm_panic_type_map); i++) { + if (!strcmp(val, drm_panic_type_map[i])) { + drm_panic_type = i; + return 0; + } + } + + return -EINVAL; } -static void drm_panic_qr_init(void) {}; -static void drm_panic_qr_exit(void) {}; +static int drm_panic_type_get(char *buffer, const struct kernel_param *kp) +{ + return scnprintf(buffer, PAGE_SIZE, "%s\n", + drm_panic_type_map[drm_panic_type]); +} + +static const struct kernel_param_ops drm_panic_ops = { + .set = drm_panic_type_set, + .get = drm_panic_type_get, +}; + +module_param_cb(panic_screen, &drm_panic_ops, NULL, 0644); +MODULE_PARM_DESC(panic_screen, +#if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE) + "Choose what will be displayed by drm_panic, 'user', 'kmsg' or 'qr' [default=" +#else + "Choose what will be displayed by drm_panic, 'user' or 'kmsg' [default=" #endif + CONFIG_DRM_PANIC_SCREEN "]"); /* * drm_panic_is_format_supported() @@ -790,11 +829,19 @@ static bool drm_panic_is_format_supported(const struct drm_format_info *format) static void draw_panic_dispatch(struct drm_scanout_buffer *sb) { - if (!strcmp(drm_panic_screen, "kmsg")) { + switch (drm_panic_type) { + case DRM_PANIC_TYPE_KMSG: draw_panic_static_kmsg(sb); - } else if (!strcmp(drm_panic_screen, "qr_code")) { + break; + +#if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE) + case DRM_PANIC_TYPE_QR: draw_panic_static_qr_code(sb); - } else { + break; +#endif + + case DRM_PANIC_TYPE_USER: + default: draw_panic_static_user(sb); } } @@ -977,6 +1024,8 @@ void drm_panic_unregister(struct drm_device *dev) */ void __init drm_panic_init(void) { + if (drm_panic_type == -1) + drm_panic_type_set(CONFIG_DRM_PANIC_SCREEN, NULL); drm_panic_qr_init(); } -- 2.47.3