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