* Re: [PATCH v2 1/1] mshv: Add conditional VMBus dependency
From: Hardik Garg @ 2026-05-27 19:57 UTC (permalink / raw)
To: mhklinux, kys, haiyangz, wei.liu, decui, longli, jloeser,
linux-hyperv
Cc: linux-kernel, arnd, hamzamahfooz
In-Reply-To: <20260526141304.3924-1-mhklkml@zohomail.com>
On 5/26/2026 7:13 AM, Michael Kelley wrote:
> From: Michael Kelley <mhklinux@outlook.com>
>
> When the VMBus driver is not part of the kernel (CONFIG_HYPERV_VMBUS=n),
> the MSHV root driver fails to link:
>
> ERROR: modpost: "hv_vmbus_exists" [drivers/hv/mshv_root.ko] undefined!
>
> Fix this while meeting these requirements:
> * It must be possible to include the MSHV root driver without the
> VMBus driver. In such case, the MSHV root driver can be built-in
> to the kernel image, or it can be built as a separate module.
> * If both the MSHV root driver and the VMBus driver are present, the
> MSHV root driver and VMBus driver can both be built-in, or they can
> both be separate modules. Or the MSHV root driver can be a module
> while the VMBus driver can be built-in, but the reverse is
> disallowed. Regardless of the build choices, the VMBus driver must
> be loaded before the MSHV driver in order for the SynIC to be
> managed properly (see comments in the MSHV SynIC code).
>
> The fix has two parts:
> * Add a Kconfig entry for MSHV_ROOT to depend on HYPERV_VMBUS if
> HYPERV_VMBUS is present. The entry disallows MSHV_ROOT being
> built-in when HYPERV_VMBUS is a module, but without requiring that
> HYPERV_VMBUS be built.
> * Add a stub implementation of hv_vmbus_exists() for when the
> VMBus driver is not present so that the MSHV root driver has
> no module dependency on VMBus. When the VMBus driver *is*
> present, the module dependency ensures that the VMBus driver
> loads first when both are built as modules.
>
> Existing code ensures that the VMBus driver loads first if it is
> built-in. The VMBus driver uses subsys_initcall(), which is
> initcall level 4. The MSHV root driver uses module_init(), which
> becomes device_init() when built-in, and device_init() is
> initcall level 6.
>
> Reported-by: Arnd Bergmann <arnd@arndb.de>
> Closes: https://lore.kernel.org/all/20260520074044.923728-1-arnd@kernel.org/
> Signed-off-by: Michael Kelley <mhklinux@outlook.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Jork Loeser <jloeser@linux.microsoft.com>
> ---
> Changes in v2:
> * Instead of putting IS_ENABLED(CONFIG_HYPERV_VMBUS) around each of
> the two calls to hv_vmbus_exists() in mshv_synic.c, provide a stub
> for hv_vmbus_exists() when CONFIG_HYPERV_VMBUS is not set. The
> effect is the same as in v1, but the code is cleaner. [Jork Loeser]
>
> Arnd: I've kept your Ack even though I changed how hv_vmbus_exists()
> is stubbed out since the effect is the same. Let me know if
> you have any concerns.
>
> drivers/hv/Kconfig | 1 +
> include/linux/hyperv.h | 4 ++++
> 2 files changed, 5 insertions(+)
>
> diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
> index 2d0b3fcb0ff8..aa11bcefddf2 100644
> --- a/drivers/hv/Kconfig
> +++ b/drivers/hv/Kconfig
> @@ -74,6 +74,7 @@ config MSHV_ROOT
> # e.g. When withdrawing memory, the hypervisor gives back 4k pages in
> # no particular order, making it impossible to reassemble larger pages
> depends on PAGE_SIZE_4KB
> + depends on HYPERV_VMBUS if HYPERV_VMBUS
> select EVENTFD
> select VIRT_XFER_TO_GUEST_WORK
> select HMM_MIRROR
> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
> index 41a3d82f0722..734b7ef98f4d 100644
> --- a/include/linux/hyperv.h
> +++ b/include/linux/hyperv.h
> @@ -1304,7 +1304,11 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
>
> struct device *hv_get_vmbus_root_device(void);
>
> +#if IS_ENABLED(CONFIG_HYPERV_VMBUS)
> bool hv_vmbus_exists(void);
> +#else
> +static inline bool hv_vmbus_exists(void) { return false; }
> +#endif
>
> struct hv_ring_buffer_debug_info {
> u32 current_interrupt_mask;
Reviewed-by: Hardik Garg <hargar@linux.microsoft.com>
Thanks,
Hardik
^ permalink raw reply
* RE: [PATCH 1/1] drm/hyperv: Replace "hyperv_" with "hvdrm_" as symbol name prefix
From: Dexuan Cui @ 2026-05-27 19:54 UTC (permalink / raw)
To: Michael Kelley, Hamza Mahfooz
Cc: maarten.lankhorst@linux.intel.com, mripard@kernel.org,
tzimmermann@suse.de, airlied@gmail.com, simona@ffwll.ch, Long Li,
ssengar@linux.microsoft.com, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org, linux-hyperv@vger.kernel.org
In-Reply-To: <SN6PR02MB4157EC6C4CE3BBE2ACC3E86AD4082@SN6PR02MB4157.namprd02.prod.outlook.com>
> From: Michael Kelley <mhklinux@outlook.com>
> Sent: Wednesday, May 27, 2026 8:05 AM
> > >
> > > Function and structure names in the Hyper-V DRM driver currently
> > > use "hyperv_" as the prefix. This conflicts with usage in core Hyper-V
> > > and VMBus code, and incorrectly implies that functions and structures
> > > in this driver apply generically to Hyper-V. A specific conflict arises
> > > for "hyperv_init", which is an initcall for generic Hyper-V
> > > initialization on arm64. The conflict prevents the use of
> > > initcall_blacklist on the kernel boot line to skip loading this driver.
I also hit the issue. Thanks for the fix!
> > > Fix this by substituting "hvdrm_" as the prefix for all functions and
> >
> > I would personally prefer "hv_drm_", since it seems clearer.
>
> My choice of "hvdrm" mimics the old Hyper-V FBdev driver, which
> uses "hvfb" as the prefix. However, looking through everything that
> starts with "hv" in /proc/kallsyms, I also see prefixes with the additional
> underscore. "hv_kbd_" in the Hyper-V keyboard driver is an example.
> The Hyper-V utils drivers have both forms -- I see "hv_vss_", "hv_ptp_",
> and "hv_kvp_", but also "hvt" (for Hyper-V Transport). So the historical
> practice is inconsistent.
>
> I'm OK going either way. Does anyone else want to express a
> preference?
I also prefer "hv_drm_".
> > > -struct hyperv_drm_device {
> > > +struct hvdrm_drm_device {
> >
> > "hvdrm_drm_device" looks kinda redundant, perhaps
> > s/hyperv_drm_device/hv_drm_device would be more sensible.
s/hyperv_drm_device/hv_drm_dev/ seems better to me.
> Yes, I'll make this change. And in looking through kallsyms, I
> see that the Hyper-V DRM driver has "hv_fops", which did not
> get changed in the mechanical substitution because it doesn't
> start with "hyperv_". I'll change it to hv_drm_fops.
>
> Michael
Some comments need to be updated accordingly, e.g.
/* hvdrm_drm_modeset */
/* hvdrm_drm_proto */
This needs to be updated as well:
+static const struct drm_encoder_funcs hvdrm_drm_simple_encoder_funcs_cleanup
Thanks,
Dexuan
^ permalink raw reply
* [PATCH] hyperv: Clean up and fix the guest ID comment in hvgdk.h
From: Dexuan Cui @ 2026-05-27 19:21 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, linux-hyperv; +Cc: gregkh, linux-kernel
Change the "64 bit" to "64-bit", and the "Os" to "OS".
Remove the obsolete paragraph since the guideline has been
published in the Hypervisor Top Level Functional Specification
for many years.
The "OS Type" is 0x1 for Linux, not 0x100.
No functional change.
Fixes: 83ba0c4f3f31 ("Drivers: hv: Cleanup the guest ID computation")
Signed-off-by: Dexuan Cui <decui@microsoft.com>
---
include/hyperv/hvgdk.h | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/include/hyperv/hvgdk.h b/include/hyperv/hvgdk.h
index 384c3f3ff4a5..f538144280ca 100644
--- a/include/hyperv/hvgdk.h
+++ b/include/hyperv/hvgdk.h
@@ -10,18 +10,12 @@
/*
* The guest OS needs to register the guest ID with the hypervisor.
- * The guest ID is a 64 bit entity and the structure of this ID is
+ * The guest ID is a 64-bit entity and the structure of this ID is
* specified in the Hyper-V TLFS specification.
*
- * While the current guideline does not specify how Linux guest ID(s)
- * need to be generated, our plan is to publish the guidelines for
- * Linux and other guest operating systems that currently are hosted
- * on Hyper-V. The implementation here conforms to this yet
- * unpublished guidelines.
- *
* Bit(s)
* 63 - Indicates if the OS is Open Source or not; 1 is Open Source
- * 62:56 - Os Type; Linux is 0x100
+ * 62:56 - OS Type; Linux is 0x1
* 55:48 - Distro specific identification
* 47:16 - Linux kernel version number
* 15:0 - Distro specific identification
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v2 1/1] mshv: Add conditional VMBus dependency
From: Jork Loeser @ 2026-05-27 17:22 UTC (permalink / raw)
To: mhklinux
Cc: kys, haiyangz, wei.liu, decui, longli, linux-hyperv, linux-kernel,
arnd, hamzamahfooz
In-Reply-To: <20260526141304.3924-1-mhklkml@zohomail.com>
On Tue, 26 May 2026, Michael Kelley wrote:
> From: Michael Kelley <mhklinux@outlook.com>
>
> When the VMBus driver is not part of the kernel (CONFIG_HYPERV_VMBUS=n),
> the MSHV root driver fails to link:
>
> ERROR: modpost: "hv_vmbus_exists" [drivers/hv/mshv_root.ko] undefined!
>
> Fix this while meeting these requirements:
> * It must be possible to include the MSHV root driver without the
> VMBus driver. In such case, the MSHV root driver can be built-in
> to the kernel image, or it can be built as a separate module.
> * If both the MSHV root driver and the VMBus driver are present, the
> MSHV root driver and VMBus driver can both be built-in, or they can
> both be separate modules. Or the MSHV root driver can be a module
> while the VMBus driver can be built-in, but the reverse is
> disallowed. Regardless of the build choices, the VMBus driver must
> be loaded before the MSHV driver in order for the SynIC to be
> managed properly (see comments in the MSHV SynIC code).
>
> The fix has two parts:
> * Add a Kconfig entry for MSHV_ROOT to depend on HYPERV_VMBUS if
> HYPERV_VMBUS is present. The entry disallows MSHV_ROOT being
> built-in when HYPERV_VMBUS is a module, but without requiring that
> HYPERV_VMBUS be built.
> * Add a stub implementation of hv_vmbus_exists() for when the
> VMBus driver is not present so that the MSHV root driver has
> no module dependency on VMBus. When the VMBus driver *is*
> present, the module dependency ensures that the VMBus driver
> loads first when both are built as modules.
>
> Existing code ensures that the VMBus driver loads first if it is
> built-in. The VMBus driver uses subsys_initcall(), which is
> initcall level 4. The MSHV root driver uses module_init(), which
> becomes device_init() when built-in, and device_init() is
> initcall level 6.
>
> Reported-by: Arnd Bergmann <arnd@arndb.de>
> Closes: https://lore.kernel.org/all/20260520074044.923728-1-arnd@kernel.org/
> Signed-off-by: Michael Kelley <mhklinux@outlook.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Jork Loeser <jloeser@linux.microsoft.com>
> ---
> Changes in v2:
> * Instead of putting IS_ENABLED(CONFIG_HYPERV_VMBUS) around each of
> the two calls to hv_vmbus_exists() in mshv_synic.c, provide a stub
> for hv_vmbus_exists() when CONFIG_HYPERV_VMBUS is not set. The
> effect is the same as in v1, but the code is cleaner. [Jork Loeser]
>
> Arnd: I've kept your Ack even though I changed how hv_vmbus_exists()
> is stubbed out since the effect is the same. Let me know if
> you have any concerns.
>
> drivers/hv/Kconfig | 1 +
> include/linux/hyperv.h | 4 ++++
> 2 files changed, 5 insertions(+)
>
> diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
> index 2d0b3fcb0ff8..aa11bcefddf2 100644
> --- a/drivers/hv/Kconfig
> +++ b/drivers/hv/Kconfig
> @@ -74,6 +74,7 @@ config MSHV_ROOT
> # e.g. When withdrawing memory, the hypervisor gives back 4k pages in
> # no particular order, making it impossible to reassemble larger pages
> depends on PAGE_SIZE_4KB
> + depends on HYPERV_VMBUS if HYPERV_VMBUS
> select EVENTFD
> select VIRT_XFER_TO_GUEST_WORK
> select HMM_MIRROR
> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
> index 41a3d82f0722..734b7ef98f4d 100644
> --- a/include/linux/hyperv.h
> +++ b/include/linux/hyperv.h
> @@ -1304,7 +1304,11 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
>
> struct device *hv_get_vmbus_root_device(void);
>
> +#if IS_ENABLED(CONFIG_HYPERV_VMBUS)
> bool hv_vmbus_exists(void);
> +#else
> +static inline bool hv_vmbus_exists(void) { return false; }
> +#endif
>
> struct hv_ring_buffer_debug_info {
> u32 current_interrupt_mask;
> --
> 2.25.1
>
Thank you!
Reviewed-by: Jork Loeser <jloeser@linux.microsoft.com>
^ permalink raw reply
* Re: [PATCH v2 0/9] drm: Limit DRM_IOCTL_WAIT_VBLANK to vblank interrupts
From: Julian Orth @ 2026-05-27 16:31 UTC (permalink / raw)
To: Thomas Zimmermann
Cc: simona, airlied, mdaenzer, pekka.paalanen, jadahl, contact,
maarten.lankhorst, mripard, mhklinux, amd-gfx, dri-devel,
wayland-devel, linux-hyperv, virtualization, spice-devel
In-Reply-To: <20260527133917.207150-1-tzimmermann@suse.de>
On Wed, May 27, 2026 at 3:39 PM Thomas Zimmermann <tzimmermann@suse.de> wrote:
>
> DRM's WAIT_VBLANK ioctl synchronizes user-space clients to display
> refresh. This is meaningless with vblank timers, which run unrelated
> to the hardware's vblank.
>
> Disable the ioctl for simulated vblanks. Set DRM_VBLANK_FLAG_SIMULATED
> for CRTCs with simulated vblank events in all such drivers. The vblank
> timers of these devices still rate-limit the number of page-flip events
> to match the display refresh.
>
> According to maintainers, user-space compositors do not require the ioctl
> for rate-limitting display output. Weston, Kwin and Mutter rely on completion
> events. Mutter optionally uses the WAIT_VBLANK ioctl only to optimize the
> time from input to output.
>
> When testing with mutter and weston, the page-flip rate appears correct
> with the patch set applied.
To avoid this being a regression, you need to test that this change
does not regress input latency.
As discussed on IRC, compositors use vblank data to predict the time
of the next flip event. For each device that you are touching here,
there are two possibilities:
- The vblank data is related to the flip timing, i.e. flip events and
vblank events are sent at almost the same time. In this case removing
these apis removes the path for compositors to predict the time of the
next flip event. Input latency will therefore regress after idle
periods when the compositor no longer has the time of the last vblank.
- The vblank data has nothing to do with the time of the next flip
event. In this case this series could in fact improve latency because
it removes the incorrect data from the compositor.
Whether the times of the flip events correspond to hardware timings is
not relevant. Everything in wayland compositors is scheduled against
flip event timings and they are also forwarded to clients for their
frame scheduling. If the flip timings are wrong/out of sync with the
hardware, then removing the vblank apis does not improve this
situation.
>
> This change has been discussed at length on IRC recently.
>
> https://people.freedesktop.org/~cbrill/dri-log/?channel=dri-devel&highlight_names=&date=2026-05-08&show_html=true
> https://people.freedesktop.org/~cbrill/dri-log/?channel=dri-devel&highlight_names=&date=2026-05-12&show_html=true
> https://people.freedesktop.org/~cbrill/dri-log/?channel=dri-devel&highlight_names=&date=2026-05-13&show_html=true
> https://people.freedesktop.org/~cbrill/dri-log/?channel=dri-devel&highlight_names=&date=2026-05-15&show_html=true
>
> v2:
> - add filter to CRTC_GET_SEQUENCE and CRTC_QUEUE_SEQUENCE ioctls (Michel)
> - clarify Mutter's behavior in cover letter (Michel)
>
> Thomas Zimmermann (9):
> drm/vblank: Add drmm_vblank_init() to indicate managed cleanup
> drm/vblank: Add DRM_VBLANK_FLAG_SIMULATED
> drm/amdgpu: vkms: Set DRM_VBLANK_FLAG_SIMULATED
> drm/bochs: Set DRM_VBLANK_FLAG_SIMULATED
> drm/cirrus: Set DRM_VBLANK_FLAG_SIMULATED
> drm/hypervdrm: Set DRM_VBLANK_FLAG_SIMULATED
> drm/qxl: Set DRM_VBLANK_FLAG_SIMULATED
> drm/virtgpu: Set DRM_VBLANK_FLAG_SIMULATED
> drm/vkms: Set DRM_VBLANK_FLAG_SIMULATED
>
> drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 3 ++-
> drivers/gpu/drm/drm_vblank.c | 26 +++++++++++++++------
> drivers/gpu/drm/drm_vblank_helper.c | 2 +-
> drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 2 +-
> drivers/gpu/drm/qxl/qxl_display.c | 2 +-
> drivers/gpu/drm/tiny/bochs.c | 2 +-
> drivers/gpu/drm/tiny/cirrus-qemu.c | 2 +-
> drivers/gpu/drm/virtio/virtgpu_display.c | 2 +-
> drivers/gpu/drm/vkms/vkms_drv.c | 4 ++--
> include/drm/drm_crtc.h | 2 +-
> include/drm/drm_device.h | 2 +-
> include/drm/drm_vblank.h | 15 +++++++++++-
> 12 files changed, 45 insertions(+), 19 deletions(-)
>
>
> base-commit: 5fb5a9a63cf5ece68e0eeb6fa397da27712bccf0
> --
> 2.54.0
>
^ permalink raw reply
* Re: [PATCH v3 05/10] drm/appletbdrm: Allocate request/response buffers in begin_fb_access
From: sashiko-bot @ 2026-05-27 15:42 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-hyperv
In-Reply-To: <20260527145113.241595-6-tzimmermann@suse.de>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Unbounded accumulation of damage clip sizes causes an integer overflow, resulting in an undersized buffer allocation and subsequent out-of-bounds heap write.
- [High] The plane `atomic_update` callback incorrectly calls sleeping functions, violating DRM atomic context guidelines.
- [High] Mismatched coordinate space intersection and inconsistent calculation ordering lead to uninitialized memory gaps and malformed hardware payloads.
--
commit fc37b98d4bfc3183056fa690c4e2e659894c67e7
Author: Thomas Zimmermann <tzimmermann@suse.de>
Date: Wed May 27 14:46:24 2026 +0000
drm/appletbdrm: Allocate request/response buffers in begin_fb_access
In atomic_check, damage handling is not fully evaluated. Another
atomic_check helper could trigger a full modeset and thus invalidate
damage clips.
Allocation of the request/response buffers in appletbdrm depends on
correct damage information. Otherwise it might allocate incorrectly
sized buffers. Allocate the buffers in the driver's begin_fb_access
helper. It runs early during the commit when damage clipping has been
fully evaluated.
> diff --git a/drivers/gpu/drm/tiny/appletbdrm.c b/drivers/gpu/drm/tiny/appletbdrm.c
> index cdd35af498920..b683dcb35b0be 100644
> --- a/drivers/gpu/drm/tiny/appletbdrm.c
> +++ b/drivers/gpu/drm/tiny/appletbdrm.c
> @@ -315,33 +315,16 @@ static const u32 appletbdrm_primary_plane_formats[] = {
> DRM_FORMAT_XRGB8888, /* emulated */
> };
>
> -static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
> - struct drm_atomic_commit *state)
> +static int appletbdrm_primary_plane_helper_begin_fb_access(struct drm_plane *plane,
> + struct drm_plane_state *new_plane_state)
> {
> struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(new_plane_state);
> + size_t frames_size = 0;
> struct drm_atomic_helper_damage_iter iter;
> struct drm_rect damage;
> size_t request_size;
>
> - drm_atomic_helper_damage_iter_init(&iter, old_plane_state, new_plane_state);
> + drm_atomic_helper_damage_iter_init(&iter, NULL, new_plane_state);
> drm_atomic_for_each_plane_damage(&iter, &damage) {
> frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage));
> }
[Severity: Critical]
This is a pre-existing issue, but could the unbounded accumulation of damage
clip sizes cause an integer overflow?
The FB_DAMAGE_CLIPS property allows userspace to pass an unbounded number of
damage clips, limited only by the maximum DRM property blob size.
If millions of clips are provided, accumulating the sizes with:
frames_size += struct_size(...)
could wrap around size_t on 32-bit systems. Even if frames_size doesn't wrap,
the subsequent calculation:
request_size = ALIGN(sizeof(...) + frames_size + sizeof(...), 16)
might easily wrap around to a small value, causing kvzalloc() to successfully
allocate an undersized buffer.
When appletbdrm_flush_damage() iteratively processes the exact same clips,
could it trust the per-clip buf_size and copy pixel data into the undersized
buffer via drm_fb_memcpy(), resulting in an out-of-bounds heap write?
[Severity: High]
This is also a pre-existing issue, but does this allocation properly account
for the intersection calculations that happen later?
In appletbdrm_flush_damage(), buf_size is calculated before the intersection:
buf_size = rect_size(&damage);
if (!drm_rect_intersect(&dst_clip, &damage))
continue;
If the intersection shrinks the damage rectangle, drm_fb_memcpy() copies fewer
bytes than buf_size, leaving zeroed memory at the end of the frame buffer.
Since frame->buf_size was already set to the original size, the hardware will
read these zeroes as pixel data.
Furthermore, dst_clip is in CRTC coordinates while damage is in Framebuffer
(SRC) coordinates. If userspace utilizes a framebuffer larger than the CRTC
and applies a source offset, the coordinate spaces will not overlap properly.
This causes valid damage clips to be skipped entirely.
Since the begin_fb_access() helper factored these skipped clips into the total
frames_size allocation without performing the intersection, skipping them later
fails to advance the frame pointer.
Could this leave uninitialized gaps before the footer, corrupting the packed
payload structure sent to the hardware?
[ ... ]
> @@ -468,7 +474,7 @@ static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
> }
>
> static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
> - struct drm_atomic_commit *old_state)
> + struct drm_atomic_commit *old_state)
> {
> struct appletbdrm_device *adev = drm_to_adev(plane->dev);
> struct drm_device *drm = plane->dev;
[Severity: High]
This is a pre-existing issue, but does this code execute sleeping functions
from an atomic context?
According to DRM atomic context guidelines, plane atomic update callbacks
execute in an atomic context where sleeping is forbidden.
The appletbdrm_primary_plane_helper_atomic_update() callback invokes
appletbdrm_flush_damage(), which subsequently calls:
drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
This function takes locks and can wait on fences. The flush function then
performs synchronous USB bulk transfers, which also sleep.
Could this break atomic context rules and cause system instability?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260527145113.241595-1-tzimmermann@suse.de?part=5
^ permalink raw reply
* Re: [PATCH v3 10/10] drm/vmwgfx: Remove unused field struct vmwgfx_du_update_plane.old_state
From: sashiko-bot @ 2026-05-27 15:22 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-hyperv
In-Reply-To: <20260527145113.241595-11-tzimmermann@suse.de>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Plane atomic_update callbacks indirectly call sleeping functions (mutex_lock/mutex_lock_interruptible) from an atomic context.
--
commit deccb03fba43ed6006d88ae9933240eb52b52fee
Author: Thomas Zimmermann <tzimmermann@suse.de>
drm/vmwgfx: Remove unused field struct vmwgfx_du_update_plane.old_state
This commit removes the unused old_state field from the
vmw_du_update_plane structure and updates all caller functions to
accommodate this change.
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
[ ... ]
> @@ -721,7 +717,6 @@ static void
> vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
> struct drm_atomic_commit *state)
> {
> - struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
> struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
> struct drm_crtc *crtc = new_state->crtc;
> struct vmw_fence_obj *fence = NULL;
> @@ -734,12 +729,9 @@ vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
> vmw_framebuffer_to_vfb(new_state->fb);
>
> if (vfb->bo)
> - ret = vmw_sou_plane_update_bo(dev_priv, plane,
> - old_state, vfb, &fence);
> + ret = vmw_sou_plane_update_bo(dev_priv, plane, vfb, &fence);
> else
> - ret = vmw_sou_plane_update_surface(dev_priv, plane,
> - old_state, vfb,
> - &fence);
> + ret = vmw_sou_plane_update_surface(dev_priv, plane, vfb, &fence);
[Severity: High]
This is a pre-existing issue, but does this code path end up calling sleeping
functions from an atomic context?
Looking at the call chain, vmw_sou_primary_plane_atomic_update() is a plane
atomic update callback, which runs in atomic context where sleeping is
forbidden. However, it calls vmw_sou_plane_update_surface(), which assigns a
mutex pointer to the update structure:
vmw_sou_plane_update_surface()
srf_update.base.mutex = &dev_priv->cmdbuf_mutex;
vmw_du_helper_plane_update(&srf_update.base);
This closure is then passed down to vmw_du_helper_plane_update(), which calls
vmw_validation_prepare(). That function then takes the lock using
mutex_lock() or mutex_lock_interruptible().
Could this lead to system instability or deadlocks if the atomic commit runs
in a non-blocking path where sleeping is not allowed?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260527145113.241595-1-tzimmermann@suse.de?part=10
^ permalink raw reply
* Re: [PATCH v3 01/10] drm/damage-helper: Do not alter damage clips on modeset, but ignore them
From: sashiko-bot @ 2026-05-27 15:19 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-hyperv
In-Reply-To: <20260527145113.241595-2-tzimmermann@suse.de>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Retaining damage clips during modesets causes drivers that directly access damage clips to incorrectly perform partial screen updates instead of full screen updates.
--
commit 36f89d2b464094389bd2dab30c24b79223ef7bd1
Author: Thomas Zimmermann <tzimmermann@suse.de>
drm/damage-helper: Do not alter damage clips on modeset, but ignore them
This commit modifies the plane damage check to retain damage clips during
a full modeset. Instead of explicitly clearing the clips, it sets a new
ignore_damage_clips flag which is then checked by the damage iterator.
> diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
> --- a/drivers/gpu/drm/drm_damage_helper.c
> +++ b/drivers/gpu/drm/drm_damage_helper.c
> @@ -78,10 +78,8 @@ void drm_atomic_helper_check_plane_damage(struct drm_atomic_commit *state,
> if (WARN_ON(!crtc_state))
> return;
>
> - if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> - drm_property_blob_put(plane_state->fb_damage_clips);
> - plane_state->fb_damage_clips = NULL;
> - }
> + if (drm_atomic_crtc_needs_modeset(crtc_state))
> + plane_state->ignore_damage_clips = true;
> }
> }
[Severity: High]
By no longer setting plane_state->fb_damage_clips to NULL during a modeset,
will this break drivers that bypass the damage iterator?
Drivers like AMDGPU (in fill_dc_dirty_rects) and vmwgfx directly call
drm_plane_get_damage_clips_count() and drm_plane_get_damage_clips().
Because these accessor functions do not check the new ignore_damage_clips flag,
won't they see a non-zero clip count if userspace provided one?
If they see a non-zero clip count during a modeset, will they incorrectly
skip their fallback paths and perform a partial update instead of the
required full framebuffer update?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260527145113.241595-1-tzimmermann@suse.de?part=1
^ permalink raw reply
* Re: [PATCH v3 00/10] drm: Improve logic behind damage handling
From: Thomas Zimmermann @ 2026-05-27 15:17 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Am 27.05.26 um 16:46 schrieb Thomas Zimmermann:
> DRM clients can supply information on framebuffer areas to update as
> part of each page flip, called damage clipping rectangles. But DRM's
> processing of this information is inconsistent and prone to errors.
>
> - There are multiple fields and tests that decide if damage clips
> should be taken or ignored.
>
> - Sometimes damage clips are removed behind the back of the DRM client.
>
> - Atomic helpers evaluate damage clipping in the middle of the atomic
> check: after connectors and encoders, but before planes and CRTCs. Hence
> pipeline stages have an inconsistent view.
>
> - Which leads to drivers (ingenic) doing a re-evaluation if necessary.
>
> - Tests of plane source coordinates only happen during commits. At this
> point, the driver should already know if damage clips are to be taken or
> not. Because of this, some drivers (appletbdrm) might operate on incorrect
> damage information for their internal workings. This also leads to excessive
> use of the old plane state.
>
> Therefore go through DRM helpers and drivers and fix the logic.
>
> - Run all of the atomic checks with the damage information supplied by
> DRM clients. Afterwards evaluate plane and CRTC states on whether to
> take or ignore damage clips. Do all related tests in a single atomic
> helper.
>
> - Do not discard damage clips. Set ignore_damage_clips in struct
> drm_plane_state instead. This includes changes to plane source-coordinates.
> The damage iterator now only has to look at this flag to detect if it
> should use the damage clips.
>
> - Go over drivers and fix the damage handling in the plane's
> atomic_update helpers. Most drivers no longer need the old plane state
> in their update.
>
> - The appletbdrm driver requires a fix in how it uses damage information.
> Ingenic and vmwgfx can be simplified. These changes improve the drivers'
> code organization.
>
> - Kunit tests require some changes. Drop some obsolete tests and add a new
> one for ignore_damage_flags.
>
> Tested with bochs, mgag200, Kunit tests.
>
> v3:
> - fix error path in appletbdrm
> v2:
> - rebase on latest upstream
>
> Thomas Zimmermann (10):
> drm/damage-helper: Do not alter damage clips on modeset, but ignore
> them
> drm/atomic-helpers: Evaluate plane damage after atomic_check
> drm/ingenic: Remove calls to drm_atomic_helper_check_plane_damage()
> drm/damage-helper: Test src coord in
> drm_atomic_helper_check_plane_damage()
> drm/appletbdrm: Allocate request/response buffers in begin_fb_access
> drm/damage-helper: Remove old state from
> drm_atomic_helper_damage_iter_init()
> drm/damage-helper: Remove old state from
> drm_atomic_helper_damage_merged()
> drm/atomic_helper: Do not evaluate plane damage before atomic_check
> drm/damage-helper: Rename state parameters in damage helpers
> drm/vmwgfx: Remove unused field struct
> vmwgfx_du_update_plane.old_state
>
> drivers/gpu/drm/ast/ast_cursor.c | 3 +-
> drivers/gpu/drm/ast/ast_mode.c | 2 +-
> drivers/gpu/drm/drm_atomic_helper.c | 6 +-
> drivers/gpu/drm/drm_atomic_state_helper.c | 1 +
> drivers/gpu/drm/drm_damage_helper.c | 44 ++--
> drivers/gpu/drm/drm_fb_dma_helper.c | 2 +-
> drivers/gpu/drm/drm_mipi_dbi.c | 3 +-
> drivers/gpu/drm/gud/gud_pipe.c | 3 +-
> drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 3 +-
> drivers/gpu/drm/i915/display/intel_plane.c | 11 +-
> drivers/gpu/drm/i915/display/intel_psr.c | 3 +-
> drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 3 -
> drivers/gpu/drm/ingenic/ingenic-ipu.c | 8 +-
> drivers/gpu/drm/mgag200/mgag200_mode.c | 3 +-
> drivers/gpu/drm/sitronix/st7571.c | 3 +-
> drivers/gpu/drm/sitronix/st7586.c | 3 +-
> drivers/gpu/drm/sitronix/st7920.c | 3 +-
> drivers/gpu/drm/solomon/ssd130x.c | 9 +-
> drivers/gpu/drm/sysfb/drm_sysfb_modeset.c | 3 +-
> .../gpu/drm/tests/drm_damage_helper_test.c | 200 +++---------------
> drivers/gpu/drm/tiny/appletbdrm.c | 59 +++---
> drivers/gpu/drm/tiny/bochs.c | 3 +-
> drivers/gpu/drm/tiny/cirrus-qemu.c | 2 +-
> drivers/gpu/drm/tiny/gm12u320.c | 2 +-
> drivers/gpu/drm/tiny/ili9225.c | 3 +-
> drivers/gpu/drm/tiny/repaper.c | 2 +-
> drivers/gpu/drm/tiny/sharp-memory.c | 3 +-
> drivers/gpu/drm/udl/udl_modeset.c | 3 +-
> drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +-
> drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 5 +-
> drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 -
> drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 12 +-
> drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 15 +-
> include/drm/drm_damage_helper.h | 9 +-
> 34 files changed, 123 insertions(+), 315 deletions(-)
>
>
> base-commit: 5fb5a9a63cf5ece68e0eeb6fa397da27712bccf0
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)
^ permalink raw reply
* Re: [PATCH v3 04/10] drm/damage-helper: Test src coord in drm_atomic_helper_check_plane_damage()
From: sashiko-bot @ 2026-05-27 15:11 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-hyperv
In-Reply-To: <20260527145113.241595-5-tzimmermann@suse.de>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Comparing plane `src` coordinates before `atomic_check` clips them causes unintended full frame updates for partially off-screen planes.
- [Low] Removal of unit tests for `src` coordinate changes without replacing them causes a loss of critical test coverage.
--
commit 70283d9d64d3987145c43d7d6e7df2c84b0de6ae
Author: Thomas Zimmermann <tzimmermann@suse.de>
drm/damage-helper: Test src coord in drm_atomic_helper_check_plane_damage()
This commit evaluates plane source coordinate changes during the atomic check
phase instead of the atomic commit phase. It sets the ignore_damage_clips flag
in the plane state if coordinates change and removes related unit tests.
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1034,7 +1034,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
>
> drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane);
>
> - drm_atomic_helper_check_plane_damage(state, new_plane_state);
> + drm_atomic_helper_check_plane_damage(state, old_plane_state, new_plane_state);
[Severity: Medium]
Is there a risk of unintended full frame updates for partially off-screen
planes here?
When userspace requests an update, the DRM core provides unclipped coordinates
into new_plane_state->src. The old_plane_state->src retains the coordinates
from the previous commit, which were already clipped during that commit's
atomic check phase via drm_atomic_helper_check_plane_state().
Because drm_atomic_helper_check_plane_damage() now performs the
drm_rect_equals check before atomic_check scales and clips the new
coordinates, does it erroneously detect a change in src and permanently latch
ignore_damage_clips = true? This could cause any plane positioned partially
off-screen to continuously ignore damage clips and perform a full update on
every single frame.
Note: This regression is fixed later in the patch series by commit
"drm/atomic_helper: Do not evaluate plane damage before atomic_check".
>
> if (!funcs || !funcs->atomic_check)
> continue;
[ ... ]
> diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c
> --- a/drivers/gpu/drm/tests/drm_damage_helper_test.c
> +++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c
[ ... ]
> -static void drm_test_damage_iter_no_damage_src_moved(struct kunit *test)
> -{
> - struct drm_damage_mock *mock = test->priv;
> - struct drm_atomic_helper_damage_iter iter;
> - struct drm_rect clip;
> - u32 num_hits = 0;
> -
> - /* Plane src moved since old plane state. */
> - set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
> - set_plane_src(&mock->state, 10 << 16, 10 << 16,
> - (10 + 1024) << 16, (10 + 768) << 16);
> - drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
> - drm_atomic_for_each_plane_damage(&iter, &clip)
> - num_hits++;
> -
> - KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
> - check_damage_clip(test, &clip, 10, 10, 1034, 778);
> -}
[Severity: Low]
Does the removal of these unit tests cause a loss of valuable test coverage?
The commit message mentions there is a separate unit test for when
ignore_damage_clips is true, but without these removed tests, there are no
longer any tests ensuring that moving the src coordinates actually correctly
sets ignore_damage_clips = true via drm_atomic_helper_check_plane_damage().
Instead of completely deleting these tests, could they have been adapted to
call drm_atomic_helper_check_plane_damage() prior to initializing the
iterator, preserving the validation of the source coordinate tracking logic?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260527145113.241595-1-tzimmermann@suse.de?part=4
^ permalink raw reply
* Re: [PATCH v3 07/10] drm/damage-helper: Remove old state from drm_atomic_helper_damage_merged()
From: sashiko-bot @ 2026-05-27 15:10 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-hyperv
In-Reply-To: <20260527145113.241595-8-tzimmermann@suse.de>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but the plane atomic update callback `gm12u320_pipe_update` executes a path that acquires a mutex. Plane atomic update callbacks run in atomic context during non-blocking commits, making the use of sleeping locks unsafe.
- [High] This problem wasn't introduced by this patch, but the plane atomic update callback `repaper_pipe_update` executes a path that performs a memory allocation with `GFP_KERNEL`. Plane atomic update callbacks run in atomic context, where allocations that may sleep are strictly prohibited.
--
commit da86f07c371224a54756c1f750c01c663a2a7a86
Author: Thomas Zimmermann <tzimmermann@suse.de>
drm/damage-helper: Remove old state from drm_atomic_helper_damage_merged()
This patch removes the unused old_state parameter from
drm_atomic_helper_damage_merged() and updates all callers. It also cleans up
the old_plane_state variable in caller functions where it is no longer
needed.
[ ... ]
> diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
> --- a/drivers/gpu/drm/tiny/gm12u320.c
> +++ b/drivers/gpu/drm/tiny/gm12u320.c
> @@ -582,7 +582,7 @@ static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
> struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
> struct drm_rect rect;
>
> - if (drm_atomic_helper_damage_merged(old_state, state, &rect))
> + if (drm_atomic_helper_damage_merged(state, &rect))
[Severity: High]
This is a pre-existing issue, but does gm12u320_pipe_update() safely execute
in an atomic context?
This function acts as the simple display pipe's plane atomic update callback,
which runs in atomic context during non-blocking commits. However, it calls
gm12u320_fb_mark_dirty(), which acquires a mutex:
drivers/gpu/drm/tiny/gm12u320.c:gm12u320_fb_mark_dirty() {
...
mutex_lock(&gm12u320->fb_update.lock);
...
}
Since mutex_lock() is a sleeping function, could this lead to deadlocks or
kernel warnings when called from an atomic context?
> gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect);
> }
[ ... ]
> diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c
> --- a/drivers/gpu/drm/tiny/repaper.c
> +++ b/drivers/gpu/drm/tiny/repaper.c
> @@ -837,7 +837,7 @@ static void repaper_pipe_update(struct drm_simple_display_pipe *pipe,
> if (!pipe->crtc.state->active)
> return;
>
> - if (drm_atomic_helper_damage_merged(old_state, state, &rect))
> + if (drm_atomic_helper_damage_merged(state, &rect))
[Severity: High]
This isn't a bug introduced by this patch, but is it safe for
repaper_pipe_update() to trigger allocations with GFP_KERNEL?
Like the issue above, this acts as the plane atomic update callback. It calls
repaper_fb_dirty(), which performs a memory allocation that may sleep:
drivers/gpu/drm/tiny/repaper.c:repaper_fb_dirty() {
...
buf = kmalloc(fb->width * fb->height / 8, GFP_KERNEL);
...
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
...
}
Because plane atomic update callbacks run in atomic context, allocations that
may sleep (like GFP_KERNEL) and sleeping functions like
drm_gem_fb_begin_cpu_access() are strictly prohibited. Is there a plan to
shift these sleeping operations to a workqueue or use non-sleeping
allocations?
> repaper_fb_dirty(state->fb, shadow_plane_state->data,
> &shadow_plane_state->fmtcnv_state);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260527145113.241595-1-tzimmermann@suse.de?part=7
^ permalink raw reply
* Re: [PATCH v3 06/10] drm/damage-helper: Remove old state from drm_atomic_helper_damage_iter_init()
From: sashiko-bot @ 2026-05-27 15:07 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: linux-hyperv
In-Reply-To: <20260527145113.241595-7-tzimmermann@suse.de>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Integer overflow in `frames_size` accumulation in `appletbdrm_primary_plane_helper_begin_fb_access()` leads to an undersized allocation and subsequent heap buffer overflow.
--
commit 95dfe9915dca0c203d54cd610ead65b1de9a07b7
Author: Thomas Zimmermann <tzimmermann@suse.de>
drm/damage-helper: Remove old state from drm_atomic_helper_damage_iter_init()
This commit removes the unused old_plane_state parameter from
drm_atomic_helper_damage_iter_init() and updates all callers. Most callers
no longer require the old plane state in their atomic_update helpers.
[ ... ]
> diff --git a/drivers/gpu/drm/tiny/appletbdrm.c b/drivers/gpu/drm/tiny/appletbdrm.c
> index b683dcb35b0be..eadc3aed72774 100644
> --- a/drivers/gpu/drm/tiny/appletbdrm.c
> +++ b/drivers/gpu/drm/tiny/appletbdrm.c
> @@ -324,7 +324,7 @@ static int appletbdrm_primary_plane_helper_begin_fb_access(struct drm_plane *pla
> struct drm_rect damage;
> size_t request_size;
>
> - drm_atomic_helper_damage_iter_init(&iter, NULL, new_plane_state);
> + drm_atomic_helper_damage_iter_init(&iter, new_plane_state);
> drm_atomic_for_each_plane_damage(&iter, &damage) {
> frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage));
[Severity: Critical]
This is a pre-existing issue, but can this loop cause an integer overflow
when accumulating frames_size?
Because += is used instead of safe accumulation like size_add(), supplying a
large number of clips (or clips with large dimensions) could cause the size_t
variable frames_size to wrap around. For example, on 32-bit systems, a large
amount of damage clips can map to >4GB of frame data.
This would result in an undersized buffer being allocated via kvzalloc().
Subsequently, in appletbdrm_flush_damage(), the code iterates over the same
clips and uses drm_fb_memcpy() or drm_fb_xrgb8888_to_bgr888() to copy the
full unclipped frame data into the destination buffer, potentially causing a
heap buffer overflow.
> }
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260527145113.241595-1-tzimmermann@suse.de?part=6
^ permalink raw reply
* RE: [PATCH 1/1] drm/hyperv: Replace "hyperv_" with "hvdrm_" as symbol name prefix
From: Michael Kelley @ 2026-05-27 15:05 UTC (permalink / raw)
To: Hamza Mahfooz, Michael Kelley
Cc: maarten.lankhorst@linux.intel.com, mripard@kernel.org,
tzimmermann@suse.de, airlied@gmail.com, simona@ffwll.ch,
decui@microsoft.com, longli@microsoft.com,
ssengar@linux.microsoft.com, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org, linux-hyperv@vger.kernel.org
In-Reply-To: <ahbr3aepFUuJ45Zg@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net>
From: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> Sent: Wednesday, May 27, 2026 6:04 AM
>
> On Tue, May 26, 2026 at 01:52:39PM -0700, Michael Kelley wrote:
> > From: Michael Kelley <mhklinux@outlook.com>
> >
> > Function and structure names in the Hyper-V DRM driver currently
> > use "hyperv_" as the prefix. This conflicts with usage in core Hyper-V
> > and VMBus code, and incorrectly implies that functions and structures
> > in this driver apply generically to Hyper-V. A specific conflict arises
> > for "hyperv_init", which is an initcall for generic Hyper-V
> > initialization on arm64. The conflict prevents the use of
> > initcall_blacklist on the kernel boot line to skip loading this driver.
> >
> > Fix this by substituting "hvdrm_" as the prefix for all functions and
>
> I would personally prefer "hv_drm_", since it seems clearer.
My choice of "hvdrm" mimics the old Hyper-V FBdev driver, which
uses "hvfb" as the prefix. However, looking through everything that
starts with "hv" in /proc/kallsyms, I also see prefixes with the additional
underscore. "hv_kbd_" in the Hyper-V keyboard driver is an example.
The Hyper-V utils drivers have both forms -- I see "hv_vss_", "hv_ptp_",
and "hv_kvp_", but also "hvt" (for Hyper-V Transport). So the historical
practice is inconsistent.
I'm OK going either way. Does anyone else want to express a
preference?
>
> > structures in this driver. This prefix marries the existing "hv" prefix
> > for Hyper-V related code with "drm" to indicate this driver.
> >
> > The changes are all mechanical text substitution in symbol names.
> > There are no other code or functional changes.
> >
> > Signed-off-by: Michael Kelley <mhklinux@outlook.com>
> > ---
> > This patch is built against linux-next20260526.
> >
> > drivers/gpu/drm/hyperv/hyperv_drm.h | 20 ++--
> > drivers/gpu/drm/hyperv/hyperv_drm_drv.c | 88 ++++++++--------
> > drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 110 ++++++++++----------
> > drivers/gpu/drm/hyperv/hyperv_drm_proto.c | 70 ++++++-------
> > 4 files changed, 144 insertions(+), 144 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/hyperv/hyperv_drm.h
> b/drivers/gpu/drm/hyperv/hyperv_drm.h
> > index 9e776112c03e..66bd8730aad2 100644
> > --- a/drivers/gpu/drm/hyperv/hyperv_drm.h
> > +++ b/drivers/gpu/drm/hyperv/hyperv_drm.h
> > @@ -8,7 +8,7 @@
> >
> > #define VMBUS_MAX_PACKET_SIZE 0x4000
> >
> > -struct hyperv_drm_device {
> > +struct hvdrm_drm_device {
>
> "hvdrm_drm_device" looks kinda redundant, perhaps
> s/hyperv_drm_device/hv_drm_device would be more sensible.
Yes, I'll make this change. And in looking through kallsyms, I
see that the Hyper-V DRM driver has "hv_fops", which did not
get changed in the mechanical substitution because it doesn't
start with "hyperv_". I'll change it to hv_drm_fops.
Michael
^ permalink raw reply
* [PATCH v3 08/10] drm/atomic_helper: Do not evaluate plane damage before atomic_check
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Remove the call to drm_atomic_helper_check_plane_damage() from before
calling the atomic_check helpers. The call has no longer any purpose,
as the actual evaluation happens after running atomic_check.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_atomic_helper.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 823ce60d45b4..57ffa8c8d641 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1034,8 +1034,6 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane);
- drm_atomic_helper_check_plane_damage(state, old_plane_state, new_plane_state);
-
if (!funcs || !funcs->atomic_check)
continue;
--
2.54.0
^ permalink raw reply related
* [PATCH v3 07/10] drm/damage-helper: Remove old state from drm_atomic_helper_damage_merged()
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Nothing in drm_atomic_helper_damage_merged() requires the old
plane state. Remove the parameter and mass-convert callers.
Most callers now no longer require the old plane state in their plane's
atomic_update helper. Remove it as well.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/ast/ast_cursor.c | 3 +--
drivers/gpu/drm/drm_damage_helper.c | 4 +---
drivers/gpu/drm/drm_mipi_dbi.c | 3 +--
drivers/gpu/drm/i915/display/intel_plane.c | 11 ++---------
drivers/gpu/drm/i915/display/intel_psr.c | 3 +--
drivers/gpu/drm/sitronix/st7586.c | 3 +--
drivers/gpu/drm/tiny/gm12u320.c | 2 +-
drivers/gpu/drm/tiny/ili9225.c | 3 +--
drivers/gpu/drm/tiny/repaper.c | 2 +-
drivers/gpu/drm/tiny/sharp-memory.c | 3 +--
drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +-
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 4 +---
include/drm/drm_damage_helper.h | 3 +--
13 files changed, 14 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c
index fd19c45f2abe..12d5f93eec5f 100644
--- a/drivers/gpu/drm/ast/ast_cursor.c
+++ b/drivers/gpu/drm/ast/ast_cursor.c
@@ -251,7 +251,6 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct ast_device *ast = to_ast_device(plane->dev);
struct drm_rect damage;
u64 dst_off = ast_plane->offset;
@@ -266,7 +265,7 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
* engine to the offset.
*/
- if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
+ if (drm_atomic_helper_damage_merged(plane_state, &damage)) {
const u8 *argb4444 = ast_cursor_plane_get_argb4444(ast_cursor_plane,
shadow_plane_state,
&damage);
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index 28f26234523d..28b847636253 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -296,7 +296,6 @@ EXPORT_SYMBOL(drm_atomic_helper_damage_iter_next);
/**
* drm_atomic_helper_damage_merged - Merged plane damage
- * @old_state: Old plane state for validation.
* @state: Plane state from which to iterate the damage clips.
* @rect: Returns the merged damage rectangle
*
@@ -309,8 +308,7 @@ EXPORT_SYMBOL(drm_atomic_helper_damage_iter_next);
* Returns:
* True if there is valid plane damage otherwise false.
*/
-bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
- const struct drm_plane_state *state,
+bool drm_atomic_helper_damage_merged(const struct drm_plane_state *state,
struct drm_rect *rect)
{
struct drm_atomic_helper_damage_iter iter;
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 25cf04d029f7..4da201c38c93 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -380,7 +380,6 @@ void drm_mipi_dbi_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *plane_state = plane->state;
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_rect rect;
int idx;
@@ -388,7 +387,7 @@ void drm_mipi_dbi_plane_helper_atomic_update(struct drm_plane *plane,
return;
if (drm_dev_enter(plane->dev, &idx)) {
- if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect))
+ if (drm_atomic_helper_damage_merged(plane_state, &rect))
mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
&shadow_plane_state->fmtcnv_state);
drm_dev_exit(idx);
diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c
index a1f9558d53af..f4ef23dee26e 100644
--- a/drivers/gpu/drm/i915/display/intel_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_plane.c
@@ -346,7 +346,6 @@ static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state)
static void
intel_plane_copy_uapi_plane_damage(struct intel_plane_state *new_plane_state,
- const struct intel_plane_state *old_uapi_plane_state,
const struct intel_plane_state *new_uapi_plane_state)
{
struct intel_display *display = to_intel_display(new_plane_state);
@@ -356,10 +355,9 @@ intel_plane_copy_uapi_plane_damage(struct intel_plane_state *new_plane_state,
if (DISPLAY_VER(display) < 12)
return;
- if (!drm_atomic_helper_damage_merged(&old_uapi_plane_state->uapi,
- &new_uapi_plane_state->uapi,
+ if (!drm_atomic_helper_damage_merged(&new_uapi_plane_state->uapi,
damage))
- /* Incase helper fails, mark whole plane region as damage */
+ /* In case the helper fails, mark whole plane region as damage */
*damage = drm_plane_state_src(&new_uapi_plane_state->uapi);
}
@@ -815,7 +813,6 @@ static int plane_atomic_check(struct intel_atomic_state *state,
const struct intel_plane_state *old_plane_state =
intel_atomic_get_old_plane_state(state, plane);
const struct intel_plane_state *new_primary_crtc_plane_state;
- const struct intel_plane_state *old_primary_crtc_plane_state;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, plane->pipe);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
@@ -830,15 +827,11 @@ static int plane_atomic_check(struct intel_atomic_state *state,
new_primary_crtc_plane_state =
intel_atomic_get_new_plane_state(state, primary_crtc_plane);
- old_primary_crtc_plane_state =
- intel_atomic_get_old_plane_state(state, primary_crtc_plane);
} else {
new_primary_crtc_plane_state = new_plane_state;
- old_primary_crtc_plane_state = old_plane_state;
}
intel_plane_copy_uapi_plane_damage(new_plane_state,
- old_primary_crtc_plane_state,
new_primary_crtc_plane_state);
intel_plane_copy_uapi_to_hw_state(new_plane_state,
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 9382ad1e01d8..073eb296236d 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -3015,8 +3015,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
src = drm_plane_state_src(&new_plane_state->uapi);
drm_rect_fp_to_int(&src, &src);
- if (!drm_atomic_helper_damage_merged(&old_plane_state->uapi,
- &new_plane_state->uapi, &damaged_area))
+ if (!drm_atomic_helper_damage_merged(&new_plane_state->uapi, &damaged_area))
continue;
damaged_area.y1 += new_plane_state->uapi.dst.y1 - src.y1;
diff --git a/drivers/gpu/drm/sitronix/st7586.c b/drivers/gpu/drm/sitronix/st7586.c
index 28b2245f6b79..2cc0312595a4 100644
--- a/drivers/gpu/drm/sitronix/st7586.c
+++ b/drivers/gpu/drm/sitronix/st7586.c
@@ -176,7 +176,6 @@ static void st7586_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *plane_state = plane->state;
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_rect rect;
int idx;
@@ -186,7 +185,7 @@ static void st7586_plane_helper_atomic_update(struct drm_plane *plane,
if (!drm_dev_enter(plane->dev, &idx))
return;
- if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect))
+ if (drm_atomic_helper_damage_merged(plane_state, &rect))
st7586_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
&shadow_plane_state->fmtcnv_state);
diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
index d73dfebb4353..880b965e283a 100644
--- a/drivers/gpu/drm/tiny/gm12u320.c
+++ b/drivers/gpu/drm/tiny/gm12u320.c
@@ -582,7 +582,7 @@ static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
struct drm_rect rect;
- if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+ if (drm_atomic_helper_damage_merged(state, &rect))
gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect);
}
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
index 5bf52a8fd75b..d821a659a585 100644
--- a/drivers/gpu/drm/tiny/ili9225.c
+++ b/drivers/gpu/drm/tiny/ili9225.c
@@ -185,7 +185,6 @@ static void ili9225_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *plane_state = plane->state;
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_rect rect;
int idx;
@@ -195,7 +194,7 @@ static void ili9225_plane_helper_atomic_update(struct drm_plane *plane,
if (!drm_dev_enter(drm, &idx))
return;
- if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect))
+ if (drm_atomic_helper_damage_merged(plane_state, &rect))
ili9225_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
&shadow_plane_state->fmtcnv_state);
diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c
index c8270591afc7..531831d2b73f 100644
--- a/drivers/gpu/drm/tiny/repaper.c
+++ b/drivers/gpu/drm/tiny/repaper.c
@@ -837,7 +837,7 @@ static void repaper_pipe_update(struct drm_simple_display_pipe *pipe,
if (!pipe->crtc.state->active)
return;
- if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+ if (drm_atomic_helper_damage_merged(state, &rect))
repaper_fb_dirty(state->fb, shadow_plane_state->data,
&shadow_plane_state->fmtcnv_state);
}
diff --git a/drivers/gpu/drm/tiny/sharp-memory.c b/drivers/gpu/drm/tiny/sharp-memory.c
index 506e6432e70d..1dacd41ddbaa 100644
--- a/drivers/gpu/drm/tiny/sharp-memory.c
+++ b/drivers/gpu/drm/tiny/sharp-memory.c
@@ -241,7 +241,6 @@ static int sharp_memory_plane_atomic_check(struct drm_plane *plane,
static void sharp_memory_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *plane_state = plane->state;
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct sharp_memory_device *smd;
@@ -251,7 +250,7 @@ static void sharp_memory_plane_atomic_update(struct drm_plane *plane,
if (!smd->crtc.state->active)
return;
- if (drm_atomic_helper_damage_merged(old_state, plane_state, &rect))
+ if (drm_atomic_helper_damage_merged(plane_state, &rect))
sharp_memory_fb_dirty(plane_state->fb, shadow_plane_state->data,
&rect, &shadow_plane_state->fmtcnv_state);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index 1d1b27ece62a..4728047315a2 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -260,7 +260,7 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
return;
}
- if (!drm_atomic_helper_damage_merged(old_state, plane->state, &rect))
+ if (!drm_atomic_helper_damage_merged(plane->state, &rect))
return;
bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 4139837f4caf..f0df2b1c8465 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -977,7 +977,6 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
enum stdu_content_type new_content_type;
struct vmw_framebuffer_surface *new_vfbs;
uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h;
- struct drm_plane_state *old_state = plane->state;
struct drm_rect rect;
int ret;
@@ -1101,8 +1100,7 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
struct vmw_surface *surf = vmw_user_object_surface(&vps->uo);
struct vmw_resource *res = &surf->res;
- if (!res->res_dirty && drm_atomic_helper_damage_merged(old_state,
- new_state,
+ if (!res->res_dirty && drm_atomic_helper_damage_merged(new_state,
&rect)) {
/*
* At some point it might be useful to actually translate
diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h
index fafe29b50fc6..b5a4de779db6 100644
--- a/include/drm/drm_damage_helper.h
+++ b/include/drm/drm_damage_helper.h
@@ -77,8 +77,7 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
bool
drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
struct drm_rect *rect);
-bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
- const struct drm_plane_state *state,
+bool drm_atomic_helper_damage_merged(const struct drm_plane_state *state,
struct drm_rect *rect);
#endif
--
2.54.0
^ permalink raw reply related
* [PATCH v3 06/10] drm/damage-helper: Remove old state from drm_atomic_helper_damage_iter_init()
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Nothing in drm_atomic_helper_damage_iter_init() requires the old
plane state. Remove the parameter and mass-convert callers.
Most callers now no longer require the old plane state in their plane's
atomic_update helper. Remove it as well.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/ast/ast_mode.c | 2 +-
drivers/gpu/drm/drm_damage_helper.c | 4 +-
drivers/gpu/drm/drm_fb_dma_helper.c | 2 +-
drivers/gpu/drm/gud/gud_pipe.c | 3 +-
drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 3 +-
drivers/gpu/drm/mgag200/mgag200_mode.c | 3 +-
drivers/gpu/drm/sitronix/st7571.c | 3 +-
drivers/gpu/drm/sitronix/st7920.c | 3 +-
drivers/gpu/drm/solomon/ssd130x.c | 9 +--
drivers/gpu/drm/sysfb/drm_sysfb_modeset.c | 3 +-
.../gpu/drm/tests/drm_damage_helper_test.c | 55 ++++++-------------
drivers/gpu/drm/tiny/appletbdrm.c | 8 +--
drivers/gpu/drm/tiny/bochs.c | 3 +-
drivers/gpu/drm/tiny/cirrus-qemu.c | 2 +-
drivers/gpu/drm/udl/udl_modeset.c | 3 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 5 +-
include/drm/drm_damage_helper.h | 3 +-
17 files changed, 37 insertions(+), 77 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index d5ed8c5c7925..6fe3fda6d145 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -579,7 +579,7 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
/* if the buffer comes from another device */
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE) == 0) {
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage,
&shadow_plane_state->fmtcnv_state);
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index f492a59edbeb..28f26234523d 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -209,7 +209,6 @@ EXPORT_SYMBOL(drm_atomic_helper_dirtyfb);
/**
* drm_atomic_helper_damage_iter_init - Initialize the damage iterator.
* @iter: The iterator to initialize.
- * @old_state: Unused, pass NULL.
* @state: Plane state from which to iterate the damage clips.
*
* Initialize an iterator, which clips plane damage
@@ -226,7 +225,6 @@ EXPORT_SYMBOL(drm_atomic_helper_dirtyfb);
*/
void
drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
- const struct drm_plane_state *old_state,
const struct drm_plane_state *state)
{
struct drm_rect src;
@@ -324,7 +322,7 @@ bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
rect->x2 = 0;
rect->y2 = 0;
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
rect->x1 = min(rect->x1, clip.x1);
rect->y1 = min(rect->y1, clip.y1);
diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c
index fd71969d2fb1..bbad16d32b6f 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -138,7 +138,7 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
continue;
daddr = drm_fb_dma_get_gem_addr(state->fb, state, i);
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
/* Ignore x1/x2 values, invalidate complete lines */
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index 5ef887d8485a..758990cd78aa 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -618,7 +618,6 @@ void gud_plane_atomic_update(struct drm_plane *plane,
{
struct drm_device *drm = plane->dev;
struct gud_device *gdrm = to_gud_device(drm);
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(atomic_state, plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(atomic_state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
struct drm_framebuffer *fb = new_state->fb;
@@ -647,7 +646,7 @@ void gud_plane_atomic_update(struct drm_plane *plane,
if (ret)
goto out;
- drm_atomic_helper_damage_iter_init(&iter, old_state, new_state);
+ drm_atomic_helper_damage_iter_init(&iter, new_state);
drm_atomic_for_each_plane_damage(&iter, &damage)
gud_fb_handle_damage(gdrm, fb, &shadow_plane_state->data[0], &damage);
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
index 1bbb7de5ab49..9f74365c4d7e 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
@@ -171,14 +171,13 @@ static void hyperv_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct hyperv_drm_device *hv = to_hv(plane->dev);
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
struct drm_rect damage;
struct drm_rect dst_clip;
struct drm_atomic_helper_damage_iter iter;
- drm_atomic_helper_damage_iter_init(&iter, old_state, new_state);
+ drm_atomic_helper_damage_iter_init(&iter, new_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = new_state->dst;
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 7e07fc3f1a60..ea121428adf2 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -503,14 +503,13 @@ void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_device *dev = plane->dev;
struct mga_device *mdev = to_mga_device(dev);
struct drm_plane_state *plane_state = plane->state;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
struct drm_atomic_helper_damage_iter iter;
struct drm_rect damage;
mgag200_set_datasiz(mdev, fb->format->format);
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
}
diff --git a/drivers/gpu/drm/sitronix/st7571.c b/drivers/gpu/drm/sitronix/st7571.c
index 20954c33eca9..bc0e59c2600c 100644
--- a/drivers/gpu/drm/sitronix/st7571.c
+++ b/drivers/gpu/drm/sitronix/st7571.c
@@ -342,7 +342,6 @@ static int st7571_primary_plane_helper_atomic_check(struct drm_plane *plane,
static void st7571_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
@@ -362,7 +361,7 @@ static void st7571_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (!drm_dev_enter(drm, &idx))
goto out_drm_gem_fb_end_cpu_access;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
st7571->pformat->prepare_buffer(st7571,
&shadow_plane_state->data[0],
diff --git a/drivers/gpu/drm/sitronix/st7920.c b/drivers/gpu/drm/sitronix/st7920.c
index d320391801f3..7ee45a2b2d3e 100644
--- a/drivers/gpu/drm/sitronix/st7920.c
+++ b/drivers/gpu/drm/sitronix/st7920.c
@@ -390,7 +390,6 @@ static void st7920_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct st7920_crtc_state *st7920_crtc_state = to_st7920_crtc_state(crtc_state);
@@ -407,7 +406,7 @@ static void st7920_primary_plane_atomic_update(struct drm_plane *plane,
return;
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE) == 0) {
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = plane_state->dst;
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index cae92a3ae8a4..4b55532da31b 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -1198,7 +1198,6 @@ static void ssd130x_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
@@ -1216,7 +1215,7 @@ static void ssd130x_primary_plane_atomic_update(struct drm_plane *plane,
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
goto out_drm_dev_exit;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = plane_state->dst;
@@ -1239,7 +1238,6 @@ static void ssd132x_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
@@ -1257,7 +1255,7 @@ static void ssd132x_primary_plane_atomic_update(struct drm_plane *plane,
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
goto out_drm_dev_exit;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = plane_state->dst;
@@ -1280,7 +1278,6 @@ static void ssd133x_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
@@ -1297,7 +1294,7 @@ static void ssd133x_primary_plane_atomic_update(struct drm_plane *plane,
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
goto out_drm_dev_exit;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = plane_state->dst;
diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
index d2de29caf89e..9f1ae5ca9a11 100644
--- a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
+++ b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
@@ -331,7 +331,6 @@ void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, struct drm_at
struct drm_device *dev = plane->dev;
struct drm_sysfb_device *sysfb = to_drm_sysfb_device(dev);
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_sysfb_plane_state *sysfb_plane_state = to_drm_sysfb_plane_state(plane_state);
struct drm_shadow_plane_state *shadow_plane_state = &sysfb_plane_state->base;
struct drm_framebuffer *fb = plane_state->fb;
@@ -351,7 +350,7 @@ void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, struct drm_at
if (!drm_dev_enter(dev, &idx))
goto out_drm_gem_fb_end_cpu_access;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
struct iosys_map dst = sysfb->fb_addr;
struct drm_rect dst_clip = plane_state->dst;
diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c
index ef931497baf9..2139ec8b0eb0 100644
--- a/drivers/gpu/drm/tests/drm_damage_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c
@@ -20,7 +20,6 @@ struct drm_damage_mock {
struct drm_property prop;
struct drm_framebuffer fb;
struct drm_plane_state state;
- struct drm_plane_state old_state;
};
static int drm_damage_helper_init(struct kunit *test)
@@ -37,7 +36,6 @@ static int drm_damage_helper_init(struct kunit *test)
mock->state.fb = &mock->fb;
mock->state.visible = true;
- mock->old_state.plane = &mock->plane;
mock->state.plane = &mock->plane;
/* just enough so that drm_plane_enable_fb_damage_clips() works */
@@ -124,9 +122,8 @@ static void drm_test_damage_iter_no_damage(struct kunit *test)
u32 num_hits = 0;
/* Plane src same as fb size. */
- set_plane_src(&mock->old_state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
set_plane_src(&mock->state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -142,11 +139,9 @@ static void drm_test_damage_iter_no_damage_fractional_src(struct kunit *test)
u32 num_hits = 0;
/* Plane src has fractional part. */
- set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
- 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -164,9 +159,8 @@ static void drm_test_damage_iter_no_damage_not_visible(struct kunit *test)
mock->state.visible = false;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -182,9 +176,8 @@ static void drm_test_damage_iter_no_damage_no_crtc(struct kunit *test)
mock->state.crtc = NULL;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -200,9 +193,8 @@ static void drm_test_damage_iter_no_damage_no_fb(struct kunit *test)
mock->state.fb = NULL;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -218,13 +210,12 @@ static void drm_test_damage_iter_simple_damage(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* Damage set to plane src */
set_damage_clip(&damage, 0, 0, 1024, 768);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -241,12 +232,11 @@ static void drm_test_damage_iter_single_damage(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
set_damage_clip(&damage, 256, 192, 768, 576);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -263,13 +253,12 @@ static void drm_test_damage_iter_single_damage_intersect_src(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* Damage intersect with plane src. */
set_damage_clip(&damage, 256, 192, 1360, 768);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -286,13 +275,12 @@ static void drm_test_damage_iter_single_damage_outside_src(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* Damage clip outside plane src */
set_damage_clip(&damage, 1360, 1360, 1380, 1380);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -309,14 +297,12 @@ static void drm_test_damage_iter_single_damage_fractional_src(struct kunit *test
u32 num_hits = 0;
/* Plane src has fractional part. */
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_plane_src(&mock->state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_damage_clip(&damage, 10, 10, 256, 330);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -334,15 +320,13 @@ static void drm_test_damage_iter_single_damage_intersect_fractional_src(struct k
u32 num_hits = 0;
/* Plane src has fractional part. */
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_plane_src(&mock->state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
/* Damage intersect with plane src. */
set_damage_clip(&damage, 10, 1, 1360, 330);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -361,15 +345,13 @@ static void drm_test_damage_iter_single_damage_outside_fractional_src(struct kun
u32 num_hits = 0;
/* Plane src has fractional part. */
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_plane_src(&mock->state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
/* Damage clip outside plane src */
set_damage_clip(&damage, 1360, 1360, 1380, 1380);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -385,14 +367,13 @@ static void drm_test_damage_iter_damage(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* 2 damage clips. */
set_damage_clip(&damage[0], 20, 30, 200, 180);
set_damage_clip(&damage[1], 240, 200, 280, 250);
set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
if (num_hits == 0)
check_damage_clip(test, &clip, 20, 30, 200, 180);
@@ -413,8 +394,6 @@ static void drm_test_damage_iter_damage_one_intersect(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_plane_src(&mock->state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
/* 2 damage clips, one intersect plane src. */
@@ -422,7 +401,7 @@ static void drm_test_damage_iter_damage_one_intersect(struct kunit *test)
set_damage_clip(&damage[1], 2, 2, 1360, 1360);
set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
if (num_hits == 0)
check_damage_clip(test, &clip, 20, 30, 200, 180);
@@ -443,14 +422,13 @@ static void drm_test_damage_iter_damage_one_outside(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* 2 damage clips, one outside plane src. */
set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
set_damage_clip(&damage[1], 240, 200, 280, 250);
set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -467,7 +445,6 @@ static void drm_test_damage_iter_damage_ignore(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* 2 damage clips, but ignore them. */
set_damage_clip(&damage[0], 20, 30, 200, 180);
@@ -475,7 +452,7 @@ static void drm_test_damage_iter_damage_ignore(struct kunit *test)
set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
mock->state.ignore_damage_clips = true;
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
if (num_hits == 0)
check_damage_clip(test, &clip, 0, 0, 1024, 768);
diff --git a/drivers/gpu/drm/tiny/appletbdrm.c b/drivers/gpu/drm/tiny/appletbdrm.c
index b683dcb35b0b..eadc3aed7277 100644
--- a/drivers/gpu/drm/tiny/appletbdrm.c
+++ b/drivers/gpu/drm/tiny/appletbdrm.c
@@ -324,7 +324,7 @@ static int appletbdrm_primary_plane_helper_begin_fb_access(struct drm_plane *pla
struct drm_rect damage;
size_t request_size;
- drm_atomic_helper_damage_iter_init(&iter, NULL, new_plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, new_plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage));
}
@@ -376,7 +376,6 @@ static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
}
static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
- struct drm_plane_state *old_state,
struct drm_plane_state *state)
{
struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(state);
@@ -412,7 +411,7 @@ static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
frame = (struct appletbdrm_frame *)request->data;
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
struct drm_rect dst_clip = state->dst;
struct iosys_map dst = IOSYS_MAP_INIT_VADDR(frame->buf);
@@ -479,13 +478,12 @@ static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane *plan
struct appletbdrm_device *adev = drm_to_adev(plane->dev);
struct drm_device *drm = plane->dev;
struct drm_plane_state *plane_state = plane->state;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane);
int idx;
if (!drm_dev_enter(drm, &idx))
return;
- appletbdrm_flush_damage(adev, old_plane_state, plane_state);
+ appletbdrm_flush_damage(adev, plane_state);
drm_dev_exit(idx);
}
diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c
index e2d957e51505..1e19e98694c0 100644
--- a/drivers/gpu/drm/tiny/bochs.c
+++ b/drivers/gpu/drm/tiny/bochs.c
@@ -447,7 +447,6 @@ static void bochs_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_device *dev = plane->dev;
struct bochs_device *bochs = to_bochs_device(dev);
struct drm_plane_state *plane_state = plane->state;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
struct drm_atomic_helper_damage_iter iter;
@@ -456,7 +455,7 @@ static void bochs_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (!fb || !bochs->stride)
return;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(bochs->fb_map);
diff --git a/drivers/gpu/drm/tiny/cirrus-qemu.c b/drivers/gpu/drm/tiny/cirrus-qemu.c
index 075221b431d3..44ffce563e51 100644
--- a/drivers/gpu/drm/tiny/cirrus-qemu.c
+++ b/drivers/gpu/drm/tiny/cirrus-qemu.c
@@ -350,7 +350,7 @@ static void cirrus_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (!old_fb || old_fb->pitches[0] != fb->pitches[0])
cirrus_pitch_set(cirrus, fb->pitches[0]);
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
unsigned int offset = drm_fb_clip_offset(fb->pitches[0], fb->format, &damage);
struct iosys_map dst = IOSYS_MAP_INIT_OFFSET(&vaddr, offset);
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 289711035b67..ac981ffca5d9 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -286,7 +286,6 @@ static void udl_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_atomic_helper_damage_iter iter;
struct drm_rect damage;
int ret, idx;
@@ -301,7 +300,7 @@ static void udl_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (!drm_dev_enter(dev, &idx))
goto out_drm_gem_fb_end_cpu_access;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
udl_handle_damage(fb, &shadow_plane_state->data[0], &damage);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 1b407b61f683..32617eb9538e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1733,7 +1733,6 @@ void vmw_kms_lost_device(struct drm_device *dev)
int vmw_du_helper_plane_update(struct vmw_du_update_plane *update)
{
struct drm_plane_state *state = update->plane->state;
- struct drm_plane_state *old_state = update->old_state;
struct drm_atomic_helper_damage_iter iter;
struct drm_rect clip;
struct drm_rect bb;
@@ -1750,7 +1749,7 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update)
* Iterate in advance to check if really need plane update and find the
* number of clips that actually are in plane src for fifo allocation.
*/
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -1818,7 +1817,7 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update)
bb.x2 = INT_MIN;
bb.y2 = INT_MIN;
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
uint32_t fb_x = clip.x1;
uint32_t fb_y = clip.y1;
diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h
index e93eaa0fbcb6..fafe29b50fc6 100644
--- a/include/drm/drm_damage_helper.h
+++ b/include/drm/drm_damage_helper.h
@@ -73,8 +73,7 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
unsigned int num_clips);
void
drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
- const struct drm_plane_state *old_state,
- const struct drm_plane_state *new_state);
+ const struct drm_plane_state *state);
bool
drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
struct drm_rect *rect);
--
2.54.0
^ permalink raw reply related
* [PATCH v3 10/10] drm/vmwgfx: Remove unused field struct vmwgfx_du_update_plane.old_state
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Plane updates no longer require the old plane state. Remove the field
from struct vmwgfx_du_update_plane and fix all callers.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 --
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 12 ++----------
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 11 ++---------
3 files changed, 4 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 2224d7d91d1b..8c2072b82062 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -19,7 +19,6 @@
/**
* struct vmw_du_update_plane - Closure structure for vmw_du_helper_plane_update
* @plane: Plane which is being updated.
- * @old_state: Old state of plane.
* @dev_priv: Device private.
* @du: Display unit on which to update the plane.
* @vfb: Framebuffer which is blitted to display unit.
@@ -102,7 +101,6 @@ struct vmw_du_update_plane {
struct drm_rect *bb);
struct drm_plane *plane;
- struct drm_plane_state *old_state;
struct vmw_private *dev_priv;
struct vmw_display_unit *du;
struct vmw_framebuffer *vfb;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index c83061cf7455..fa84bc7ab5bb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -530,7 +530,6 @@ static uint32_t vmw_stud_bo_post_clip(struct vmw_du_update_plane *update,
*/
static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv,
struct drm_plane *plane,
- struct drm_plane_state *old_state,
struct vmw_framebuffer *vfb,
struct vmw_fence_obj **out_fence)
{
@@ -538,7 +537,6 @@ static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv,
memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
bo_update.base.plane = plane;
- bo_update.base.old_state = old_state;
bo_update.base.dev_priv = dev_priv;
bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
bo_update.base.vfb = vfb;
@@ -692,7 +690,6 @@ static uint32_t vmw_sou_surface_post_clip(struct vmw_du_update_plane *update,
*/
static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv,
struct drm_plane *plane,
- struct drm_plane_state *old_state,
struct vmw_framebuffer *vfb,
struct vmw_fence_obj **out_fence)
{
@@ -700,7 +697,6 @@ static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv,
memset(&srf_update, 0, sizeof(struct vmw_du_update_plane_surface));
srf_update.base.plane = plane;
- srf_update.base.old_state = old_state;
srf_update.base.dev_priv = dev_priv;
srf_update.base.du = vmw_crtc_to_du(plane->state->crtc);
srf_update.base.vfb = vfb;
@@ -721,7 +717,6 @@ static void
vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_crtc *crtc = new_state->crtc;
struct vmw_fence_obj *fence = NULL;
@@ -734,12 +729,9 @@ vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
vmw_framebuffer_to_vfb(new_state->fb);
if (vfb->bo)
- ret = vmw_sou_plane_update_bo(dev_priv, plane,
- old_state, vfb, &fence);
+ ret = vmw_sou_plane_update_bo(dev_priv, plane, vfb, &fence);
else
- ret = vmw_sou_plane_update_surface(dev_priv, plane,
- old_state, vfb,
- &fence);
+ ret = vmw_sou_plane_update_surface(dev_priv, plane, vfb, &fence);
if (ret != 0)
DRM_ERROR("Failed to update screen.\n");
} else {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index f0df2b1c8465..474e3badb80f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1240,7 +1240,6 @@ vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane *update, void *cmd,
*/
static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv,
struct drm_plane *plane,
- struct drm_plane_state *old_state,
struct vmw_framebuffer *vfb,
struct vmw_fence_obj **out_fence)
{
@@ -1248,7 +1247,6 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv,
memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
bo_update.base.plane = plane;
- bo_update.base.old_state = old_state;
bo_update.base.dev_priv = dev_priv;
bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
bo_update.base.vfb = vfb;
@@ -1350,7 +1348,6 @@ vmw_stdu_surface_populate_update(struct vmw_du_update_plane *update, void *cmd,
*/
static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv,
struct drm_plane *plane,
- struct drm_plane_state *old_state,
struct vmw_framebuffer *vfb,
struct vmw_fence_obj **out_fence)
{
@@ -1363,7 +1360,6 @@ static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv,
memset(&srf_update, 0, sizeof(struct vmw_du_update_plane));
srf_update.plane = plane;
- srf_update.old_state = old_state;
srf_update.dev_priv = dev_priv;
srf_update.du = vmw_crtc_to_du(plane->state->crtc);
srf_update.vfb = vfb;
@@ -1424,12 +1420,9 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
DRM_ERROR("Failed to bind surface to STDU.\n");
if (vfb->bo)
- ret = vmw_stdu_plane_update_bo(dev_priv, plane,
- old_state, vfb, &fence);
+ ret = vmw_stdu_plane_update_bo(dev_priv, plane, vfb, &fence);
else
- ret = vmw_stdu_plane_update_surface(dev_priv, plane,
- old_state, vfb,
- &fence);
+ ret = vmw_stdu_plane_update_surface(dev_priv, plane, vfb, &fence);
if (ret)
DRM_ERROR("Failed to update STDU.\n");
} else {
--
2.54.0
^ permalink raw reply related
* [PATCH v3 05/10] drm/appletbdrm: Allocate request/response buffers in begin_fb_access
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
In atomic_check, damage handling is not fully evaluated. Another
atomic_check helper could trigger a full modeset and thus invalidate
damage clips.
Allocation of the request/response buffers in appletbdrm depends on
correct damage information. Otherwise it might allocate incorrectly
sized buffers. Allocate the buffers in the driver's begin_fb_access
helper. It runs early during the commit when damage clipping has been
fully evaluated.
v2:
- allocate before drm_gem_begin_shadow_fb_access() to avoid leak on error
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Aditya Garg <gargaditya08@proton.me>
---
drivers/gpu/drm/tiny/appletbdrm.c | 53 +++++++++++++++++--------------
1 file changed, 30 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/tiny/appletbdrm.c b/drivers/gpu/drm/tiny/appletbdrm.c
index cdd35af49892..b683dcb35b0b 100644
--- a/drivers/gpu/drm/tiny/appletbdrm.c
+++ b/drivers/gpu/drm/tiny/appletbdrm.c
@@ -315,33 +315,16 @@ static const u32 appletbdrm_primary_plane_formats[] = {
DRM_FORMAT_XRGB8888, /* emulated */
};
-static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
- struct drm_atomic_commit *state)
+static int appletbdrm_primary_plane_helper_begin_fb_access(struct drm_plane *plane,
+ struct drm_plane_state *new_plane_state)
{
- struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
- struct drm_crtc *new_crtc = new_plane_state->crtc;
- struct drm_crtc_state *new_crtc_state = NULL;
struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(new_plane_state);
+ size_t frames_size = 0;
struct drm_atomic_helper_damage_iter iter;
struct drm_rect damage;
- size_t frames_size = 0;
size_t request_size;
- int ret;
-
- if (new_crtc)
- new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
- ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
- DRM_PLANE_NO_SCALING,
- DRM_PLANE_NO_SCALING,
- false, false);
- if (ret)
- return ret;
- else if (!new_plane_state->visible)
- return 0;
-
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, new_plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, NULL, new_plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage));
}
@@ -366,6 +349,29 @@ static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
appletbdrm_state->request_size = request_size;
appletbdrm_state->frames_size = frames_size;
+ return drm_gem_begin_shadow_fb_access(plane, new_plane_state);
+}
+
+static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
+ struct drm_atomic_commit *state)
+{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_crtc *new_crtc = new_plane_state->crtc;
+ struct drm_crtc_state *new_crtc_state = NULL;
+ int ret;
+
+ if (new_crtc)
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
+
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ false, false);
+ if (ret)
+ return ret;
+ else if (!new_plane_state->visible)
+ return 0;
+
return 0;
}
@@ -468,7 +474,7 @@ static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
}
static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
- struct drm_atomic_commit *old_state)
+ struct drm_atomic_commit *old_state)
{
struct appletbdrm_device *adev = drm_to_adev(plane->dev);
struct drm_device *drm = plane->dev;
@@ -552,7 +558,8 @@ static void appletbdrm_primary_plane_destroy_state(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs appletbdrm_primary_plane_helper_funcs = {
- DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+ .begin_fb_access = appletbdrm_primary_plane_helper_begin_fb_access,
+ .end_fb_access = drm_gem_end_shadow_fb_access,
.atomic_check = appletbdrm_primary_plane_helper_atomic_check,
.atomic_update = appletbdrm_primary_plane_helper_atomic_update,
.atomic_disable = appletbdrm_primary_plane_helper_atomic_disable,
--
2.54.0
^ permalink raw reply related
* [PATCH v3 09/10] drm/damage-helper: Rename state parameters in damage helpers
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Rename some of the state parameters of the damage-helper functions to
align them with each other and other helpers. No functional changes.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_damage_helper.c | 20 ++++++++++----------
include/drm/drm_damage_helper.h | 4 ++--
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index 28b847636253..23701e5c51b7 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -209,7 +209,7 @@ EXPORT_SYMBOL(drm_atomic_helper_dirtyfb);
/**
* drm_atomic_helper_damage_iter_init - Initialize the damage iterator.
* @iter: The iterator to initialize.
- * @state: Plane state from which to iterate the damage clips.
+ * @plane_state: Plane state from which to iterate the damage clips.
*
* Initialize an iterator, which clips plane damage
* &drm_plane_state.fb_damage_clips to plane &drm_plane_state.src. This iterator
@@ -225,26 +225,26 @@ EXPORT_SYMBOL(drm_atomic_helper_dirtyfb);
*/
void
drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
- const struct drm_plane_state *state)
+ const struct drm_plane_state *plane_state)
{
struct drm_rect src;
memset(iter, 0, sizeof(*iter));
- if (!state || !state->crtc || !state->fb || !state->visible)
+ if (!plane_state || !plane_state->crtc || !plane_state->fb || !plane_state->visible)
return;
- iter->clips = (struct drm_rect *)drm_plane_get_damage_clips(state);
- iter->num_clips = drm_plane_get_damage_clips_count(state);
+ iter->clips = (struct drm_rect *)drm_plane_get_damage_clips(plane_state);
+ iter->num_clips = drm_plane_get_damage_clips_count(plane_state);
/* Round down for x1/y1 and round up for x2/y2 to catch all pixels */
- src = drm_plane_state_src(state);
+ src = drm_plane_state_src(plane_state);
iter->plane_src.x1 = src.x1 >> 16;
iter->plane_src.y1 = src.y1 >> 16;
iter->plane_src.x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF);
iter->plane_src.y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF);
- if (!iter->clips || state->ignore_damage_clips) {
+ if (!iter->clips || plane_state->ignore_damage_clips) {
iter->clips = NULL;
iter->num_clips = 0;
iter->full_update = true;
@@ -296,7 +296,7 @@ EXPORT_SYMBOL(drm_atomic_helper_damage_iter_next);
/**
* drm_atomic_helper_damage_merged - Merged plane damage
- * @state: Plane state from which to iterate the damage clips.
+ * @plane_state: Plane state from which to iterate the damage clips.
* @rect: Returns the merged damage rectangle
*
* This function merges any valid plane damage clips into one rectangle and
@@ -308,7 +308,7 @@ EXPORT_SYMBOL(drm_atomic_helper_damage_iter_next);
* Returns:
* True if there is valid plane damage otherwise false.
*/
-bool drm_atomic_helper_damage_merged(const struct drm_plane_state *state,
+bool drm_atomic_helper_damage_merged(const struct drm_plane_state *plane_state,
struct drm_rect *rect)
{
struct drm_atomic_helper_damage_iter iter;
@@ -320,7 +320,7 @@ bool drm_atomic_helper_damage_merged(const struct drm_plane_state *state,
rect->x2 = 0;
rect->y2 = 0;
- drm_atomic_helper_damage_iter_init(&iter, state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
rect->x1 = min(rect->x1, clip.x1);
rect->y1 = min(rect->y1, clip.y1);
diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h
index b5a4de779db6..4a1ac47b9051 100644
--- a/include/drm/drm_damage_helper.h
+++ b/include/drm/drm_damage_helper.h
@@ -73,11 +73,11 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
unsigned int num_clips);
void
drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
- const struct drm_plane_state *state);
+ const struct drm_plane_state *plane_state);
bool
drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
struct drm_rect *rect);
-bool drm_atomic_helper_damage_merged(const struct drm_plane_state *state,
+bool drm_atomic_helper_damage_merged(const struct drm_plane_state *plane_state,
struct drm_rect *rect);
#endif
--
2.54.0
^ permalink raw reply related
* [PATCH v3 03/10] drm/ingenic: Remove calls to drm_atomic_helper_check_plane_damage()
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Atomic helpers call drm_atomic_helper_check_plane_damage() after the
atomic_check anyway. See atomic_helper_check_planes(). Remove the calls
from the planes' atomic_check.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 3 ---
drivers/gpu/drm/ingenic/ingenic-ipu.c | 8 ++------
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 42c86f195c66..e99b44e3ac92 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -519,9 +519,6 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane,
old_plane_state->fb->format->format != new_plane_state->fb->format->format))
crtc_state->mode_changed = true;
- if (priv->soc_info->map_noncoherent)
- drm_atomic_helper_check_plane_damage(state, new_plane_state);
-
return 0;
}
diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c
index 56143a191f36..fd17c642c7ac 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -594,7 +594,7 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane,
if (!new_plane_state->crtc ||
!crtc_state->mode.hdisplay || !crtc_state->mode.vdisplay)
- goto out_check_damage;
+ return 0;
/* Plane must be fully visible */
if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0 ||
@@ -611,7 +611,7 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
if (!osd_changed(new_plane_state, old_plane_state))
- goto out_check_damage;
+ return 0;
crtc_state->mode_changed = true;
@@ -645,10 +645,6 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane,
ipu_state->denom_w = denom_w;
ipu_state->denom_h = denom_h;
-out_check_damage:
- if (ingenic_drm_map_noncoherent(ipu->master))
- drm_atomic_helper_check_plane_damage(state, new_plane_state);
-
return 0;
}
--
2.54.0
^ permalink raw reply related
* [PATCH v3 04/10] drm/damage-helper: Test src coord in drm_atomic_helper_check_plane_damage()
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Planes require a full update if the source coordinates change across
atomic commits. Evaluate this during the atomic-check and set the flag
ignore_damage_clips in the plane state, if so. Remove the check from
drm_atomic_helper_damage_iter_init().
This will help with removing the old state from the atomic-commit phase
and simplify atomic_update helpers a bit.
Several unit tests check against the change of the src coordinate. Drop
them as they do no longer make sense. If the src coordinate changes across
commits, atomic helpers will set the plane state's ignore_damage_clips
flag, for which a separate unit test exists.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_atomic_helper.c | 4 +-
drivers/gpu/drm/drm_damage_helper.c | 20 ++-
.../gpu/drm/tests/drm_damage_helper_test.c | 151 ------------------
include/drm/drm_damage_helper.h | 3 +-
4 files changed, 16 insertions(+), 162 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 4c37299e8ccb..823ce60d45b4 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1034,7 +1034,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane);
- drm_atomic_helper_check_plane_damage(state, new_plane_state);
+ drm_atomic_helper_check_plane_damage(state, old_plane_state, new_plane_state);
if (!funcs || !funcs->atomic_check)
continue;
@@ -1066,7 +1066,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
}
for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
- drm_atomic_helper_check_plane_damage(state, new_plane_state);
+ drm_atomic_helper_check_plane_damage(state, old_plane_state, new_plane_state);
}
return ret;
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index 945fac8dc27b..f492a59edbeb 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -55,7 +55,8 @@ static void convert_clip_rect_to_rect(const struct drm_clip_rect *src,
/**
* drm_atomic_helper_check_plane_damage - Verify plane damage on atomic_check.
* @state: The driver state object.
- * @plane_state: Plane state for which to verify damage.
+ * @old_plane_state: Old plane state to verify against.
+ * @new_plane_state: Plane state for which to verify damage.
*
* This helper function makes sure that damage from plane state is discarded
* for full modeset. If there are more reasons a driver would want to do a full
@@ -67,19 +68,23 @@ static void convert_clip_rect_to_rect(const struct drm_clip_rect *src,
* &drm_plane_state.src as damage.
*/
void drm_atomic_helper_check_plane_damage(struct drm_atomic_commit *state,
- struct drm_plane_state *plane_state)
+ const struct drm_plane_state *old_plane_state,
+ struct drm_plane_state *new_plane_state)
{
struct drm_crtc_state *crtc_state;
- if (plane_state->crtc) {
+ if (!drm_rect_equals(&new_plane_state->src, &old_plane_state->src))
+ new_plane_state->ignore_damage_clips = true;
+
+ if (new_plane_state->crtc) {
crtc_state = drm_atomic_get_new_crtc_state(state,
- plane_state->crtc);
+ new_plane_state->crtc);
if (WARN_ON(!crtc_state))
return;
if (drm_atomic_crtc_needs_modeset(crtc_state))
- plane_state->ignore_damage_clips = true;
+ new_plane_state->ignore_damage_clips = true;
}
}
EXPORT_SYMBOL(drm_atomic_helper_check_plane_damage);
@@ -204,7 +209,7 @@ EXPORT_SYMBOL(drm_atomic_helper_dirtyfb);
/**
* drm_atomic_helper_damage_iter_init - Initialize the damage iterator.
* @iter: The iterator to initialize.
- * @old_state: Old plane state for validation.
+ * @old_state: Unused, pass NULL.
* @state: Plane state from which to iterate the damage clips.
*
* Initialize an iterator, which clips plane damage
@@ -241,8 +246,7 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
iter->plane_src.x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF);
iter->plane_src.y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF);
- if (!iter->clips || state->ignore_damage_clips ||
- !drm_rect_equals(&state->src, &old_state->src)) {
+ if (!iter->clips || state->ignore_damage_clips) {
iter->clips = NULL;
iter->num_clips = 0;
iter->full_update = true;
diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c
index 64f038a62ffe..ef931497baf9 100644
--- a/drivers/gpu/drm/tests/drm_damage_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c
@@ -155,45 +155,6 @@ static void drm_test_damage_iter_no_damage_fractional_src(struct kunit *test)
check_damage_clip(test, &clip, 3, 3, 1028, 772);
}
-static void drm_test_damage_iter_no_damage_src_moved(struct kunit *test)
-{
- struct drm_damage_mock *mock = test->priv;
- struct drm_atomic_helper_damage_iter iter;
- struct drm_rect clip;
- u32 num_hits = 0;
-
- /* Plane src moved since old plane state. */
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
- set_plane_src(&mock->state, 10 << 16, 10 << 16,
- (10 + 1024) << 16, (10 + 768) << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
- drm_atomic_for_each_plane_damage(&iter, &clip)
- num_hits++;
-
- KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
- check_damage_clip(test, &clip, 10, 10, 1034, 778);
-}
-
-static void drm_test_damage_iter_no_damage_fractional_src_moved(struct kunit *test)
-{
- struct drm_damage_mock *mock = test->priv;
- struct drm_atomic_helper_damage_iter iter;
- struct drm_rect clip;
- u32 num_hits = 0;
-
- /* Plane src has fractional part and it moved since old plane state. */
- set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
- 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
- set_plane_src(&mock->state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
- drm_atomic_for_each_plane_damage(&iter, &clip)
- num_hits++;
-
- KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
- check_damage_clip(test, &clip, 4, 4, 1029, 773);
-}
-
static void drm_test_damage_iter_no_damage_not_visible(struct kunit *test)
{
struct drm_damage_mock *mock = test->priv;
@@ -415,58 +376,6 @@ static void drm_test_damage_iter_single_damage_outside_fractional_src(struct kun
KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
}
-static void drm_test_damage_iter_single_damage_src_moved(struct kunit *test)
-{
- struct drm_damage_mock *mock = test->priv;
- struct drm_atomic_helper_damage_iter iter;
- struct drm_property_blob damage_blob;
- struct drm_mode_rect damage;
- struct drm_rect clip;
- u32 num_hits = 0;
-
- /* Plane src moved since old plane state. */
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
- set_plane_src(&mock->state, 10 << 16, 10 << 16,
- (10 + 1024) << 16, (10 + 768) << 16);
- set_damage_clip(&damage, 20, 30, 256, 256);
- set_damage_blob(&damage_blob, &damage, sizeof(damage));
- set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
- drm_atomic_for_each_plane_damage(&iter, &clip)
- num_hits++;
-
- KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
- "Should return plane src as damage.");
- check_damage_clip(test, &clip, 10, 10, 1034, 778);
-}
-
-static void drm_test_damage_iter_single_damage_fractional_src_moved(struct kunit *test)
-{
- struct drm_damage_mock *mock = test->priv;
- struct drm_atomic_helper_damage_iter iter;
- struct drm_property_blob damage_blob;
- struct drm_mode_rect damage;
- struct drm_rect clip;
- u32 num_hits = 0;
-
- /* Plane src with fractional part moved since old plane state. */
- set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
- 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
- set_plane_src(&mock->state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
- /* Damage intersect with plane src. */
- set_damage_clip(&damage, 20, 30, 1360, 256);
- set_damage_blob(&damage_blob, &damage, sizeof(damage));
- set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
- drm_atomic_for_each_plane_damage(&iter, &clip)
- num_hits++;
-
- KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
- "Should return rounded off plane as damage.");
- check_damage_clip(test, &clip, 4, 4, 1029, 773);
-}
-
static void drm_test_damage_iter_damage(struct kunit *test)
{
struct drm_damage_mock *mock = test->priv;
@@ -549,60 +458,6 @@ static void drm_test_damage_iter_damage_one_outside(struct kunit *test)
check_damage_clip(test, &clip, 240, 200, 280, 250);
}
-static void drm_test_damage_iter_damage_src_moved(struct kunit *test)
-{
- struct drm_damage_mock *mock = test->priv;
- struct drm_atomic_helper_damage_iter iter;
- struct drm_property_blob damage_blob;
- struct drm_mode_rect damage[2];
- struct drm_rect clip;
- u32 num_hits = 0;
-
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
- set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
- 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
- /* 2 damage clips, one outside plane src. */
- set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
- set_damage_clip(&damage[1], 240, 200, 280, 250);
- set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
- set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
- drm_atomic_for_each_plane_damage(&iter, &clip)
- num_hits++;
-
- KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
- "Should return round off plane src as damage.");
- check_damage_clip(test, &clip, 3, 3, 1028, 772);
-}
-
-static void drm_test_damage_iter_damage_not_visible(struct kunit *test)
-{
- struct drm_damage_mock *mock = test->priv;
- struct drm_atomic_helper_damage_iter iter;
- struct drm_property_blob damage_blob;
- struct drm_mode_rect damage[2];
- struct drm_rect clip;
- u32 num_hits = 0;
-
- mock->state.visible = false;
-
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
- set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
- 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
- /* 2 damage clips, one outside plane src. */
- set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
- set_damage_clip(&damage[1], 240, 200, 280, 250);
- set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
- set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
- drm_atomic_for_each_plane_damage(&iter, &clip)
- num_hits++;
-
- KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should not return any damage.");
-}
-
static void drm_test_damage_iter_damage_ignore(struct kunit *test)
{
struct drm_damage_mock *mock = test->priv;
@@ -633,8 +488,6 @@ static void drm_test_damage_iter_damage_ignore(struct kunit *test)
static struct kunit_case drm_damage_helper_tests[] = {
KUNIT_CASE(drm_test_damage_iter_no_damage),
KUNIT_CASE(drm_test_damage_iter_no_damage_fractional_src),
- KUNIT_CASE(drm_test_damage_iter_no_damage_src_moved),
- KUNIT_CASE(drm_test_damage_iter_no_damage_fractional_src_moved),
KUNIT_CASE(drm_test_damage_iter_no_damage_not_visible),
KUNIT_CASE(drm_test_damage_iter_no_damage_no_crtc),
KUNIT_CASE(drm_test_damage_iter_no_damage_no_fb),
@@ -645,13 +498,9 @@ static struct kunit_case drm_damage_helper_tests[] = {
KUNIT_CASE(drm_test_damage_iter_single_damage_fractional_src),
KUNIT_CASE(drm_test_damage_iter_single_damage_intersect_fractional_src),
KUNIT_CASE(drm_test_damage_iter_single_damage_outside_fractional_src),
- KUNIT_CASE(drm_test_damage_iter_single_damage_src_moved),
- KUNIT_CASE(drm_test_damage_iter_single_damage_fractional_src_moved),
KUNIT_CASE(drm_test_damage_iter_damage),
KUNIT_CASE(drm_test_damage_iter_damage_one_intersect),
KUNIT_CASE(drm_test_damage_iter_damage_one_outside),
- KUNIT_CASE(drm_test_damage_iter_damage_src_moved),
- KUNIT_CASE(drm_test_damage_iter_damage_not_visible),
KUNIT_CASE(drm_test_damage_iter_damage_ignore),
{ }
};
diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h
index 3661aeab2cd3..e93eaa0fbcb6 100644
--- a/include/drm/drm_damage_helper.h
+++ b/include/drm/drm_damage_helper.h
@@ -65,7 +65,8 @@ struct drm_atomic_helper_damage_iter {
};
void drm_atomic_helper_check_plane_damage(struct drm_atomic_commit *state,
- struct drm_plane_state *plane_state);
+ const struct drm_plane_state *old_plane_state,
+ struct drm_plane_state *new_plane_state);
int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
struct drm_file *file_priv, unsigned int flags,
unsigned int color, struct drm_clip_rect *clips,
--
2.54.0
^ permalink raw reply related
* [PATCH v3 02/10] drm/atomic-helpers: Evaluate plane damage after atomic_check
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
Each plane's and CRTC's atomic_check might trigger a full modeset. As
this affects the plane's damage handling, evaluate damage clips after
running the atomic_check helpers.
Examples can be found in a number of drivers, such as ast, gud, ingenic,
mgag200 or vmwgfx, which all set mode_changed in the CRTC state to true.
Ingenic even reevaluates damage information in its plane's atomic_check.
Doing this after the atomic_check helpers ran benefits all drivers.
There's already a damage evaluation before the calls to atomic_check.
With a few fixes to drivers, this can be removed.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_atomic_helper.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 51f39edc31ed..4c37299e8ccb 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1065,6 +1065,10 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
}
}
+ for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
+ drm_atomic_helper_check_plane_damage(state, new_plane_state);
+ }
+
return ret;
}
EXPORT_SYMBOL(drm_atomic_helper_check_planes);
--
2.54.0
^ permalink raw reply related
* [PATCH v3 01/10] drm/damage-helper: Do not alter damage clips on modeset, but ignore them
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann, stable
In-Reply-To: <20260527145113.241595-1-tzimmermann@suse.de>
User space supplies rectangles for damage clipping in a plane property.
For full mode sets, we still require a full plane update. In this case,
leave the information as-is and set the ignore_damage_clips flag instead.
The damage iterator will later ignore any damage information.
Also fixes a bug where ignore_damage_clips was not cleared across plane
duplications.
Leaving the damage information as-is might be helpful to drivers that
benefit from it even on full modesets (e.g., for cache management). It
will also help with consolidating the damage-handling logic.
Also add a new unit test that evaluates the ignore_damage_clips flag. It
sets two damage clips plus the flag and tests if the reported damage
covers the entire framebuffer.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers to ignore damage clips")
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v6.10+
---
drivers/gpu/drm/drm_atomic_state_helper.c | 1 +
drivers/gpu/drm/drm_damage_helper.c | 6 ++--
.../gpu/drm/tests/drm_damage_helper_test.c | 28 +++++++++++++++++++
3 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index cc70508d4fdb..84d5231ccac1 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -359,6 +359,7 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
state->fence = NULL;
state->commit = NULL;
state->fb_damage_clips = NULL;
+ state->ignore_damage_clips = false;
state->color_mgmt_changed = false;
}
EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index 74a7f4252ecf..945fac8dc27b 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -78,10 +78,8 @@ void drm_atomic_helper_check_plane_damage(struct drm_atomic_commit *state,
if (WARN_ON(!crtc_state))
return;
- if (drm_atomic_crtc_needs_modeset(crtc_state)) {
- drm_property_blob_put(plane_state->fb_damage_clips);
- plane_state->fb_damage_clips = NULL;
- }
+ if (drm_atomic_crtc_needs_modeset(crtc_state))
+ plane_state->ignore_damage_clips = true;
}
}
EXPORT_SYMBOL(drm_atomic_helper_check_plane_damage);
diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c
index 0df2e1a54b0d..64f038a62ffe 100644
--- a/drivers/gpu/drm/tests/drm_damage_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c
@@ -603,6 +603,33 @@ static void drm_test_damage_iter_damage_not_visible(struct kunit *test)
KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should not return any damage.");
}
+static void drm_test_damage_iter_damage_ignore(struct kunit *test)
+{
+ struct drm_damage_mock *mock = test->priv;
+ struct drm_atomic_helper_damage_iter iter;
+ struct drm_property_blob damage_blob;
+ struct drm_mode_rect damage[2];
+ struct drm_rect clip;
+ u32 num_hits = 0;
+
+ set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+ set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+ /* 2 damage clips, but ignore them. */
+ set_damage_clip(&damage[0], 20, 30, 200, 180);
+ set_damage_clip(&damage[1], 240, 200, 280, 250);
+ set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
+ set_plane_damage(&mock->state, &damage_blob);
+ mock->state.ignore_damage_clips = true;
+ drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_for_each_plane_damage(&iter, &clip) {
+ if (num_hits == 0)
+ check_damage_clip(test, &clip, 0, 0, 1024, 768);
+ num_hits++;
+ }
+
+ KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return full-framebuffer damage.");
+}
+
static struct kunit_case drm_damage_helper_tests[] = {
KUNIT_CASE(drm_test_damage_iter_no_damage),
KUNIT_CASE(drm_test_damage_iter_no_damage_fractional_src),
@@ -625,6 +652,7 @@ static struct kunit_case drm_damage_helper_tests[] = {
KUNIT_CASE(drm_test_damage_iter_damage_one_outside),
KUNIT_CASE(drm_test_damage_iter_damage_src_moved),
KUNIT_CASE(drm_test_damage_iter_damage_not_visible),
+ KUNIT_CASE(drm_test_damage_iter_damage_ignore),
{ }
};
--
2.54.0
^ permalink raw reply related
* [PATCH v3 00/10]
From: Thomas Zimmermann @ 2026-05-27 14:46 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklinux, zack.rusin,
bcm-kernel-feedback-list
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, Thomas Zimmermann
DRM clients can supply information on framebuffer areas to update as
part of each page flip, called damage clipping rectangles. But DRM's
processing of this information is inconsistent and prone to errors.
- There are multiple fields and tests that decide if damage clips
should be taken or ignored.
- Sometimes damage clips are removed behind the back of the DRM client.
- Atomic helpers evaluate damage clipping in the middle of the atomic
check: after connectors and encoders, but before planes and CRTCs. Hence
pipeline stages have an inconsistent view.
- Which leads to drivers (ingenic) doing a re-evaluation if necessary.
- Tests of plane source coordinates only happen during commits. At this
point, the driver should already know if damage clips are to be taken or
not. Because of this, some drivers (appletbdrm) might operate on incorrect
damage information for their internal workings. This also leads to excessive
use of the old plane state.
Therefore go through DRM helpers and drivers and fix the logic.
- Run all of the atomic checks with the damage information supplied by
DRM clients. Afterwards evaluate plane and CRTC states on whether to
take or ignore damage clips. Do all related tests in a single atomic
helper.
- Do not discard damage clips. Set ignore_damage_clips in struct
drm_plane_state instead. This includes changes to plane source-coordinates.
The damage iterator now only has to look at this flag to detect if it
should use the damage clips.
- Go over drivers and fix the damage handling in the plane's
atomic_update helpers. Most drivers no longer need the old plane state
in their update.
- The appletbdrm driver requires a fix in how it uses damage information.
Ingenic and vmwgfx can be simplified. These changes improve the drivers'
code organization.
- Kunit tests require some changes. Drop some obsolete tests and add a new
one for ignore_damage_flags.
Tested with bochs, mgag200, Kunit tests.
v3:
- fix error path in appletbdrm
v2:
- rebase on latest upstream
Thomas Zimmermann (10):
drm/damage-helper: Do not alter damage clips on modeset, but ignore
them
drm/atomic-helpers: Evaluate plane damage after atomic_check
drm/ingenic: Remove calls to drm_atomic_helper_check_plane_damage()
drm/damage-helper: Test src coord in
drm_atomic_helper_check_plane_damage()
drm/appletbdrm: Allocate request/response buffers in begin_fb_access
drm/damage-helper: Remove old state from
drm_atomic_helper_damage_iter_init()
drm/damage-helper: Remove old state from
drm_atomic_helper_damage_merged()
drm/atomic_helper: Do not evaluate plane damage before atomic_check
drm/damage-helper: Rename state parameters in damage helpers
drm/vmwgfx: Remove unused field struct
vmwgfx_du_update_plane.old_state
drivers/gpu/drm/ast/ast_cursor.c | 3 +-
drivers/gpu/drm/ast/ast_mode.c | 2 +-
drivers/gpu/drm/drm_atomic_helper.c | 6 +-
drivers/gpu/drm/drm_atomic_state_helper.c | 1 +
drivers/gpu/drm/drm_damage_helper.c | 44 ++--
drivers/gpu/drm/drm_fb_dma_helper.c | 2 +-
drivers/gpu/drm/drm_mipi_dbi.c | 3 +-
drivers/gpu/drm/gud/gud_pipe.c | 3 +-
drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 3 +-
drivers/gpu/drm/i915/display/intel_plane.c | 11 +-
drivers/gpu/drm/i915/display/intel_psr.c | 3 +-
drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 3 -
drivers/gpu/drm/ingenic/ingenic-ipu.c | 8 +-
drivers/gpu/drm/mgag200/mgag200_mode.c | 3 +-
drivers/gpu/drm/sitronix/st7571.c | 3 +-
drivers/gpu/drm/sitronix/st7586.c | 3 +-
drivers/gpu/drm/sitronix/st7920.c | 3 +-
drivers/gpu/drm/solomon/ssd130x.c | 9 +-
drivers/gpu/drm/sysfb/drm_sysfb_modeset.c | 3 +-
.../gpu/drm/tests/drm_damage_helper_test.c | 200 +++---------------
drivers/gpu/drm/tiny/appletbdrm.c | 59 +++---
drivers/gpu/drm/tiny/bochs.c | 3 +-
drivers/gpu/drm/tiny/cirrus-qemu.c | 2 +-
drivers/gpu/drm/tiny/gm12u320.c | 2 +-
drivers/gpu/drm/tiny/ili9225.c | 3 +-
drivers/gpu/drm/tiny/repaper.c | 2 +-
drivers/gpu/drm/tiny/sharp-memory.c | 3 +-
drivers/gpu/drm/udl/udl_modeset.c | 3 +-
drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 5 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 -
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 12 +-
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 15 +-
include/drm/drm_damage_helper.h | 9 +-
34 files changed, 123 insertions(+), 315 deletions(-)
base-commit: 5fb5a9a63cf5ece68e0eeb6fa397da27712bccf0
--
2.54.0
^ permalink raw reply
* Re: [PATCH 0/9] drm: Limit DRM_IOCTL_WAIT_VBLANK to vblank interrupts
From: Michel Dänzer @ 2026-05-27 14:04 UTC (permalink / raw)
To: Thomas Zimmermann, simona, airlied, pekka.paalanen, jadahl,
contact, maarten.lankhorst, mripard
Cc: amd-gfx, dri-devel, linux-hyperv, virtualization, spice-devel,
wayland-devel
In-Reply-To: <4a7c2f87-60fd-458c-a579-a36799b86557@suse.de>
On 5/27/26 15:07, Thomas Zimmermann wrote:
> Am 15.05.26 um 18:56 schrieb Michel Dänzer:
>> On 5/15/26 17:12, Michel Dänzer wrote:
>>> On 5/15/26 13:55, Thomas Zimmermann wrote:
>>>> DRM's WAIT_VBLANK ioctl synchronizes user-space clients to display
>>>> refresh. This is meaningless with vblank timers, which run unrelated
>>>> to the hardware's vblank.
>>>>
>>>> Disable the ioctl for simulated vblanks. Set DRM_VBLANK_FLAG_SIMULATED
>>>> for CRTCs with simulated vblank events in all such drivers. The vblank
>>>> timers of these devices still rate-limit the number of page-flip events
>>>> to match the display refresh.
>>>>
>>>> According to maintainers, user-space compositors do not require the ioctl
>>>> for rate-limitting display output. Weston and Kwin rely on page-flip
>>>> events. Mutter uses and internal timer to limit the number of display
>>>> updates per second.
>>> Actually mutter fundamentally relies on atomic commit completion events for that, same as Weston & KWin. Mutter uses the WAIT_VBLANK ioctl only for minimizing input → output latency (which can hide issues when completion of atomic commits isn't properly throttled).
>>>
>>>
>>> (Just a side not on the cover letter, no objections to the patches themselves)
>> After more discussion on IRC, I have some concerns.
>>
>>
>> The big one first: For drivers with no strict refresh cycle (i.e. an atomic commit can take effect more or less anytime after at least one "refresh cycle" has passed since the last one), does this change really make sense / what's the actual benefit?
>
> I don't have a strong opinion on that matter. I just think we should clarify the meaning of these ioctls.
>
> Timing page flip is currently not supported on any driver without hardware vblank IRQ or a vblank timer. The situation might vary among compositors, but there have been plenty of reports of animation and frame rates either being too high or too low.
As discussed on IRC, that's due to insufficient throttling of atomic commits in the kernel, not directly related to the functionality in this series.
> So I think we should rollout vblank timers for all drivers without hardware vblank IRQ.
I'm not arguing against that. It doesn't necessarily invalidate my concern though.
> Right now, vblank timers act like a vblank IRQ in these ioctls. That's a convenient position for user space.
>
> But we don't really sync anything with hardware here, so the alternate proposal is to not support them. This also appears to be the original intention of these ioctls.
Speaking as the creator of the DRM_IOCTL_WAIT_VBLANK ioctl, I'm afraid it's not that simple. While it's true that the ioctl was originally only available if backed by corresponding HW & driver support, that's mostly because vblank timers and the scenarios which motivated them weren't really a thing until much later though, not an explicit intention at the time.
I created it to give user space information about the display refresh cycle timing, and to allow it to synchronize to that. This seems like it could be useful even with vblank timers. At least if this ioctl and atomic commits are properly integrated, similar to how they are with a proper HW display refresh cycle, which I'm not sure is currently the case though.
> Vblank timers would just limit the internal page-flip rate, but nothing else. That's the more defensive approach.
If those two things aren't properly integrated though, then this might indeed be less bad than the status quo.
--
Earthling Michel Dänzer \ GNOME / Xwayland / Mesa developer
https://redhat.com \ Libre software enthusiast
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox