diff options
| author | Dave Airlie <airlied@redhat.com> | 2026-09-18 11:43:54 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2026-09-18 11:58:41 +1000 |
| commit | 762a482b8615e4ce5672ae2b49359ddc51f4072d (patch) | |
| tree | 8afe0e74e8d9bb248d7c85d8043d2882d3ddd8cb /include | |
| parent | 2446a767ffacee0d247db932621cd4b165ad721a (diff) | |
| parent | a8fe4e162ba8212b7e51fdb024b37800f36b496c (diff) | |
Merge tag 'drm-misc-next-2026-09-17' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for v7.4:
UAPI Changes:
ivpu:
- add DRM_IVPU_CAP_CMDQ_SET_PRIORITY
Cross-subsystem Changes:
dma-fence:
- fix documentation
vga_switcheroo:
- disconnect from fbcon; update fbcon from within DRM fbdev emulation
Core Changes:
atomic:
- replace state reset callback with create_state throughout DRM core
and drivers
panic:
- split into core and helpers
sched:
- clean up interface
sysfs:
- drop drm_class_device_register()
Driver Changes:
amdxdna:
- fix BO handling
arcpgu:
- replace simple-display pipeline with regular atomic helpers
aspeed:
- replace simple-display pipeline with regular atomic helpers
gm12u320:
- replace simple-display pipeline with regular atomic helpers
imagination:
- various improvement to firmware interaction
ivpu:
- support command-queue priority ioctl
mcde:
- replace simple-display pipeline with regular atomic helpers
p111:
- replace simple-display pipeline with regular atomic helpers
- drop unsupported alpha formats from primary plane
panel:
- edp: Add support for BOE NV140FHM-T0A
- samsung: Share test-key helpers
rcar-du:
- support Renesas R-Car V4H DSC
- dsi: Support larger transfers with AXI memory
repaper:
- replace simple-display pipeline with regular atomic helpers
rockchip:
- dsi: improve PHY timings
ssd130x:
- support Solomon SSD1351 OLED plus DT bindings
- ssd133x: upgrade color format to RGB565
tve200:
- replace simple-display pipeline with regular atomic helpers
xen:
- replace simple-display pipeline with regular atomic helpers
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patch.msgid.link/20260917090534.GA420415@2a02-2455-9062-2500-ec39-e8a6-193-9c05.dyn6.pyur.net
Diffstat (limited to 'include')
| -rw-r--r-- | include/drm/drm_atomic.h | 89 | ||||
| -rw-r--r-- | include/drm/drm_atomic_state_helper.h | 6 | ||||
| -rw-r--r-- | include/drm/drm_client.h | 14 | ||||
| -rw-r--r-- | include/drm/drm_client_event.h | 3 | ||||
| -rw-r--r-- | include/drm/drm_crtc.h | 12 | ||||
| -rw-r--r-- | include/drm/drm_gem_atomic_helper.h | 2 | ||||
| -rw-r--r-- | include/drm/drm_mode_config.h | 4 | ||||
| -rw-r--r-- | include/drm/drm_modeset_helper_vtables.h | 25 | ||||
| -rw-r--r-- | include/drm/drm_panic.h | 117 | ||||
| -rw-r--r-- | include/drm/drm_panic_helper.h | 41 | ||||
| -rw-r--r-- | include/drm/drm_plane.h | 69 | ||||
| -rw-r--r-- | include/drm/drm_simple_kms_helper.h | 1 | ||||
| -rw-r--r-- | include/drm/drm_sysfs.h | 4 | ||||
| -rw-r--r-- | include/linux/dma-fence.h | 2 | ||||
| -rw-r--r-- | include/linux/vga_switcheroo.h | 29 | ||||
| -rw-r--r-- | include/uapi/drm/ivpu_accel.h | 17 |
16 files changed, 241 insertions, 194 deletions
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 88087910ab1a..3ae35b09c0cf 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -159,7 +159,23 @@ struct drm_crtc_commit { struct __drm_colorops_state { struct drm_colorop *ptr; - struct drm_colorop_state *state, *old_state, *new_state; + + /** + * @state_to_destroy: + * + * Used to track the @drm_colorop_state we will need to free + * when tearing down the associated &drm_atomic_commit in + * $drm_mode_config_funcs.atomic_state_clear or + * drm_atomic_commit_default_clear(). + * + * Before a commit, and the call to + * drm_atomic_helper_swap_state() in particular, it points to + * the same state than @new_state. After a commit, it points to + * the same state than @old_state. + */ + struct drm_colorop_state *state_to_destroy; + + struct drm_colorop_state *old_state, *new_state; }; struct __drm_planes_state { @@ -951,9 +967,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)++) \ for_each_if ((__state)->connectors[__i].ptr && \ ((connector) = (__state)->connectors[__i].ptr, \ - (void)(connector) /* Only to avoid unused-but-set-variable warning */, \ - (old_connector_state) = (__state)->connectors[__i].old_state, \ - (new_connector_state) = (__state)->connectors[__i].new_state, 1)) + (void)(connector) /* Only to avoid unused-but-set-variable warning */, \ + (old_connector_state) = (__state)->connectors[__i].old_state, \ + (void)(old_connector_state) /* Only to avoid unused-but-set-variable warning */, \ + (new_connector_state) = (__state)->connectors[__i].new_state, \ + (void)(new_connector_state) /* Only to avoid unused-but-set-variable warning */, 1)) /** * for_each_old_connector_in_state - iterate over all connectors in an atomic update @@ -973,8 +991,9 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)++) \ for_each_if ((__state)->connectors[__i].ptr && \ ((connector) = (__state)->connectors[__i].ptr, \ - (void)(connector) /* Only to avoid unused-but-set-variable warning */, \ - (old_connector_state) = (__state)->connectors[__i].old_state, 1)) + (void)(connector) /* Only to avoid unused-but-set-variable warning */, \ + (old_connector_state) = (__state)->connectors[__i].old_state, \ + (void)(old_connector_state) /* Only to avoid unused-but-set-variable warning */, 1)) /** * for_each_new_connector_in_state - iterate over all connectors in an atomic update @@ -994,9 +1013,9 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)++) \ for_each_if ((__state)->connectors[__i].ptr && \ ((connector) = (__state)->connectors[__i].ptr, \ - (void)(connector) /* Only to avoid unused-but-set-variable warning */, \ - (new_connector_state) = (__state)->connectors[__i].new_state, \ - (void)(new_connector_state) /* Only to avoid unused-but-set-variable warning */, 1)) + (void)(connector) /* Only to avoid unused-but-set-variable warning */, \ + (new_connector_state) = (__state)->connectors[__i].new_state, \ + (void)(new_connector_state) /* Only to avoid unused-but-set-variable warning */, 1)) /** * for_each_oldnew_crtc_in_state - iterate over all CRTCs in an atomic update @@ -1017,10 +1036,10 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); for_each_if ((__state)->crtcs[__i].ptr && \ ((crtc) = (__state)->crtcs[__i].ptr, \ (void)(crtc) /* Only to avoid unused-but-set-variable warning */, \ - (old_crtc_state) = (__state)->crtcs[__i].old_state, \ - (void)(old_crtc_state) /* Only to avoid unused-but-set-variable warning */, \ - (new_crtc_state) = (__state)->crtcs[__i].new_state, \ - (void)(new_crtc_state) /* Only to avoid unused-but-set-variable warning */, 1)) + (old_crtc_state) = (__state)->crtcs[__i].old_state, \ + (void)(old_crtc_state) /* Only to avoid unused-but-set-variable warning */, \ + (new_crtc_state) = (__state)->crtcs[__i].new_state, \ + (void)(new_crtc_state) /* Only to avoid unused-but-set-variable warning */, 1)) /** * for_each_old_crtc_in_state - iterate over all CRTCs in an atomic update @@ -1040,7 +1059,8 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); for_each_if ((__state)->crtcs[__i].ptr && \ ((crtc) = (__state)->crtcs[__i].ptr, \ (void)(crtc) /* Only to avoid unused-but-set-variable warning */, \ - (old_crtc_state) = (__state)->crtcs[__i].old_state, 1)) + (old_crtc_state) = (__state)->crtcs[__i].old_state, \ + (void)(old_crtc_state) /* Only to avoid unused-but-set-variable warning */, 1)) /** * for_each_new_crtc_in_state - iterate over all CRTCs in an atomic update @@ -1126,8 +1146,10 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); for_each_if ((__state)->planes[__i].ptr && \ ((plane) = (__state)->planes[__i].ptr, \ (void)(plane) /* Only to avoid unused-but-set-variable warning */, \ - (old_plane_state) = (__state)->planes[__i].old_state,\ - (new_plane_state) = (__state)->planes[__i].new_state, 1)) + (old_plane_state) = (__state)->planes[__i].old_state, \ + (void)(old_plane_state) /* Only to avoid unused-but-set-variable warning */, \ + (new_plane_state) = (__state)->planes[__i].new_state, \ + (void)(new_plane_state) /* Only to avoid unused-but-set-variable warning */, 1)) /** * for_each_oldnew_plane_in_state_reverse - iterate over all planes in an atomic @@ -1148,8 +1170,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)--) \ for_each_if ((__state)->planes[__i].ptr && \ ((plane) = (__state)->planes[__i].ptr, \ - (old_plane_state) = (__state)->planes[__i].old_state,\ - (new_plane_state) = (__state)->planes[__i].new_state, 1)) + (void)(plane) /* Only to avoid unused-but-set-variable warning */, \ + (old_plane_state) = (__state)->planes[__i].old_state, \ + (void)(old_plane_state) /* Only to avoid unused-but-set-variable warning */, \ + (new_plane_state) = (__state)->planes[__i].new_state, \ + (void)(new_plane_state) /* Only to avoid unused-but-set-variable warning */, 1)) /** * for_each_new_plane_in_state_reverse - other than only tracking new state, @@ -1165,7 +1190,9 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)--) \ for_each_if ((__state)->planes[__i].ptr && \ ((plane) = (__state)->planes[__i].ptr, \ - (new_plane_state) = (__state)->planes[__i].new_state, 1)) + (void)(plane) /* Only to avoid unused-but-set-variable warning */, \ + (new_plane_state) = (__state)->planes[__i].new_state, \ + (void)(new_plane_state) /* Only to avoid unused-but-set-variable warning */, 1)) /** * for_each_old_plane_in_state - iterate over all planes in an atomic update @@ -1184,7 +1211,10 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)++) \ for_each_if ((__state)->planes[__i].ptr && \ ((plane) = (__state)->planes[__i].ptr, \ - (old_plane_state) = (__state)->planes[__i].old_state, 1)) + (void)(plane) /* Only to avoid unused-but-set-variable warning */, \ + (old_plane_state) = (__state)->planes[__i].old_state, \ + (void)(old_plane_state) /* Only to avoid unused-but-set-variable warning */, 1)) + /** * for_each_new_plane_in_state - iterate over all planes in an atomic update * @__state: &struct drm_atomic_commit pointer @@ -1222,8 +1252,11 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); for ((__i) = 0; \ (__i) < (__state)->num_private_objs && \ ((obj) = (__state)->private_objs[__i].ptr, \ + (void)(obj) /* Only to avoid unused-but-set-variable warning */, \ (old_obj_state) = (__state)->private_objs[__i].old_state, \ - (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \ + (void)(old_obj_state) /* Only to avoid unused-but-set-variable warning */, \ + (new_obj_state) = (__state)->private_objs[__i].new_state, \ + (void)(new_obj_state) /* Only to avoid unused-but-set-variable warning */, 1); \ (__i)++) /** @@ -1241,7 +1274,9 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); for ((__i) = 0; \ (__i) < (__state)->num_private_objs && \ ((obj) = (__state)->private_objs[__i].ptr, \ - (old_obj_state) = (__state)->private_objs[__i].old_state, 1); \ + (void)(obj) /* Only to avoid unused-but-set-variable warning */, \ + (old_obj_state) = (__state)->private_objs[__i].old_state, \ + (void)(old_obj_state) /* Only to avoid unused-but-set-variable warning */, 1); \ (__i)++) /** @@ -1260,7 +1295,8 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i) < (__state)->num_private_objs && \ ((obj) = (__state)->private_objs[__i].ptr, \ (void)(obj) /* Only to avoid unused-but-set-variable warning */, \ - (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \ + (new_obj_state) = (__state)->private_objs[__i].new_state, \ + (void)(new_obj_state) /* Only to avoid unused-but-set-variable warning */, 1); \ (__i)++) /** @@ -1361,11 +1397,8 @@ struct drm_bridge_state { struct drm_bus_cfg output_bus_cfg; }; -static inline struct drm_bridge_state * -drm_priv_to_bridge_state(struct drm_private_state *priv) -{ - return container_of(priv, struct drm_bridge_state, base); -} +#define drm_priv_to_bridge_state(priv) \ + container_of_const(priv, struct drm_bridge_state, base) struct drm_bridge_state * drm_atomic_get_bridge_state(struct drm_atomic_commit *state, diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index 34a599c3d86d..4706eeab52c1 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -42,9 +42,6 @@ struct drm_device; void __drm_atomic_helper_crtc_state_init(struct drm_crtc_state *state, struct drm_crtc *crtc); -void __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc, - struct drm_crtc_state *state); -void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); struct drm_crtc_state * drm_atomic_helper_crtc_create_state(struct drm_crtc *crtc); void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, @@ -59,9 +56,6 @@ void __drm_atomic_helper_plane_state_init(struct drm_plane_state *state, struct drm_plane *plane); struct drm_plane_state * drm_atomic_helper_plane_create_state(struct drm_plane *plane); -void __drm_atomic_helper_plane_reset(struct drm_plane *plane, - struct drm_plane_state *state); -void drm_atomic_helper_plane_reset(struct drm_plane *plane); void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, struct drm_plane_state *state); struct drm_plane_state * diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 49a21f3dcb36..10a0cae3e48f 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -67,6 +67,20 @@ struct drm_client_funcs { int (*restore)(struct drm_client_dev *client, bool force); /** + * @acquire_outputs: + * + * Called by vga-switcheroo. Informs the client that the outputs will + * be switched to its device. When @acquire_outputs runs, the outputs + * have not been switched yet. The client should only prepare the software + * state. After the switch happened, the client might get a hotplug + * event to update the hardware state. + * + * This callback exists for remapping framebuffers to virtual terminals + * in fbcon. + */ + void (*acquire_outputs)(struct drm_client_dev *client); + + /** * @hotplug: * * Called on drm_kms_helper_hotplug_event(). diff --git a/include/drm/drm_client_event.h b/include/drm/drm_client_event.h index 79369c755bc9..c93f404bae1d 100644 --- a/include/drm/drm_client_event.h +++ b/include/drm/drm_client_event.h @@ -11,6 +11,7 @@ struct drm_device; void drm_client_dev_unregister(struct drm_device *dev); void drm_client_dev_hotplug(struct drm_device *dev); void drm_client_dev_restore(struct drm_device *dev, bool force); +void drm_client_dev_acquire_outputs(struct drm_device *dev); void drm_client_dev_suspend(struct drm_device *dev); void drm_client_dev_resume(struct drm_device *dev); #else @@ -20,6 +21,8 @@ static inline void drm_client_dev_hotplug(struct drm_device *dev) { } static inline void drm_client_dev_restore(struct drm_device *dev, bool force) { } +static inline void drm_client_dev_acquire_outputs(struct drm_device *dev) +{ } static inline void drm_client_dev_suspend(struct drm_device *dev) { } static inline void drm_client_dev_resume(struct drm_device *dev) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 152349f973e3..be5dca538d87 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -424,18 +424,6 @@ struct drm_crtc_state { */ struct drm_crtc_funcs { /** - * @reset: - * - * Reset CRTC hardware and software state to off. This function isn't - * called by the core directly, only through drm_mode_config_reset(). - * It's not a helper hook only for historical reasons. - * - * Atomic drivers can use drm_atomic_helper_crtc_reset() to reset - * atomic state using this hook. - */ - void (*reset)(struct drm_crtc *crtc); - - /** * @cursor_set: * * Update the cursor image. The cursor position is relative to the CRTC diff --git a/include/drm/drm_gem_atomic_helper.h b/include/drm/drm_gem_atomic_helper.h index 2deb0cd9ebbe..d41877f77b77 100644 --- a/include/drm/drm_gem_atomic_helper.h +++ b/include/drm/drm_gem_atomic_helper.h @@ -91,8 +91,6 @@ to_drm_shadow_plane_state(struct drm_plane_state *state) void __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane, struct drm_shadow_plane_state *new_shadow_plane_state); void __drm_gem_destroy_shadow_plane_state(struct drm_shadow_plane_state *shadow_plane_state); -void __drm_gem_reset_shadow_plane(struct drm_plane *plane, - struct drm_shadow_plane_state *shadow_plane_state); void __drm_gem_shadow_plane_state_init(struct drm_plane *plane, struct drm_shadow_plane_state *shadow_plane_state); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index d8f5b7e9673e..084517beb924 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -495,8 +495,8 @@ struct drm_mode_config { * * Raw spinlock used to protect critical sections of code that access * the display hardware or modeset software state, which the panic - * printing code must be protected against. See drm_panic_trylock(), - * drm_panic_lock() and drm_panic_unlock(). + * printing code must be protected against. See the documentation on + * DRM panic handling for more information. */ struct raw_spinlock panic_lock; diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index ca6268945c28..dc4c5e8733c3 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -282,6 +282,20 @@ struct drm_crtc_helper_funcs { void (*disable)(struct drm_crtc *crtc); /** + * @hw_reset: + * + * Optional hook for CRTC hardware reset. + * + * Unlike @drm_crtc_funcs.reset, which both resets hardware and + * creates new software state, this hook only resets the + * hardware to a known good state without touching the software + * state at all. + * + * This hook is called by drm_mode_config_reset(). + */ + void (*hw_reset)(struct drm_crtc *crtc); + + /** * @atomic_check: * * Drivers should check plane-update related CRTC constraints in this @@ -1442,17 +1456,20 @@ struct drm_plane_helper_funcs { /** * @get_scanout_buffer: * - * Get the current scanout buffer, to display a message with drm_panic. + * 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 + * Please look the documentation on DRM panic handling 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 panic screen won't be displayed. Drivers must not make any + * assumptions about the actual state of the hardware. + * * The returned &drm_scanout_buffer.map must be valid if no error code is * returned. * @@ -1472,7 +1489,7 @@ struct drm_plane_helper_funcs { * 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 + * Please look the documentation on DRM panic handling for an in-depth * discussions of what's safe and what is not allowed. */ void (*panic_flush)(struct drm_plane *plane); diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h index ac0e46b73436..3e628cbaffca 100644 --- a/include/drm/drm_panic.h +++ b/include/drm/drm_panic.h @@ -8,13 +8,19 @@ #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> +struct page; + +enum drm_panic_type { + DRM_PANIC_TYPE_KMSG, + DRM_PANIC_TYPE_USER, + DRM_PANIC_TYPE_QR, +}; + /** * struct drm_scanout_buffer - DRM scanout buffer * @@ -77,113 +83,6 @@ struct drm_scanout_buffer { * set_pixel() */ void *private; - }; -#ifdef CONFIG_DRM_PANIC - -/** - * drm_panic_trylock - try to enter the panic printing critical section - * @dev: struct drm_device - * @flags: unsigned long irq flags you need to pass to the unlock() counterpart - * - * This function must be called by any panic printing code. The panic printing - * attempt must be aborted if the trylock fails. - * - * Panic printing code can make the following assumptions while holding the - * panic lock: - * - * - Anything protected by drm_panic_lock() and drm_panic_unlock() pairs is safe - * to access. - * - * - Furthermore the panic printing code only registers in drm_dev_unregister() - * and gets removed in drm_dev_unregister(). This allows the panic code to - * safely access any state which is invariant in between these two function - * calls, like the list of planes &drm_mode_config.plane_list or most of the - * struct drm_plane structure. - * - * Specifically thanks to the protection around plane updates in - * drm_atomic_helper_swap_state() the following additional guarantees hold: - * - * - It is safe to deference the drm_plane.state pointer. - * - * - Anything in struct drm_plane_state or the driver's subclass thereof which - * stays invariant after the atomic check code has finished is safe to access. - * Specifically this includes the reference counted pointers to framebuffer - * and buffer objects. - * - * - Anything set up by &drm_plane_helper_funcs.fb_prepare and cleaned up - * &drm_plane_helper_funcs.fb_cleanup is safe to access, as long as it stays - * invariant between these two calls. This also means that for drivers using - * dynamic buffer management the framebuffer is pinned, and therefer all - * relevant datastructures can be accessed without taking any further locks - * (which would be impossible in panic context anyway). - * - * - Importantly, software and hardware state set up by - * &drm_plane_helper_funcs.begin_fb_access and - * &drm_plane_helper_funcs.end_fb_access is not safe to access. - * - * Drivers must not make any assumptions about the actual state of the hardware, - * unless they explicitly protected these hardware access with drm_panic_lock() - * and drm_panic_unlock(). - * - * Return: - * %0 when failing to acquire the raw spinlock, nonzero on success. - */ -#define drm_panic_trylock(dev, flags) \ - raw_spin_trylock_irqsave(&(dev)->mode_config.panic_lock, flags) - -/** - * drm_panic_lock - protect panic printing relevant state - * @dev: struct drm_device - * @flags: unsigned long irq flags you need to pass to the unlock() counterpart - * - * This function must be called to protect software and hardware state that the - * panic printing code must be able to rely on. The protected sections must be - * as small as possible. It uses the irqsave/irqrestore variant, and can be - * called from irq handler. Examples include: - * - * - Access to peek/poke or other similar registers, if that is the way the - * driver prints the pixels into the scanout buffer at panic time. - * - * - Updates to pointers like &drm_plane.state, allowing the panic handler to - * safely deference these. This is done in drm_atomic_helper_swap_state(). - * - * - An state that isn't invariant and that the driver must be able to access - * during panic printing. - */ - -#define drm_panic_lock(dev, flags) \ - raw_spin_lock_irqsave(&(dev)->mode_config.panic_lock, flags) - -/** - * drm_panic_unlock - end of the panic printing critical section - * @dev: struct drm_device - * @flags: irq flags that were returned when acquiring the lock - * - * Unlocks the raw spinlock acquired by either drm_panic_lock() or - * drm_panic_trylock(). - */ -#define drm_panic_unlock(dev, flags) \ - raw_spin_unlock_irqrestore(&(dev)->mode_config.panic_lock, flags) - -#else - -static inline bool drm_panic_trylock(struct drm_device *dev, unsigned long flags) -{ - return true; -} - -static inline void drm_panic_lock(struct drm_device *dev, unsigned long flags) {} -static inline void drm_panic_unlock(struct drm_device *dev, unsigned long flags) {} - -#endif - -#if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE) -size_t drm_panic_qr_max_data_size(u8 version, size_t url_len); - -u8 drm_panic_qr_generate(const char *url, u8 *data, size_t data_len, size_t data_size, - u8 *tmp, size_t tmp_size); -#endif - #endif /* __DRM_PANIC_H__ */ diff --git a/include/drm/drm_panic_helper.h b/include/drm/drm_panic_helper.h new file mode 100644 index 000000000000..fbfe51161aef --- /dev/null +++ b/include/drm/drm_panic_helper.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 or MIT */ + +#ifndef __DRM_DRM_PANIC_HELPER_H_ +#define __DRM_DRM_PANIC_HELPER_H_ + +#include <linux/types.h> + +enum drm_panic_type; + +struct drm_plane; +struct drm_scanout_buffer; + +/* drm_panic_helper.c */ +int drm_plane_helper_display_panic_screen(struct drm_plane *plane, + const char *description, + enum drm_panic_type panic_type, + u32 fg_color, u32 bg_color, + unsigned int qr_version); +#if IS_ENABLED(CONFIG_KUNIT) +int drm_panic_helper_draw_screen_user(struct drm_scanout_buffer *sb, u32 fg_color, u32 bg_color); +int drm_panic_helper_draw_screen_kmsg(struct drm_scanout_buffer *sb, u32 fg_color, u32 bg_color); +int drm_panic_helper_draw_screen_qr_code(struct drm_scanout_buffer *sb, + u32 fg_color, u32 bg_color, unsigned int qr_version); +void drm_panic_helper_set_description(const char *description); +void drm_panic_helper_clear_description(void); +#endif + +/* drm_panic_helper_qr.rs */ +size_t drm_panic_helper_qr_max_data_size(u8 version, size_t url_len); +u8 drm_panic_helper_qr_generate(const char *url, u8 *data, size_t data_len, size_t data_size, + u8 *tmp, size_t tmp_size); + +#if IS_ENABLED(CONFIG_DRM_PANIC) +#define DRM_PANIC_PLANE_FUNCS \ + .display_panic_screen = drm_plane_helper_display_panic_screen +#else +#define DRM_PANIC_PLANE_FUNCS \ + .display_panic_screen = NULL +#endif + +#endif diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 2c5a5a70a71b..410d7b02b77a 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -32,6 +32,8 @@ #include <drm/drm_modeset_lock.h> #include <drm/drm_util.h> +enum drm_panic_type; + struct drm_crtc; struct drm_plane_size_hint; struct drm_printer; @@ -360,18 +362,6 @@ struct drm_plane_funcs { void (*destroy)(struct drm_plane *plane); /** - * @reset: - * - * Reset plane hardware and software state to off. This function isn't - * called by the core directly, only through drm_mode_config_reset(). - * It's not a helper hook only for historical reasons. - * - * Atomic drivers can use drm_atomic_helper_plane_reset() to reset - * atomic state using this hook. - */ - void (*reset)(struct drm_plane *plane); - - /** * @set_property: * * This is the legacy entry point to update a property attached to the @@ -590,6 +580,61 @@ struct drm_plane_funcs { bool (*format_mod_supported_async)(struct drm_plane *plane, u32 format, u64 modifier); + /** + * @display_panic_screen: + * + * DRM panic handling invokes this callback on panics. + * + * It is a panic handler, so it can't take locks, 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). + * + * Panic-printing code must acquire the panic lock before interacting with the + * scanout buffer. Such helpers can make the following assumptions while holding + * the panic lock: + * + * - Anything protected by drm_panic_lock() and drm_panic_unlock() pairs is safe + * to access. + * + * - Furthermore the panic printing code only registers in drm_dev_unregister() + * and gets removed in drm_dev_unregister(). This allows the panic code to + * safely access any state which is invariant in between these two function + * calls, like the list of planes &drm_mode_config.plane_list or most of the + * struct drm_plane structure. + * + * Specifically thanks to the protection around plane updates in + * drm_atomic_helper_swap_state() the following additional guarantees hold: + * + * - It is safe to deference the drm_plane.state pointer. + * + * - Anything in struct drm_plane_state or the driver's subclass thereof which + * stays invariant after the atomic check code has finished is safe to access. + * Specifically this includes the reference counted pointers to framebuffer + * and buffer objects. + * + * - Anything set up by &drm_plane_helper_funcs.fb_prepare and cleaned up + * &drm_plane_helper_funcs.fb_cleanup is safe to access, as long as it stays + * invariant between these two calls. This also means that for drivers using + * dynamic buffer management the framebuffer is pinned, and therefer all + * relevant datastructures can be accessed without taking any further locks + * (which would be impossible in panic context anyway). + * + * - Importantly, software and hardware state set up by + * &drm_plane_helper_funcs.begin_fb_access and + * &drm_plane_helper_funcs.end_fb_access is not safe to access. + * + * It will display only one static frame, so performance optimizations are + * low priority as the machine is already in an unusable state. + * + * This callback is optional. Planes without will not be considered + * for panic output. + */ + int (*display_panic_screen)(struct drm_plane *plane, + const char *description, + enum drm_panic_type panic_type, + u32 fg_color, u32 bg_color, + unsigned int qr_version); }; /** diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h index 4a4a840d84f1..2b31c25c57a9 100644 --- a/include/drm/drm_simple_kms_helper.h +++ b/include/drm/drm_simple_kms_helper.h @@ -42,7 +42,6 @@ struct drm_simple_display_pipe_funcs { struct drm_crtc_state * (*duplicate_crtc_state)(struct drm_simple_display_pipe *pipe); void (*destroy_crtc_state)(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state); - void (*reset_plane)(struct drm_simple_display_pipe *pipe); struct drm_plane_state * (*create_plane_state)(struct drm_simple_display_pipe *pipe); struct drm_plane_state * (*duplicate_plane_state)(struct drm_simple_display_pipe *pipe); void (*destroy_plane_state)(struct drm_simple_display_pipe *pipe, diff --git a/include/drm/drm_sysfs.h b/include/drm/drm_sysfs.h index 96a5d858404b..7695873a9456 100644 --- a/include/drm/drm_sysfs.h +++ b/include/drm/drm_sysfs.h @@ -3,13 +3,9 @@ #define _DRM_SYSFS_H_ struct drm_device; -struct device; struct drm_connector; struct drm_property; -int drm_class_device_register(struct device *dev); -void drm_class_device_unregister(struct device *dev); - void drm_sysfs_hotplug_event(struct drm_device *dev); void drm_sysfs_connector_hotplug_event(struct drm_connector *connector); void drm_sysfs_connector_property_event(struct drm_connector *connector, diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index 158cd609f103..3aa85be43aad 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -501,7 +501,7 @@ dma_fence_test_signaled_flag(struct dma_fence *fence) * Returns true if the fence was already signaled, false if not. Since this * function doesn't enable signaling, it is not guaranteed to ever return * true if dma_fence_add_callback(), dma_fence_wait() or - * dma_fence_enable_sw_signaling() haven't been called before. + * dma_fence_enable_signaling() haven't been called before. * * This function requires &dma_fence.lock to be held. * diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 7e6ac0114d55..d7eee65664ab 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -31,8 +31,12 @@ #ifndef _LINUX_VGA_SWITCHEROO_H_ #define _LINUX_VGA_SWITCHEROO_H_ -#include <linux/fb.h> +#include <linux/errno.h> +#include <linux/types.h> +struct device; +struct dev_pm_domain; +struct fb_info; struct pci_dev; /** @@ -127,23 +131,28 @@ struct vga_switcheroo_handler { * @set_gpu_state: do the equivalent of suspend/resume for the card. * Mandatory. This should not cut power to the discrete GPU, * which is the job of the handler - * @reprobe: poll outputs. - * Optional. This gets called after waking the GPU and switching - * the outputs to it * @can_switch: check if the device is in a position to switch now. * Mandatory. The client should return false if a user space process * has one of its device files open + * @pre_switch: prepare switch + * Optional. This gets called before switching the outputs to the + * GPU. Allows drivers to prepare for the switch. + * @post_switch: completes switch + * Optional. This gets called after waking the GPU and switching + * the outputs to it. Allows drivers to poll the switched outputs. * @gpu_bound: notify the client id to audio client when the GPU is bound. * * Client callbacks. A client can be either a GPU or an audio device on a GPU. - * The @set_gpu_state and @can_switch methods are mandatory, @reprobe may be - * set to NULL. For audio clients, the @reprobe member is bogus. - * OTOH, @gpu_bound is only for audio clients, and not used for GPU clients. + * The @set_gpu_state and @can_switch methods are mandatory, @pre_switch and + * @post_switch may be set to NULL. For audio clients, the @pre_switch and + * @post_switch members are bogus. OTOH, @gpu_bound is only for audio clients, + * and not used for GPU clients. */ struct vga_switcheroo_client_ops { void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state); - void (*reprobe)(struct pci_dev *dev); bool (*can_switch)(struct pci_dev *dev); + void (*pre_switch)(struct pci_dev *dev); + void (*post_switch)(struct pci_dev *dev); void (*gpu_bound)(struct pci_dev *dev, enum vga_switcheroo_client_id); }; @@ -156,9 +165,6 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, struct pci_dev *vga_dev); -void vga_switcheroo_client_fb_set(struct pci_dev *dev, - struct fb_info *info); - int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, enum vga_switcheroo_handler_flags_t handler_flags); void vga_switcheroo_unregister_handler(void); @@ -178,7 +184,6 @@ void vga_switcheroo_fini_domain_pm_ops(struct device *dev); static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {} static inline int vga_switcheroo_register_client(struct pci_dev *dev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; } -static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {} static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, enum vga_switcheroo_handler_flags_t handler_flags) { return 0; } static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, diff --git a/include/uapi/drm/ivpu_accel.h b/include/uapi/drm/ivpu_accel.h index 264505d54f93..9ce19d9c3131 100644 --- a/include/uapi/drm/ivpu_accel.h +++ b/include/uapi/drm/ivpu_accel.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (C) 2020-2025 Intel Corporation + * Copyright (C) 2020-2026 Intel Corporation */ #ifndef __UAPI_IVPU_DRM_H__ @@ -96,6 +96,7 @@ extern "C" { #define DRM_IVPU_PARAM_SKU 12 #define DRM_IVPU_PARAM_CAPABILITIES 13 #define DRM_IVPU_PARAM_PREEMPT_BUFFER_SIZE 14 +#define DRM_IVPU_PARAM_CMDQ_PRIORITY 15 #define DRM_IVPU_PLATFORM_TYPE_SILICON 0 @@ -141,6 +142,15 @@ extern "C" { #define DRM_IVPU_CAP_BO_CREATE_FROM_USERPTR 4 /** + * DRM_IVPU_CAP_CMDQ_SET_PRIORITY + * + * Driver supports DRM_IVPU_PARAM_CMDQ_PRIORITY parameter to get/set command + * queue priority. + * This allows changing command queue priority after creation. + */ +#define DRM_IVPU_CAP_CMDQ_SET_PRIORITY 5 + +/** * struct drm_ivpu_param - Get/Set VPU parameters */ struct drm_ivpu_param { @@ -192,6 +202,11 @@ struct drm_ivpu_param { * * %DRM_IVPU_PARAM_PREEMPT_BUFFER_SIZE: * Size of the preemption buffer (read-only) + * + * %DRM_IVPU_PARAM_CMDQ_PRIORITY: + * Get/Set command queue priority (see DRM_IVPU_JOB_PRIORITY_*). + * DRM_IVPU_JOB_PRIORITY_DEFAULT is treated as DRM_IVPU_JOB_PRIORITY_NORMAL. + * Command queue ID is given via drm_ivpu_param.index. */ __u32 param; |
