mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	drm/panic: Add a drm panic handler
This module displays a user friendly message when a kernel panic occurs. It currently doesn't contain any debug information, but that can be added later. v2 * Use get_scanout_buffer() instead of the drm client API. (Thomas Zimmermann) * Add the panic reason to the panic message (Nerdopolis) * Add an exclamation mark (Nerdopolis) v3 * Rework the drawing functions, to write the pixels line by line and to use the drm conversion helper to support other formats. (Thomas Zimmermann) v4 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann) * Remove the default y to DRM_PANIC config option (Thomas Zimmermann) * Add foreground/background color config option * Fix the bottom lines not painted if the framebuffer height is not a multiple of the font height. * Automatically register the device to drm_panic, if the function get_scanout_buffer exists. (Thomas Zimmermann) v5 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font. * Also add drm_fb_fill() to fill area with background color. * Add draw_pixel_xy() API for drivers that can't provide a linear buffer. * Add a flush() callback for drivers that needs to synchronize the buffer. * Add a void *private field, so drivers can pass private data to draw_pixel_xy() and flush(). v6 * Fix sparse warning for panic_msg and logo. v7 * Add select DRM_KMS_HELPER for the color conversion functions. v8 * Register directly each plane to the panic notifier (Sima) * Add raw_spinlock to properly handle concurrency (Sima) * Register plane instead of device, to avoid looping through plane list, and simplify code. * Replace get_scanout_buffer() logic with drm_panic_set_buffer() (Thomas Zimmermann) * Removed the draw_pixel_xy() API, will see later if it can be added back. v9 * Revert to using get_scanout_buffer() (Sima) * Move get_scanout_buffer() and panic_flush() to the plane helper functions (Thomas Zimmermann) * Register all planes with get_scanout_buffer() to the panic notifier * Use drm_panic_lock() to protect against race (Sima) v10 * Move blit and fill functions back in drm_panic (Thomas Zimmermann). * Simplify the text drawing functions. * Use kmsg_dumper instead of panic_notifier (Sima). v12 * Use array for map and pitch in struct drm_scanout_buffer to support multi-planar format later. (Thomas Zimmermann) * Better indent struct drm_scanout_buffer declaration. (Thomas Zimmermann) Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240409163432.352518-3-jfalempe@redhat.com Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
		
							parent
							
								
									e2a1cda3e0
								
							
						
					
					
						commit
						bf9fb17c66
					
				
					 8 changed files with 435 additions and 0 deletions
				
			
		|  | @ -398,6 +398,21 @@ Plane Damage Tracking Functions Reference | |||
| .. kernel-doc:: include/drm/drm_damage_helper.h | ||||
|    :internal: | ||||
| 
 | ||||
| Plane Panic Feature | ||||
| ------------------- | ||||
| 
 | ||||
| .. kernel-doc:: drivers/gpu/drm/drm_panic.c | ||||
|    :doc: overview | ||||
| 
 | ||||
| Plane Panic Functions Reference | ||||
| ------------------------------- | ||||
| 
 | ||||
| .. kernel-doc:: include/drm/drm_panic.h | ||||
|    :internal: | ||||
| 
 | ||||
| .. kernel-doc:: drivers/gpu/drm/drm_panic.c | ||||
|    :export: | ||||
| 
 | ||||
| Display Modes Function Reference | ||||
| ================================ | ||||
| 
 | ||||
|  |  | |||
|  | @ -104,6 +104,29 @@ config DRM_KMS_HELPER | |||
| 	help | ||||
| 	  CRTC helpers for KMS drivers. | ||||
| 
 | ||||
| config DRM_PANIC | ||||
| 	bool "Display a user-friendly message when a kernel panic occurs" | ||||
| 	depends on DRM && !FRAMEBUFFER_CONSOLE | ||||
| 	select DRM_KMS_HELPER | ||||
| 	select FONT_SUPPORT | ||||
| 	help | ||||
| 	  Enable a drm panic handler, which will display a user-friendly message | ||||
| 	  when a kernel panic occurs. It's useful when using a user-space | ||||
| 	  console instead of fbcon. | ||||
| 	  It will only work if your graphic driver supports this feature. | ||||
| 	  To support Hi-DPI Display, you can enable bigger fonts like | ||||
| 	  FONT_TER16x32 | ||||
| 
 | ||||
| config DRM_PANIC_FOREGROUND_COLOR | ||||
| 	hex "Drm panic screen foreground color, in RGB" | ||||
| 	depends on DRM_PANIC | ||||
| 	default 0xffffff | ||||
| 
 | ||||
| config DRM_PANIC_BACKGROUND_COLOR | ||||
| 	hex "Drm panic screen background color, in RGB" | ||||
| 	depends on DRM_PANIC | ||||
| 	default 0x000000 | ||||
| 
 | ||||
| config DRM_DEBUG_DP_MST_TOPOLOGY_REFS | ||||
|         bool "Enable refcount backtrace history in the DP MST helpers" | ||||
| 	depends on STACKTRACE_SUPPORT | ||||
|  |  | |||
|  | @ -88,6 +88,7 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \ | |||
| 	drm_privacy_screen.o \
 | ||||
| 	drm_privacy_screen_x86.o | ||||
| drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o | ||||
| drm-$(CONFIG_DRM_PANIC) += drm_panic.o | ||||
| obj-$(CONFIG_DRM)	+= drm.o | ||||
| 
 | ||||
| obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ | |||
| #include <drm/drm_file.h> | ||||
| #include <drm/drm_managed.h> | ||||
| #include <drm/drm_mode_object.h> | ||||
| #include <drm/drm_panic.h> | ||||
| #include <drm/drm_print.h> | ||||
| #include <drm/drm_privacy_screen_machine.h> | ||||
| 
 | ||||
|  | @ -944,6 +945,7 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) | |||
| 		if (ret) | ||||
| 			goto err_unload; | ||||
| 	} | ||||
| 	drm_panic_register(dev); | ||||
| 
 | ||||
| 	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", | ||||
| 		 driver->name, driver->major, driver->minor, | ||||
|  | @ -988,6 +990,8 @@ void drm_dev_unregister(struct drm_device *dev) | |||
| { | ||||
| 	dev->registered = false; | ||||
| 
 | ||||
| 	drm_panic_unregister(dev); | ||||
| 
 | ||||
| 	drm_client_dev_unregister(dev); | ||||
| 
 | ||||
| 	if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||||
|  |  | |||
							
								
								
									
										290
									
								
								drivers/gpu/drm/drm_panic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										290
									
								
								drivers/gpu/drm/drm_panic.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,290 @@ | |||
| // SPDX-License-Identifier: GPL-2.0 or MIT
 | ||||
| /*
 | ||||
|  * Copyright (c) 2023 Red Hat. | ||||
|  * Author: Jocelyn Falempe <jfalempe@redhat.com> | ||||
|  * inspired by the drm_log driver from David Herrmann <dh.herrmann@gmail.com> | ||||
|  * Tux Ascii art taken from cowsay written by Tony Monroe | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/font.h> | ||||
| #include <linux/iosys-map.h> | ||||
| #include <linux/kdebug.h> | ||||
| #include <linux/kmsg_dump.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| #include <drm/drm_drv.h> | ||||
| #include <drm/drm_format_helper.h> | ||||
| #include <drm/drm_fourcc.h> | ||||
| #include <drm/drm_framebuffer.h> | ||||
| #include <drm/drm_modeset_helper_vtables.h> | ||||
| #include <drm/drm_panic.h> | ||||
| #include <drm/drm_plane.h> | ||||
| #include <drm/drm_print.h> | ||||
| 
 | ||||
| MODULE_AUTHOR("Jocelyn Falempe"); | ||||
| MODULE_DESCRIPTION("DRM panic handler"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| 
 | ||||
| /**
 | ||||
|  * DOC: overview | ||||
|  * | ||||
|  * To enable DRM panic for a driver, the primary plane must implement a | ||||
|  * &drm_plane_helper_funcs.get_scanout_buffer helper function. It is then | ||||
|  * automatically registered to the drm panic handler. | ||||
|  * When a panic occurs, the &drm_plane_helper_funcs.get_scanout_buffer will be | ||||
|  * called, and the driver can provide a framebuffer so the panic handler can | ||||
|  * draw the panic screen on it. Currently only linear buffer and a few color | ||||
|  * formats are supported. | ||||
|  * Optionally the driver can also provide a &drm_plane_helper_funcs.panic_flush | ||||
|  * callback, that will be called after that, to send additional commands to the | ||||
|  * hardware to make the scanout buffer visible. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * This module displays a user friendly message on screen when a kernel panic | ||||
|  * occurs. This is conflicting with fbcon, so you can only enable it when fbcon | ||||
|  * is disabled. | ||||
|  * It's intended for end-user, so have minimal technical/debug information. | ||||
|  * | ||||
|  * Implementation details: | ||||
|  * | ||||
|  * It is a panic handler, so it can't take lock, allocate memory, run tasks/irq, | ||||
|  * or attempt to sleep. It's a best effort, and it may not be able to display | ||||
|  * the message in all situations (like if the panic occurs in the middle of a | ||||
|  * modesetting). | ||||
|  * It will display only one static frame, so performance optimizations are low | ||||
|  * priority as the machine is already in an unusable state. | ||||
|  */ | ||||
| 
 | ||||
| struct drm_panic_line { | ||||
| 	u32 len; | ||||
| 	const char *txt; | ||||
| }; | ||||
| 
 | ||||
| #define PANIC_LINE(s) {.len = sizeof(s) - 1, .txt = s} | ||||
| 
 | ||||
| static struct drm_panic_line panic_msg[] = { | ||||
| 	PANIC_LINE("KERNEL PANIC !"), | ||||
| 	PANIC_LINE(""), | ||||
| 	PANIC_LINE("Please reboot your computer."), | ||||
| }; | ||||
| 
 | ||||
| static const struct drm_panic_line logo[] = { | ||||
| 	PANIC_LINE("     .--.        _"), | ||||
| 	PANIC_LINE("    |o_o |      | |"), | ||||
| 	PANIC_LINE("    |:_/ |      | |"), | ||||
| 	PANIC_LINE("   //   \\ \\     |_|"), | ||||
| 	PANIC_LINE("  (|     | )     _"), | ||||
| 	PANIC_LINE(" /'\\_   _/`\\    (_)"), | ||||
| 	PANIC_LINE(" \\___)=(___/"), | ||||
| }; | ||||
| 
 | ||||
| static void drm_panic_fill32(struct iosys_map *map, unsigned int pitch, | ||||
| 			     unsigned int height, unsigned int width, | ||||
| 			     u32 color) | ||||
| { | ||||
| 	unsigned int y, x; | ||||
| 
 | ||||
| 	for (y = 0; y < height; y++) | ||||
| 		for (x = 0; x < width; x++) | ||||
| 			iosys_map_wr(map, y * pitch + x * sizeof(u32), u32, color); | ||||
| } | ||||
| 
 | ||||
| static void drm_panic_blit32(struct iosys_map *dmap, unsigned int dpitch, | ||||
| 			     const u8 *sbuf8, unsigned int spitch, | ||||
| 			     unsigned int height, unsigned int width, | ||||
| 			     u32 fg32, u32 bg32) | ||||
| { | ||||
| 	unsigned int y, x; | ||||
| 	u32 val32; | ||||
| 
 | ||||
| 	for (y = 0; y < height; y++) { | ||||
| 		for (x = 0; x < width; x++) { | ||||
| 			val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32; | ||||
| 			iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, val32); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static const u8 *get_char_bitmap(const struct font_desc *font, char c, size_t font_pitch) | ||||
| { | ||||
| 	return font->data + (c * font->height) * font_pitch; | ||||
| } | ||||
| 
 | ||||
| static unsigned int get_max_line_len(const struct drm_panic_line *lines, int len) | ||||
| { | ||||
| 	int i; | ||||
| 	unsigned int max = 0; | ||||
| 
 | ||||
| 	for (i = 0; i < len; i++) | ||||
| 		max = max(lines[i].len, max); | ||||
| 	return max; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Draw a text in a rectangle on a framebuffer. The text is truncated if it overflows the rectangle | ||||
|  */ | ||||
| static void draw_txt_rectangle(struct drm_scanout_buffer *sb, | ||||
| 			       const struct font_desc *font, | ||||
| 			       const struct drm_panic_line *msg, | ||||
| 			       unsigned int msg_lines, | ||||
| 			       bool centered, | ||||
| 			       struct drm_rect *clip, | ||||
| 			       u32 fg_color, | ||||
| 			       u32 bg_color) | ||||
| { | ||||
| 	int i, j; | ||||
| 	const u8 *src; | ||||
| 	size_t font_pitch = DIV_ROUND_UP(font->width, 8); | ||||
| 	struct iosys_map dst; | ||||
| 	unsigned int px_width = sb->format->cpp[0]; | ||||
| 	int left = 0; | ||||
| 
 | ||||
| 	msg_lines = min(msg_lines,  drm_rect_height(clip) / font->height); | ||||
| 	for (i = 0; i < msg_lines; i++) { | ||||
| 		size_t line_len = min(msg[i].len, drm_rect_width(clip) / font->width); | ||||
| 
 | ||||
| 		if (centered) | ||||
| 			left = (drm_rect_width(clip) - (line_len * font->width)) / 2; | ||||
| 
 | ||||
| 		dst = sb->map[0]; | ||||
| 		iosys_map_incr(&dst, (clip->y1 + i * font->height) * sb->pitch[0] + | ||||
| 				     (clip->x1 + left) * px_width); | ||||
| 		for (j = 0; j < line_len; j++) { | ||||
| 			src = get_char_bitmap(font, msg[i].txt[j], font_pitch); | ||||
| 			drm_panic_blit32(&dst, sb->pitch[0], src, font_pitch, | ||||
| 					 font->height, font->width, | ||||
| 					 fg_color, bg_color); | ||||
| 			iosys_map_incr(&dst, font->width * px_width); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Draw the panic message at the center of the screen | ||||
|  */ | ||||
| static void draw_panic_static(struct drm_scanout_buffer *sb) | ||||
| { | ||||
| 	size_t msg_lines = ARRAY_SIZE(panic_msg); | ||||
| 	size_t logo_lines = ARRAY_SIZE(logo); | ||||
| 	u32 fg_color = CONFIG_DRM_PANIC_FOREGROUND_COLOR; | ||||
| 	u32 bg_color = CONFIG_DRM_PANIC_BACKGROUND_COLOR; | ||||
| 	const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL); | ||||
| 	struct drm_rect r_logo, r_msg; | ||||
| 
 | ||||
| 	if (!font) | ||||
| 		return; | ||||
| 
 | ||||
| 	r_logo = DRM_RECT_INIT(0, 0, | ||||
| 			       get_max_line_len(logo, logo_lines) * font->width, | ||||
| 			       logo_lines * font->height); | ||||
| 	r_msg = DRM_RECT_INIT(0, 0, | ||||
| 			      min(get_max_line_len(panic_msg, msg_lines) * font->width, sb->width), | ||||
| 			      min(msg_lines * font->height, sb->height)); | ||||
| 
 | ||||
| 	/* Center the panic message */ | ||||
| 	drm_rect_translate(&r_msg, (sb->width - r_msg.x2) / 2, (sb->height - r_msg.y2) / 2); | ||||
| 
 | ||||
| 	/* Fill with the background color, and draw text on top */ | ||||
| 	drm_panic_fill32(&sb->map[0], sb->pitch[0], sb->height, sb->width, bg_color); | ||||
| 
 | ||||
| 	if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) && | ||||
| 	    drm_rect_width(&r_logo) < sb->width && drm_rect_height(&r_logo) < sb->height) { | ||||
| 		draw_txt_rectangle(sb, font, logo, logo_lines, false, &r_logo, fg_color, bg_color); | ||||
| 	} | ||||
| 	draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color, bg_color); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * drm_panic_is_format_supported() | ||||
|  * @format: a fourcc color code | ||||
|  * Returns: true if supported, false otherwise. | ||||
|  * | ||||
|  * Check if drm_panic will be able to use this color format. | ||||
|  */ | ||||
| static bool drm_panic_is_format_supported(const struct drm_format_info *format) | ||||
| { | ||||
| 	if (format->num_planes != 1) | ||||
| 		return false; | ||||
| 	return format->format == DRM_FORMAT_XRGB8888; | ||||
| } | ||||
| 
 | ||||
| static void draw_panic_plane(struct drm_plane *plane) | ||||
| { | ||||
| 	struct drm_scanout_buffer sb; | ||||
| 	int ret; | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| 	if (!drm_panic_trylock(plane->dev, flags)) | ||||
| 		return; | ||||
| 
 | ||||
| 	ret = plane->helper_private->get_scanout_buffer(plane, &sb); | ||||
| 
 | ||||
| 	if (!ret && drm_panic_is_format_supported(sb.format)) { | ||||
| 		draw_panic_static(&sb); | ||||
| 		if (plane->helper_private->panic_flush) | ||||
| 			plane->helper_private->panic_flush(plane); | ||||
| 	} | ||||
| 	drm_panic_unlock(plane->dev, flags); | ||||
| } | ||||
| 
 | ||||
| static struct drm_plane *to_drm_plane(struct kmsg_dumper *kd) | ||||
| { | ||||
| 	return container_of(kd, struct drm_plane, kmsg_panic); | ||||
| } | ||||
| 
 | ||||
| static void drm_panic(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason) | ||||
| { | ||||
| 	struct drm_plane *plane = to_drm_plane(dumper); | ||||
| 
 | ||||
| 	if (reason == KMSG_DUMP_PANIC) | ||||
| 		draw_panic_plane(plane); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_panic_register() - Initialize DRM panic for a device | ||||
|  * @dev: the drm device on which the panic screen will be displayed. | ||||
|  */ | ||||
| void drm_panic_register(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_plane *plane; | ||||
| 	int registered_plane = 0; | ||||
| 
 | ||||
| 	if (!dev->mode_config.num_total_plane) | ||||
| 		return; | ||||
| 
 | ||||
| 	drm_for_each_plane(plane, dev) { | ||||
| 		if (!plane->helper_private || !plane->helper_private->get_scanout_buffer) | ||||
| 			continue; | ||||
| 		plane->kmsg_panic.dump = drm_panic; | ||||
| 		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 | ||||
| 			registered_plane++; | ||||
| 	} | ||||
| 	if (registered_plane) | ||||
| 		drm_info(dev, "Registered %d planes with drm panic\n", registered_plane); | ||||
| } | ||||
| EXPORT_SYMBOL(drm_panic_register); | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_panic_unregister() | ||||
|  * @dev: the drm device previously registered. | ||||
|  */ | ||||
| void drm_panic_unregister(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_plane *plane; | ||||
| 
 | ||||
| 	if (!dev->mode_config.num_total_plane) | ||||
| 		return; | ||||
| 
 | ||||
| 	drm_for_each_plane(plane, dev) { | ||||
| 		if (!plane->helper_private || !plane->helper_private->get_scanout_buffer) | ||||
| 			continue; | ||||
| 		kmsg_dump_unregister(&plane->kmsg_panic); | ||||
| 	} | ||||
| } | ||||
| EXPORT_SYMBOL(drm_panic_unregister); | ||||
|  | @ -48,6 +48,7 @@ | |||
|  * To make this clear all the helper vtables are pulled together in this location here. | ||||
|  */ | ||||
| 
 | ||||
| struct drm_scanout_buffer; | ||||
| struct drm_writeback_connector; | ||||
| struct drm_writeback_job; | ||||
| 
 | ||||
|  | @ -1443,6 +1444,44 @@ struct drm_plane_helper_funcs { | |||
| 	 */ | ||||
| 	void (*atomic_async_update)(struct drm_plane *plane, | ||||
| 				    struct drm_atomic_state *state); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @get_scanout_buffer: | ||||
| 	 * | ||||
| 	 * Get the current scanout buffer, to display a message with drm_panic. | ||||
| 	 * The driver should do the minimum changes to provide a buffer, | ||||
| 	 * that can be used to display the panic screen. Currently only linear | ||||
| 	 * buffers are supported. Non-linear buffer support is on the TODO list. | ||||
| 	 * The device &dev.mode_config.panic_lock is taken before calling this | ||||
| 	 * function, so you can safely access the &plane.state | ||||
| 	 * It is called from a panic callback, and must follow its restrictions. | ||||
| 	 * Please look the documentation at drm_panic_trylock() for an in-depth | ||||
| 	 * discussions of what's safe and what is not allowed. | ||||
| 	 * It's a best effort mode, so it's expected that in some complex cases | ||||
| 	 * the panic screen won't be displayed. | ||||
| 	 * The returned &drm_scanout_buffer.map must be valid if no error code is | ||||
| 	 * returned. | ||||
| 	 * | ||||
| 	 * Return: | ||||
| 	 * %0 on success, negative errno on failure. | ||||
| 	 */ | ||||
| 	int (*get_scanout_buffer)(struct drm_plane *plane, | ||||
| 				  struct drm_scanout_buffer *sb); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @panic_flush: | ||||
| 	 * | ||||
| 	 * It is used by drm_panic, and is called after the panic screen is | ||||
| 	 * drawn to the scanout buffer. In this function, the driver | ||||
| 	 * can send additional commands to the hardware, to make the scanout | ||||
| 	 * buffer visible. | ||||
| 	 * It is only called if get_scanout_buffer() returned successfully, and | ||||
| 	 * the &dev.mode_config.panic_lock is held during the entire sequence. | ||||
| 	 * It is called from a panic callback, and must follow its restrictions. | ||||
| 	 * Please look the documentation at drm_panic_trylock() for an in-depth | ||||
| 	 * discussions of what's safe and what is not allowed. | ||||
| 	 */ | ||||
| 	void (*panic_flush)(struct drm_plane *plane); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -2,11 +2,56 @@ | |||
| #ifndef __DRM_PANIC_H__ | ||||
| #define __DRM_PANIC_H__ | ||||
| 
 | ||||
| #include <linux/module.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/iosys-map.h> | ||||
| 
 | ||||
| #include <drm/drm_device.h> | ||||
| #include <drm/drm_fourcc.h> | ||||
| /*
 | ||||
|  * Copyright (c) 2024 Intel | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * struct drm_scanout_buffer - DRM scanout buffer | ||||
|  * | ||||
|  * This structure holds the information necessary for drm_panic to draw the | ||||
|  * panic screen, and display it. | ||||
|  */ | ||||
| struct drm_scanout_buffer { | ||||
| 	/**
 | ||||
| 	 * @format: | ||||
| 	 * | ||||
| 	 * drm format of the scanout buffer. | ||||
| 	 */ | ||||
| 	const struct drm_format_info *format; | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @map: | ||||
| 	 * | ||||
| 	 * Virtual address of the scanout buffer, either in memory or iomem. | ||||
| 	 * The scanout buffer should be in linear format, and can be directly | ||||
| 	 * sent to the display hardware. Tearing is not an issue for the panic | ||||
| 	 * screen. | ||||
| 	 */ | ||||
| 	struct iosys_map map[DRM_FORMAT_MAX_PLANES]; | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @width: Width of the scanout buffer, in pixels. | ||||
| 	 */ | ||||
| 	unsigned int width; | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @height: Height of the scanout buffer, in pixels. | ||||
| 	 */ | ||||
| 	unsigned int height; | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @pitch: Length in bytes between the start of two consecutive lines. | ||||
| 	 */ | ||||
| 	unsigned int pitch[DRM_FORMAT_MAX_PLANES]; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_panic_trylock - try to enter the panic printing critical section | ||||
|  * @dev: struct drm_device | ||||
|  | @ -92,4 +137,16 @@ | |||
| #define drm_panic_unlock(dev, flags) \ | ||||
| 	raw_spin_unlock_irqrestore(&(dev)->mode_config.panic_lock, flags) | ||||
| 
 | ||||
| #ifdef CONFIG_DRM_PANIC | ||||
| 
 | ||||
| void drm_panic_register(struct drm_device *dev); | ||||
| void drm_panic_unregister(struct drm_device *dev); | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| static inline void drm_panic_register(struct drm_device *dev) {} | ||||
| static inline void drm_panic_unregister(struct drm_device *dev) {} | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif /* __DRM_PANIC_H__ */ | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ | |||
| 
 | ||||
| #include <linux/list.h> | ||||
| #include <linux/ctype.h> | ||||
| #include <linux/kmsg_dump.h> | ||||
| #include <drm/drm_mode_object.h> | ||||
| #include <drm/drm_color_mgmt.h> | ||||
| #include <drm/drm_rect.h> | ||||
|  | @ -780,6 +781,11 @@ struct drm_plane { | |||
| 	 * @hotspot_y_property: property to set mouse hotspot y offset. | ||||
| 	 */ | ||||
| 	struct drm_property *hotspot_y_property; | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @kmsg_panic: Used to register a panic notifier for this plane | ||||
| 	 */ | ||||
| 	struct kmsg_dumper kmsg_panic; | ||||
| }; | ||||
| 
 | ||||
| #define obj_to_plane(x) container_of(x, struct drm_plane, base) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Jocelyn Falempe
						Jocelyn Falempe