xref: /linux/include/drm/drm_panic.h (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1e2a1cda3SDaniel Vetter /* SPDX-License-Identifier: GPL-2.0 or MIT */
2*96913586SJocelyn Falempe 
3*96913586SJocelyn Falempe /*
4*96913586SJocelyn Falempe  * Copyright (c) 2024 Intel
5*96913586SJocelyn Falempe  * Copyright (c) 2024 Red Hat
6*96913586SJocelyn Falempe  */
7*96913586SJocelyn Falempe 
8e2a1cda3SDaniel Vetter #ifndef __DRM_PANIC_H__
9e2a1cda3SDaniel Vetter #define __DRM_PANIC_H__
10e2a1cda3SDaniel Vetter 
11bf9fb17cSJocelyn Falempe #include <linux/module.h>
12bf9fb17cSJocelyn Falempe #include <linux/types.h>
13bf9fb17cSJocelyn Falempe #include <linux/iosys-map.h>
14bf9fb17cSJocelyn Falempe 
15e2a1cda3SDaniel Vetter #include <drm/drm_device.h>
16bf9fb17cSJocelyn Falempe #include <drm/drm_fourcc.h>
17e2a1cda3SDaniel Vetter 
18e2a1cda3SDaniel Vetter /**
19bf9fb17cSJocelyn Falempe  * struct drm_scanout_buffer - DRM scanout buffer
20bf9fb17cSJocelyn Falempe  *
21bf9fb17cSJocelyn Falempe  * This structure holds the information necessary for drm_panic to draw the
22bf9fb17cSJocelyn Falempe  * panic screen, and display it.
23bf9fb17cSJocelyn Falempe  */
24bf9fb17cSJocelyn Falempe struct drm_scanout_buffer {
25bf9fb17cSJocelyn Falempe 	/**
26bf9fb17cSJocelyn Falempe 	 * @format:
27bf9fb17cSJocelyn Falempe 	 *
28bf9fb17cSJocelyn Falempe 	 * drm format of the scanout buffer.
29bf9fb17cSJocelyn Falempe 	 */
30bf9fb17cSJocelyn Falempe 	const struct drm_format_info *format;
31bf9fb17cSJocelyn Falempe 
32bf9fb17cSJocelyn Falempe 	/**
33bf9fb17cSJocelyn Falempe 	 * @map:
34bf9fb17cSJocelyn Falempe 	 *
35bf9fb17cSJocelyn Falempe 	 * Virtual address of the scanout buffer, either in memory or iomem.
36bf9fb17cSJocelyn Falempe 	 * The scanout buffer should be in linear format, and can be directly
37bf9fb17cSJocelyn Falempe 	 * sent to the display hardware. Tearing is not an issue for the panic
38bf9fb17cSJocelyn Falempe 	 * screen.
39bf9fb17cSJocelyn Falempe 	 */
40bf9fb17cSJocelyn Falempe 	struct iosys_map map[DRM_FORMAT_MAX_PLANES];
41bf9fb17cSJocelyn Falempe 
42bf9fb17cSJocelyn Falempe 	/**
43bf9fb17cSJocelyn Falempe 	 * @width: Width of the scanout buffer, in pixels.
44bf9fb17cSJocelyn Falempe 	 */
45bf9fb17cSJocelyn Falempe 	unsigned int width;
46bf9fb17cSJocelyn Falempe 
47bf9fb17cSJocelyn Falempe 	/**
48bf9fb17cSJocelyn Falempe 	 * @height: Height of the scanout buffer, in pixels.
49bf9fb17cSJocelyn Falempe 	 */
50bf9fb17cSJocelyn Falempe 	unsigned int height;
51bf9fb17cSJocelyn Falempe 
52bf9fb17cSJocelyn Falempe 	/**
53bf9fb17cSJocelyn Falempe 	 * @pitch: Length in bytes between the start of two consecutive lines.
54bf9fb17cSJocelyn Falempe 	 */
55bf9fb17cSJocelyn Falempe 	unsigned int pitch[DRM_FORMAT_MAX_PLANES];
5624d07f11SJocelyn Falempe 
5724d07f11SJocelyn Falempe 	/**
5824d07f11SJocelyn Falempe 	 * @set_pixel: Optional function, to set a pixel color on the
5924d07f11SJocelyn Falempe 	 * framebuffer. It allows to handle special tiling format inside the
6024d07f11SJocelyn Falempe 	 * driver.
6124d07f11SJocelyn Falempe 	 */
6224d07f11SJocelyn Falempe 	void (*set_pixel)(struct drm_scanout_buffer *sb, unsigned int x,
6324d07f11SJocelyn Falempe 			  unsigned int y, u32 color);
6424d07f11SJocelyn Falempe 
65bf9fb17cSJocelyn Falempe };
66bf9fb17cSJocelyn Falempe 
67bf9fb17cSJocelyn Falempe /**
68e2a1cda3SDaniel Vetter  * drm_panic_trylock - try to enter the panic printing critical section
69e2a1cda3SDaniel Vetter  * @dev: struct drm_device
70e2a1cda3SDaniel Vetter  * @flags: unsigned long irq flags you need to pass to the unlock() counterpart
71e2a1cda3SDaniel Vetter  *
72e2a1cda3SDaniel Vetter  * This function must be called by any panic printing code. The panic printing
73e2a1cda3SDaniel Vetter  * attempt must be aborted if the trylock fails.
74e2a1cda3SDaniel Vetter  *
75e2a1cda3SDaniel Vetter  * Panic printing code can make the following assumptions while holding the
76e2a1cda3SDaniel Vetter  * panic lock:
77e2a1cda3SDaniel Vetter  *
78e2a1cda3SDaniel Vetter  * - Anything protected by drm_panic_lock() and drm_panic_unlock() pairs is safe
79e2a1cda3SDaniel Vetter  *   to access.
80e2a1cda3SDaniel Vetter  *
81e2a1cda3SDaniel Vetter  * - Furthermore the panic printing code only registers in drm_dev_unregister()
82e2a1cda3SDaniel Vetter  *   and gets removed in drm_dev_unregister(). This allows the panic code to
83e2a1cda3SDaniel Vetter  *   safely access any state which is invariant in between these two function
84e2a1cda3SDaniel Vetter  *   calls, like the list of planes &drm_mode_config.plane_list or most of the
85e2a1cda3SDaniel Vetter  *   struct drm_plane structure.
86e2a1cda3SDaniel Vetter  *
87e2a1cda3SDaniel Vetter  * Specifically thanks to the protection around plane updates in
88e2a1cda3SDaniel Vetter  * drm_atomic_helper_swap_state() the following additional guarantees hold:
89e2a1cda3SDaniel Vetter  *
90e2a1cda3SDaniel Vetter  * - It is safe to deference the drm_plane.state pointer.
91e2a1cda3SDaniel Vetter  *
92e2a1cda3SDaniel Vetter  * - Anything in struct drm_plane_state or the driver's subclass thereof which
93e2a1cda3SDaniel Vetter  *   stays invariant after the atomic check code has finished is safe to access.
94e2a1cda3SDaniel Vetter  *   Specifically this includes the reference counted pointers to framebuffer
95e2a1cda3SDaniel Vetter  *   and buffer objects.
96e2a1cda3SDaniel Vetter  *
97e2a1cda3SDaniel Vetter  * - Anything set up by &drm_plane_helper_funcs.fb_prepare and cleaned up
98e2a1cda3SDaniel Vetter  *   &drm_plane_helper_funcs.fb_cleanup is safe to access, as long as it stays
99e2a1cda3SDaniel Vetter  *   invariant between these two calls. This also means that for drivers using
100e2a1cda3SDaniel Vetter  *   dynamic buffer management the framebuffer is pinned, and therefer all
101e2a1cda3SDaniel Vetter  *   relevant datastructures can be accessed without taking any further locks
102e2a1cda3SDaniel Vetter  *   (which would be impossible in panic context anyway).
103e2a1cda3SDaniel Vetter  *
104e2a1cda3SDaniel Vetter  * - Importantly, software and hardware state set up by
105e2a1cda3SDaniel Vetter  *   &drm_plane_helper_funcs.begin_fb_access and
106e2a1cda3SDaniel Vetter  *   &drm_plane_helper_funcs.end_fb_access is not safe to access.
107e2a1cda3SDaniel Vetter  *
108e2a1cda3SDaniel Vetter  * Drivers must not make any assumptions about the actual state of the hardware,
109e2a1cda3SDaniel Vetter  * unless they explicitly protected these hardware access with drm_panic_lock()
110e2a1cda3SDaniel Vetter  * and drm_panic_unlock().
111e2a1cda3SDaniel Vetter  *
112e2a1cda3SDaniel Vetter  * Return:
113e2a1cda3SDaniel Vetter  * %0 when failing to acquire the raw spinlock, nonzero on success.
114e2a1cda3SDaniel Vetter  */
115e2a1cda3SDaniel Vetter #define drm_panic_trylock(dev, flags) \
116e2a1cda3SDaniel Vetter 	raw_spin_trylock_irqsave(&(dev)->mode_config.panic_lock, flags)
117e2a1cda3SDaniel Vetter 
118e2a1cda3SDaniel Vetter /**
119e2a1cda3SDaniel Vetter  * drm_panic_lock - protect panic printing relevant state
120e2a1cda3SDaniel Vetter  * @dev: struct drm_device
121e2a1cda3SDaniel Vetter  * @flags: unsigned long irq flags you need to pass to the unlock() counterpart
122e2a1cda3SDaniel Vetter  *
123e2a1cda3SDaniel Vetter  * This function must be called to protect software and hardware state that the
124e2a1cda3SDaniel Vetter  * panic printing code must be able to rely on. The protected sections must be
125e2a1cda3SDaniel Vetter  * as small as possible. It uses the irqsave/irqrestore variant, and can be
126e2a1cda3SDaniel Vetter  * called from irq handler. Examples include:
127e2a1cda3SDaniel Vetter  *
128e2a1cda3SDaniel Vetter  * - Access to peek/poke or other similar registers, if that is the way the
129e2a1cda3SDaniel Vetter  *   driver prints the pixels into the scanout buffer at panic time.
130e2a1cda3SDaniel Vetter  *
131e2a1cda3SDaniel Vetter  * - Updates to pointers like &drm_plane.state, allowing the panic handler to
132e2a1cda3SDaniel Vetter  *   safely deference these. This is done in drm_atomic_helper_swap_state().
133e2a1cda3SDaniel Vetter  *
134e2a1cda3SDaniel Vetter  * - An state that isn't invariant and that the driver must be able to access
135e2a1cda3SDaniel Vetter  *   during panic printing.
136e2a1cda3SDaniel Vetter  */
137e2a1cda3SDaniel Vetter 
138e2a1cda3SDaniel Vetter #define drm_panic_lock(dev, flags) \
139e2a1cda3SDaniel Vetter 	raw_spin_lock_irqsave(&(dev)->mode_config.panic_lock, flags)
140e2a1cda3SDaniel Vetter 
141e2a1cda3SDaniel Vetter /**
142e2a1cda3SDaniel Vetter  * drm_panic_unlock - end of the panic printing critical section
143e2a1cda3SDaniel Vetter  * @dev: struct drm_device
144e2a1cda3SDaniel Vetter  * @flags: irq flags that were returned when acquiring the lock
145e2a1cda3SDaniel Vetter  *
146e2a1cda3SDaniel Vetter  * Unlocks the raw spinlock acquired by either drm_panic_lock() or
147e2a1cda3SDaniel Vetter  * drm_panic_trylock().
148e2a1cda3SDaniel Vetter  */
149e2a1cda3SDaniel Vetter #define drm_panic_unlock(dev, flags) \
150e2a1cda3SDaniel Vetter 	raw_spin_unlock_irqrestore(&(dev)->mode_config.panic_lock, flags)
151e2a1cda3SDaniel Vetter 
152e2a1cda3SDaniel Vetter #endif /* __DRM_PANIC_H__ */
153