From 86d8b6147d945599b6d5b51d1dfd58d5e3885c0b Mon Sep 17 00:00:00 2001 From: Andrzej Kacprowski Date: Mon, 31 Aug 2026 14:16:17 +0200 Subject: accel/ivpu: Add support for getting and setting command queue priority Add a new DRM_IVPU_PARAM_CMDQ_PRIORITY parameter to query and update the scheduling priority of an existing command queue, identified by its ID via drm_ivpu_param.index. The priority can be changed on a queue that already has pending jobs; if the queue's doorbell is registered, the new priority is propagated to the firmware immediately, otherwise it is applied when the queue is next registered. The firmware picks up the change at the first opportunity. The feature requires HW scheduling mode and is advertised through the new DRM_IVPU_CAP_CMDQ_SET_PRIORITY capability. Legacy command queues are not supported. Signed-off-by: Andrzej Kacprowski Reviewed-by: Karol Wachowski Signed-off-by: Karol Wachowski Link: https://patch.msgid.link/20260831121617.395523-1-andrzej.kacprowski@linux.intel.com --- include/uapi/drm/ivpu_accel.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'include') 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 @@ -140,6 +141,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 */ @@ -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; -- cgit v1.2.3 From 7e5d178cbc47b1df2f0b5c1865973534fbc4460b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 4 Sep 2026 11:07:19 +0200 Subject: drm/crtc: Introduce hw_reset helper hook The CRTC reset hook conflates initial software state allocation with hardware reset. The atomic_create_state hook addresses the software state side, but drivers may still need to reset hardware to a known good state during drm_mode_config_reset(), for example during suspend/resume. Separating hardware reset from state allocation is also useful for the pending atomic state readout and userspace atomic reset flag series, which need to create pristine software state without affecting the hardware. Introduce a hw_reset hook in struct drm_crtc_helper_funcs that only resets the hardware, without touching the software state at all. Call it from drm_mode_config_crtc_reset_with_create_state() after the state has been successfully created. Reviewed-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20260904-drm-no-more-crtc-reset-v3-1-27d9891512ce@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_modeset_helper_vtables.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include') diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index ca6268945c28..4965356a6314 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -281,6 +281,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: * -- cgit v1.2.3 From 38d8b5a35367246dee147d48ea6d5cd6644de5d5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Sep 2026 16:35:02 +0200 Subject: drm/atomic: colorop: Rename state to state_to_destroy The atomic state tracking structures used to have a generic state field to track the state to free when tearing down the drm_atomic_commit. It has since been renamed to state_to_destroy in __drm_planes_state, __drm_crtcs_state, __drm_connnectors_state, and __drm_private_objs_state to better describe its purpose. The colorop support has been added after that rename, but __drm_colorops_state still uses the old state name. Rename it to state_to_destroy for consistency, and add the matching kerneldoc. Reviewed-by: Thomas Zimmermann Link: https://patch.msgid.link/20260908-drm-reset-state-flag-v3-1-905570f387a4@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_atomic.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 88087910ab1a..00b3e9fc429a 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 { -- cgit v1.2.3 From 4e089d048a4f169718934601b126c447ce6ef9c1 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 9 Jul 2026 11:15:58 +0200 Subject: drm/client: Add acquire_outputs callback; implement for fbdev emulation Add the callback acquire_outputs to drm_client_funcs to inform an internal DRM client that vga-switcheroo is about to switch the physical outputs to the client's device. Allows the client to prepare its internal state for the upcoming switch. Wire up the DRM client helpers to invoke the helper for a device's clients. Implement acquire_outputs for fbdev emulation. Invoke fb_switch_outputs(), which remaps framebuffers to virtual terminals in fbcon. Currently this is still being done by vga-switcheroo. With more DRM clients becoming available, vga-switcheroo needs to become client agonostic. Signed-off-by: Thomas Zimmermann Acked-by: Maxime Ripard Acked-by: Helge Deller Link: https://patch.msgid.link/20260709092215.168172-3-tzimmermann@suse.de --- include/drm/drm_client.h | 14 ++++++++++++++ include/drm/drm_client_event.h | 3 +++ 2 files changed, 17 insertions(+) (limited to 'include') 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 @@ -66,6 +66,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: * 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) -- cgit v1.2.3 From bd33ce60cf1c5d3c055a00b92e8141a22f5ec2d7 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 9 Jul 2026 11:15:59 +0200 Subject: vga_switcheroo: Add pre_switch callback to client ops Add pre_switch to struct vga_switcheroo_client_ops to inform the switcheroo client about upcoming switches of the outputs. This callback is intended to replace the hard-coded call to fbdev's fb_switch_outputs(). With DRM supporting more clients than just fbdev emulation, something more flexible is required. v2: - remove non-sensical gpu_bound documentation (Sashiko) Signed-off-by: Thomas Zimmermann Acked-by: Maxime Ripard Acked-by: Helge Deller Link: https://patch.msgid.link/20260709092215.168172-4-tzimmermann@suse.de --- include/linux/vga_switcheroo.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 7e6ac0114d55..4422daca9ceb 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -133,17 +133,22 @@ struct vga_switcheroo_handler { * @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. * @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 + * @reprobe may be set to NULL. For audio clients, the @pre_switch and + * @reprobe 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 (*gpu_bound)(struct pci_dev *dev, enum vga_switcheroo_client_id); }; -- cgit v1.2.3 From 649e96efe2caadb438c980459011a7f77e4d4959 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 9 Jul 2026 11:16:00 +0200 Subject: vga_switcheroo: Add post_switch callback to client ops Add post_switch to struct vga_switcheroo_client_ops to inform the switcheroo client about a completed switch of the output. This callback is intended to replace the reprobe client op. It is a rename of reprobe for consistency with pre_switch. Signed-off-by: Thomas Zimmermann Acked-by: Maxime Ripard Acked-by: Helge Deller Link: https://patch.msgid.link/20260709092215.168172-5-tzimmermann@suse.de --- include/linux/vga_switcheroo.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 4422daca9ceb..51851831d4c1 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -127,21 +127,22 @@ 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 + * @reprobe: deprecated * @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, @pre_switch and - * @reprobe may be set to NULL. For audio clients, the @pre_switch and - * @reprobe members are bogus. OTOH, @gpu_bound is only for audio clients, + * @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 { @@ -149,6 +150,7 @@ struct vga_switcheroo_client_ops { 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); }; -- cgit v1.2.3 From 2350f42c2f46b60bec79f2249f8bc5f3ff2807d4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 9 Jul 2026 11:16:03 +0200 Subject: vga-switcheroo: Remove unused interfaces Remove all unused interfaces that used to implement the functionality of pre_switch and post_switch. For pre_switch, remove vga_switcheroo_client_fb_set(). This further allows for removing all symbols and data structures that refer to fbdev; such as fb_info and fb_switch_outputs(). For post_switch, remove the reprobe callback from the client ops. v2: - move changes to fbcon and drivers into other patches Signed-off-by: Thomas Zimmermann Acked-by: Maxime Ripard Acked-by: Helge Deller Link: https://patch.msgid.link/20260709092215.168172-8-tzimmermann@suse.de --- include/linux/vga_switcheroo.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 51851831d4c1..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 +#include +#include +struct device; +struct dev_pm_domain; +struct fb_info; struct pci_dev; /** @@ -127,7 +131,6 @@ 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: deprecated * @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 @@ -147,7 +150,6 @@ struct vga_switcheroo_handler { */ 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); @@ -163,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); @@ -185,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, -- cgit v1.2.3 From 65221358b6a6ea5128accbaa6117565ab8e24aa1 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 12 Sep 2026 00:11:00 +0200 Subject: dma-fence: Fix dma_fence_enable_signaling() reference in kernel-doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel-doc comment of dma_fence_is_signaled_locked() refers to dma_fence_enable_sw_signaling, which was renamed to dma_fence_enable_signaling by commit 9370a5c664e8 ("dma-buf: rename dma_fence_enable_sw_signaling"). Say dma_fence_enable_signaling. Fixes: 9370a5c664e8 ("dma-buf: rename dma_fence_enable_sw_signaling") Assisted-by: LLM Signed-off-by: Karl Mehltretter Reviewed-by: Christian König Signed-off-by: Christian König Link: https://lore.kernel.org/r/20260911221100.7079-1-kmehltretter@gmail.com --- include/linux/dma-fence.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') 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. * -- cgit v1.2.3 From eff5a355919641c29ffae99a15cbe59b74551e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Mon, 3 Aug 2026 10:26:52 -0300 Subject: drm/sysfs: Remove drm_class_device_(un)register() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last usage of the functions drm_class_device_register() and drm_class_device_unregister() was removed in commit ed89fff97382 ("drm/ttm: drop sysfs directory"). Remove such functions as they are no longer used. Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260803132706.1497980-2-mcanal@igalia.com Signed-off-by: Maíra Canal --- include/drm/drm_sysfs.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include') 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, -- cgit v1.2.3 From 80161e76e339615edbaf900a3592e6672f8ae685 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 7 Sep 2026 15:23:37 +0200 Subject: drm/atomic: Fix unused but set warning in state iterator macros A number of state iterator macros trigger a compiler warning if an iterator parameter isn't used in the code block. Add a similar workaround than in most other macros. Acked-by: Simona Vetter Link: https://lore.kernel.org/r/20260907-drm-state-readout-v5-1-5fa1ac7a5148@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_atomic.h | 64 +++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 00b3e9fc429a..ccdac6bf0d2d 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -967,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 @@ -989,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 @@ -1010,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 @@ -1033,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 @@ -1056,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 @@ -1142,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 @@ -1164,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, @@ -1181,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 @@ -1200,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 @@ -1238,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)++) /** @@ -1257,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)++) /** @@ -1276,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)++) /** -- cgit v1.2.3 From 7a4e435602c949c4a64e8cadfe816450953c2f6d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 7 Sep 2026 15:23:39 +0200 Subject: drm/atomic: Convert drm_priv_to_bridge_state to container_of_const container_of_const is more flexible than container_of when it comes to mixing pointers constness. Switch to it. Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20260907-drm-state-readout-v5-3-5fa1ac7a5148@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_atomic.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index ccdac6bf0d2d..3ae35b09c0cf 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -1397,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, -- cgit v1.2.3 From 8c733e74ad1672a94a52bed7da19f6c222669adc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Sep 2026 16:46:32 +0200 Subject: drm/simple-kms: Remove unused reset_plane hook Commit 7f879284390c ("drm/simple-kms: Switch to atomic_create_state") replaced drm_simple_kms_plane_reset() with drm_simple_kms_plane_create_state(), removing the only user of the reset_plane hook. However, the hook itself was left behind in struct drm_simple_display_pipe_funcs. Remove it. Fixes: 7f879284390c ("drm/simple-kms: Switch to atomic_create_state") Reviewed-by: Thomas Zimmermann Link: https://patch.msgid.link/20260908-drm-no-more-plane-reset-v4-1-a31b3fcfc989@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_simple_kms_helper.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') 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, -- cgit v1.2.3 From d3e410b0e2b2fb3f440edbb3f45b3efe06128bb5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Sep 2026 16:46:35 +0200 Subject: drm/gem-atomic-helper: Remove __drm_gem_reset_shadow_plane() __drm_gem_reset_shadow_plane() is no longer used: all callers now go through __drm_gem_shadow_plane_state_init() or drm_gem_create_shadow_plane_state(). Remove it. Reviewed-by: Thomas Zimmermann Link: https://patch.msgid.link/20260908-drm-no-more-plane-reset-v4-4-a31b3fcfc989@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_gem_atomic_helper.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') 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); -- cgit v1.2.3 From 5354d1e5fba4753efc4e5e27e671de5febc21ec0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 15 Sep 2026 16:24:50 +0200 Subject: drm/atomic-helper: Remove drm_atomic_helper_crtc_reset All users of drm_atomic_helper_crtc_reset() have been converted to drm_atomic_helper_crtc_create_state(). Remove the now unused helper. Reviewed-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Link: https://patch.msgid.link/20260915-drm-no-more-crtc-reset-v5-9-bda007735748@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_atomic_state_helper.h | 1 - include/drm/drm_crtc.h | 3 --- 2 files changed, 4 deletions(-) (limited to 'include') diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index 34a599c3d86d..df70817c94fc 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -44,7 +44,6 @@ 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, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 152349f973e3..746d049f1b6e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -429,9 +429,6 @@ struct drm_crtc_funcs { * 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); -- cgit v1.2.3 From 9ea7393511e139c24d6b5d7edcbb39b5a4c10a61 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 15 Sep 2026 16:24:51 +0200 Subject: drm/atomic-helper: Remove __drm_atomic_helper_crtc_reset All users of __drm_atomic_helper_crtc_reset() have been converted to use __drm_atomic_helper_crtc_state_init() and atomic_create_state. Remove the now unused helper. Reviewed-by: Dmitry Baryshkov Reviewed-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Link: https://patch.msgid.link/20260915-drm-no-more-crtc-reset-v5-10-bda007735748@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_atomic_state_helper.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index df70817c94fc..480eaae42f45 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -42,8 +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); 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, -- cgit v1.2.3 From f1bcb90506a9a6be4d44dc85034f8acc48a49c29 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 15 Sep 2026 16:24:52 +0200 Subject: drm/crtc: Remove reset All crtc drivers now implement the atomic_create_state hook instead of the reset hook for initial state creation. The reset hook conflated initial state allocation at probe time with hardware and software reset during suspend/resume, making error handling difficult since it is not fallible. Remove the reset hook from struct drm_crtc_funcs and the associated call in drm_mode_config_reset(). Reviewed-by: Dmitry Baryshkov Reviewed-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Link: https://patch.msgid.link/20260915-drm-no-more-crtc-reset-v5-11-bda007735748@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_crtc.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 746d049f1b6e..be5dca538d87 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -423,15 +423,6 @@ struct drm_crtc_state { * bus accessors. */ 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. - */ - void (*reset)(struct drm_crtc *crtc); - /** * @cursor_set: * -- cgit v1.2.3 From e62864df82f6a47c969485636b2894472f321acd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 16 Sep 2026 10:55:50 +0200 Subject: drm/atomic-state-helper: Remove drm_atomic_helper_plane_reset() drm_atomic_helper_plane_reset() is no longer used: all callers now go through drm_atomic_helper_plane_create_state(). Remove it. Reviewed-by: Thomas Zimmermann Link: https://patch.msgid.link/20260916-drm-no-more-plane-reset-v5-7-f590d2003f2c@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_atomic_state_helper.h | 1 - include/drm/drm_plane.h | 3 --- 2 files changed, 4 deletions(-) (limited to 'include') diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index 480eaae42f45..49acd05552a5 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -58,7 +58,6 @@ 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_plane.h b/include/drm/drm_plane.h index 2c5a5a70a71b..e757e9dbf132 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -365,9 +365,6 @@ struct drm_plane_funcs { * 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); -- cgit v1.2.3 From 18216d5fa8dc29c76c4d3944282d990ebc41514c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 16 Sep 2026 10:55:51 +0200 Subject: drm/atomic-state-helper: Remove __drm_atomic_helper_plane_reset() __drm_atomic_helper_plane_reset() is no longer used: all callers now go through __drm_atomic_helper_plane_state_init(). Remove it. Reviewed-by: Thomas Zimmermann Link: https://patch.msgid.link/20260916-drm-no-more-plane-reset-v5-8-f590d2003f2c@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_atomic_state_helper.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index 49acd05552a5..4706eeab52c1 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -56,8 +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_duplicate_state(struct drm_plane *plane, struct drm_plane_state *state); struct drm_plane_state * -- cgit v1.2.3 From 5589ef09f93b85b6f506e279a502d4cf1654f232 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 16 Sep 2026 10:55:52 +0200 Subject: drm/plane: Remove reset All plane drivers now implement the atomic_create_state hook instead of the reset hook for initial state creation. The reset hook conflated initial state allocation at probe time with hardware and software reset during suspend/resume, making error handling difficult since it is not fallible. Remove the reset hook from struct drm_plane_funcs and the associated call in drm_mode_config_reset(). Reviewed-by: Thomas Zimmermann Link: https://patch.msgid.link/20260916-drm-no-more-plane-reset-v5-9-f590d2003f2c@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_plane.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include') diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index e757e9dbf132..a16e96aa7e60 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -359,15 +359,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. - */ - void (*reset)(struct drm_plane *plane); - /** * @set_property: * -- cgit v1.2.3 From b8bc58515ac49e92dd5fdd853c11c4bf6ee33a19 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 11 Sep 2026 14:44:04 +0200 Subject: drm/panic: Display panic screen via per-plane callback Add display_panic_screen to struct drm_plane_funcs. If set on a plane, register a panic handler for the plane from the DRM core's panic handling. Invoke this helper from the core to display a panic screen. The new callback replaces get_scanout_buffer as signal for panic support in a plane. Using get_scanout_buffer is now merely a detail of the implementation. This will also free struct drm_scanout_buffer for use cases besides panic handling. With display_panic_screen in place, rename draw_panic_plane() to drm_plane_helper_display_panic_screen() and make it available to DRM drivers via drm_panic_helper.h. Do not change the implementation or functionality of this code. drm_plane_helper_display_panic_screen() still supports kernel messages, user messages and QR codes on various color formats. Then update all drivers that implement panic support. Provide the initializer macro DRM_PANIC_PLANE_FUNCS that sets display_panic_screen to drm_plane_helper_display_panic_screen(). If panic handling has been disabled, it instead clears the callback. There's again no change in functionality. This logically splits panic handling into a set of entry points in the DRM code and a set of helper functions provided by drivers. The core invokes the driver's helper via callback, while the driver can tailor the implementation to its needs. Panic handling now works like most other interfaces in the DRM framework. Locking and state-handling happens in the DRM core or helpers. Drivers that receive a call to display_panic_screen can assume that no concurrent modeset takes place on the plane or its CRTC. Also update the documentation. Move information about locking and state guarantees from drm_panic_trylock() to display_panic_screen, where drivers authors can find it easily. Move information about the features of the current implementation to drm_panic_helper_display_panic_screen(). v4: - remove obsolete comment about fbcon interference (Jocelyn) v2: - only consider planes with get_scanout_buffer (Sashiko) - set callback for planes create with drm_crtc_init() (Sashiko) - return errno code from display_panic_screen Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patch.msgid.link/20260911124540.279841-12-tzimmermann@suse.de --- include/drm/drm_mode_config.h | 4 +-- include/drm/drm_modeset_helper_vtables.h | 11 +++--- include/drm/drm_panic.h | 49 ++++++--------------------- include/drm/drm_panic_helper.h | 27 +++++++++++++++ include/drm/drm_plane.h | 57 ++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 45 deletions(-) create mode 100644 include/drm/drm_panic_helper.h (limited to 'include') 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 4965356a6314..dc4c5e8733c3 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -1456,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. * @@ -1486,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..430df536de14 100644 --- a/include/drm/drm_panic.h +++ b/include/drm/drm_panic.h @@ -15,6 +15,14 @@ #include #include +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 * @@ -87,45 +95,8 @@ struct drm_scanout_buffer { * @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(). + * The panic-printing code calls this function. The panic printing attempt must + * be aborted if the trylock fails. * * Return: * %0 when failing to acquire the raw spinlock, nonzero on success. diff --git a/include/drm/drm_panic_helper.h b/include/drm/drm_panic_helper.h new file mode 100644 index 000000000000..0b6ad8f61821 --- /dev/null +++ b/include/drm/drm_panic_helper.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 or MIT */ + +#ifndef __DRM_DRM_PANIC_HELPER_H_ +#define __DRM_DRM_PANIC_HELPER_H_ + +#include + +enum drm_panic_type; + +struct drm_plane; + +/* 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_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 a16e96aa7e60..410d7b02b77a 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -32,6 +32,8 @@ #include #include +enum drm_panic_type; + struct drm_crtc; struct drm_plane_size_hint; struct drm_printer; @@ -578,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); }; /** -- cgit v1.2.3 From 3ae80dc240c9ea64c6129bd40db711e80b7f2c43 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 11 Sep 2026 14:44:05 +0200 Subject: drm/panic: Internalize panic locking in DRM core and helpers None of the DRM drivers handles panic locking. Declare the interfaces in an internal header file. Move the trylock required during the panic into the DRM core's sources. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patch.msgid.link/20260911124540.279841-13-tzimmermann@suse.de --- include/drm/drm_panic.h | 65 ------------------------------------------------- 1 file changed, 65 deletions(-) (limited to 'include') diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h index 430df536de14..99572b7eeab9 100644 --- a/include/drm/drm_panic.h +++ b/include/drm/drm_panic.h @@ -8,11 +8,9 @@ #ifndef __DRM_PANIC_H__ #define __DRM_PANIC_H__ -#include #include #include -#include #include struct page; @@ -85,71 +83,8 @@ 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 - * - * The panic-printing code calls this function. The panic printing attempt must - * be aborted if the trylock fails. - * - * 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); -- cgit v1.2.3 From 5c3d323984fd140108d527a920de8553ff6504b1 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 11 Sep 2026 14:44:06 +0200 Subject: drm/panic: Move panic display code into helper library Move drm_plane_helper_display_panic_screen() and the existing panic- display code into drm_panic_helper.c. Rename symbols accordingly. Also update the QR-related code and the bindings accordingly. Link the rsp. object file into drm_kms_helper.ko. Eventually the code will become a DRM drawing library, together with DRM's format and draw helpers. This requires more preparation. until then, KMS helpers serve as a module. All DRM drivers link it anyway. Add a new section about drawing helpers to the documentation of the KMS helpers. List format and panic helpers there. v2: - fix dependencies on other DRM modules (Randy, Sashiko) - provide placeholders for drm_panic_helper_{init,exit}() (Sashiko) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patch.msgid.link/20260911124540.279841-14-tzimmermann@suse.de --- include/drm/drm_panic.h | 7 ------- include/drm/drm_panic_helper.h | 5 +++++ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h index 99572b7eeab9..3e628cbaffca 100644 --- a/include/drm/drm_panic.h +++ b/include/drm/drm_panic.h @@ -85,11 +85,4 @@ struct drm_scanout_buffer { void *private; }; -#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 index 0b6ad8f61821..6cc9a0eba077 100644 --- a/include/drm/drm_panic_helper.h +++ b/include/drm/drm_panic_helper.h @@ -16,6 +16,11 @@ int drm_plane_helper_display_panic_screen(struct drm_plane *plane, u32 fg_color, u32 bg_color, unsigned int qr_version); +/* 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 -- cgit v1.2.3 From efb67f52fb36186935a56bc2ceda6567dfd97c47 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 11 Sep 2026 14:44:07 +0200 Subject: drm/panic: Compile KUnit tests as module Fix dependency of the panic-helper KUnit tests on CONFIG_DRM_KUNIT_TEST=y and make them build as a module. Export the necessary interfaces from the panic helpers iff the KUnit framework has been enabled. Select DRM_PANIC_HELPER from DRM_KUNIT_TEST to meet the dependencies of the panic-helper tests. It is now possible to run the tests by modprobe-ing drm_panic_helper_test at runtime. v5: - clear test description with drm_panic_helper_clear_description() (Sashiko) v3: - clean up after each test case (Sashiko) v2: - fix parameter order in decl of drm_panic_helper_draw_screen_qr() (Sashiko) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patch.msgid.link/20260911124540.279841-15-tzimmermann@suse.de --- include/drm/drm_panic_helper.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/drm/drm_panic_helper.h b/include/drm/drm_panic_helper.h index 6cc9a0eba077..fbfe51161aef 100644 --- a/include/drm/drm_panic_helper.h +++ b/include/drm/drm_panic_helper.h @@ -8,6 +8,7 @@ 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, @@ -15,6 +16,14 @@ int drm_plane_helper_display_panic_screen(struct drm_plane *plane, 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); -- cgit v1.2.3