* [PATCH 0/4] Add atomic commit HW done event & deadline property
@ 2025-07-24 16:40 Michel Dänzer
2025-07-24 16:40 ` [PATCH 1/4] drm/kms: Add DRM_EVENT_ATOMIC_HW_DONE event type Michel Dänzer
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Michel Dänzer @ 2025-07-24 16:40 UTC (permalink / raw)
To: Harry Wentland, Leo Li, Alex Hung, Shankar, Uma, Xaver Hugl,
victoria, David Turner
Cc: amd-gfx, dri-devel
This work came out of a discussion at the Display Next hackfest in Toronto, see
https://hwentland.github.io/work/2025hackfest-notes.html#scheduling-atomic-commits .
In contrast to David's suggestion in the last paragraph there, I went for a
separate property for the deadline, mainly for these reasons:
1. Communicating the deadline via events would require sending one event
per CRTC, which I'd rather avoid due to the experience with page flip
events.
2. I'm assuming the property value doesn't need to change between modesets.
If this turns out to be wrong for some hardware, may need to reconsider.
libdrm MR: https://gitlab.freedesktop.org/mesa/libdrm/-/merge_requests/426
mutter MR: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4540
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] drm/kms: Add DRM_EVENT_ATOMIC_HW_DONE event type
2025-07-24 16:40 [PATCH 0/4] Add atomic commit HW done event & deadline property Michel Dänzer
@ 2025-07-24 16:40 ` Michel Dänzer
2025-07-24 16:40 ` [PATCH 2/4] drm/kms: Send event when atomic commit HW programming is done Michel Dänzer
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Michel Dänzer @ 2025-07-24 16:40 UTC (permalink / raw)
To: Harry Wentland, Leo Li, Alex Hung, Shankar, Uma, Xaver Hugl,
victoria, David Turner
Cc: amd-gfx, dri-devel
From: Michel Dänzer <mdaenzer@redhat.com>
It contains a timestamp corresponding to when the kernel driver finished
programming an atomic commit to HW.
Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
---
include/uapi/drm/drm.h | 31 ++++++++++++++++++++++++++++++-
include/uapi/drm/drm_mode.h | 9 +++++++++
2 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index e63a71d3c607..6fd16861cd3e 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -781,6 +781,13 @@ struct drm_gem_open {
* commits.
*/
#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15
+/**
+ * DRM_CAP_ATOMIC_HW_DONE_EVENT
+ *
+ * If set to 1, the kernel supports &DRM_MODE_ATOMIC_HW_DONE_EVENT for atomic
+ * commits.
+ */
+#define DRM_CAP_ATOMIC_HW_DONE_EVENT 0x16
/* DRM_IOCTL_GET_CAP ioctl argument type */
struct drm_get_cap {
@@ -1332,7 +1339,7 @@ extern "C" {
*
* Event types 0 - 0x7fffffff are generic DRM events, 0x80000000 and
* up are chipset specific. Generic DRM events include &DRM_EVENT_VBLANK,
- * &DRM_EVENT_FLIP_COMPLETE and &DRM_EVENT_CRTC_SEQUENCE.
+ * &DRM_EVENT_FLIP_COMPLETE, &DRM_EVENT_CRTC_SEQUENCE and &DRM_EVENT_ATOMIC_HW_DONE.
*/
struct drm_event {
__u32 type;
@@ -1365,6 +1372,17 @@ struct drm_event {
* The event payload is a struct drm_event_crtc_sequence.
*/
#define DRM_EVENT_CRTC_SEQUENCE 0x03
+/**
+ * DRM_EVENT_ATOMIC_HW_DONE - atomic commit HW done event
+ *
+ * This event is sent in response to an atomic commit with the
+ * &DRM_MODE_ATOMIC_HW_DONE_EVENT flag set.
+ *
+ * One event is sent per commit.
+ *
+ * The event payload is a struct drm_event_atomic_hw_done.
+ */
+#define DRM_EVENT_ATOMIC_HW_DONE 0x04
struct drm_event_vblank {
struct drm_event base;
@@ -1375,6 +1393,17 @@ struct drm_event_vblank {
__u32 crtc_id; /* 0 on older kernels that do not support this */
};
+struct drm_event_atomic_hw_done {
+ struct drm_event base;
+ __u64 user_data;
+
+ /**
+ * Timestamp corresponding to when programming the commit to HW completed.
+ */
+ __u32 tv_sec;
+ __u32 tv_usec;
+};
+
/* Event delivered at sequence. Time stamp marks when the first pixel
* of the refresh cycle leaves the display engine for the display
*/
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index c082810c08a8..d7921e633f1a 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -1136,6 +1136,15 @@ struct drm_mode_destroy_dumb {
*/
#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400
+/**
+ * DRM_MODE_ATOMIC_HW_DONE_EVENT
+ *
+ * Request that the kernel sends back an atomic commit HW done event (see
+ * struct drm_event_atomic_hw_done) with the &DRM_EVENT_ATOMIC_HW_DONE type when
+ * programming the atomic commit to HW completes.
+ */
+#define DRM_MODE_ATOMIC_HW_DONE_EVENT 0x0800
+
/**
* DRM_MODE_ATOMIC_FLAGS
*
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/4] drm/kms: Send event when atomic commit HW programming is done
2025-07-24 16:40 [PATCH 0/4] Add atomic commit HW done event & deadline property Michel Dänzer
2025-07-24 16:40 ` [PATCH 1/4] drm/kms: Add DRM_EVENT_ATOMIC_HW_DONE event type Michel Dänzer
@ 2025-07-24 16:40 ` Michel Dänzer
2025-07-24 16:40 ` [PATCH 3/4] drm: Add HW_DONE_DEADLINE immutable atomic CRTC property Michel Dänzer
2025-07-24 16:40 ` [PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset Michel Dänzer
3 siblings, 0 replies; 9+ messages in thread
From: Michel Dänzer @ 2025-07-24 16:40 UTC (permalink / raw)
To: Harry Wentland, Leo Li, Alex Hung, Shankar, Uma, Xaver Hugl,
victoria, David Turner
Cc: amd-gfx, dri-devel
From: Michel Dänzer <mdaenzer@redhat.com>
Also add DRM_CAP_ATOMIC_HW_DONE_EVENT to let user space know it can
use the DRM_MODE_ATOMIC_HW_DONE_EVENT flag.
Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
---
drivers/gpu/drm/drm_atomic.c | 1 +
drivers/gpu/drm/drm_atomic_helper.c | 23 ++++++++++++++++++
drivers/gpu/drm/drm_atomic_uapi.c | 37 +++++++++++++++++++++++++++--
drivers/gpu/drm/drm_ioctl.c | 3 +++
include/drm/drm_atomic.h | 22 +++++++++++++++++
include/uapi/drm/drm_mode.h | 3 ++-
6 files changed, 86 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 0138cf0b8b63..159894381a45 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -108,6 +108,7 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state)
kfree(state->crtcs);
kfree(state->planes);
kfree(state->private_objs);
+ kfree(state->hw_done_event);
}
EXPORT_SYMBOL(drm_atomic_state_default_release);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index ee64ca1b1bec..e55edc42a317 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2511,6 +2511,27 @@ void drm_atomic_helper_fake_vblank(struct drm_atomic_state *state)
}
EXPORT_SYMBOL(drm_atomic_helper_fake_vblank);
+static void send_hw_done_event(struct drm_device *dev,
+ struct drm_pending_atomic_hw_done_event **e,
+ ktime_t done)
+{
+ struct timespec64 tv;
+ unsigned long irqflags;
+
+ if (!*e)
+ return;
+
+ tv = ktime_to_timespec64(done);
+ (*e)->event.tv_sec = tv.tv_sec;
+ (*e)->event.tv_usec = tv.tv_nsec / 1000;
+
+ spin_lock_irqsave(&dev->event_lock, irqflags);
+ drm_send_event_timestamp_locked(dev, &(*e)->base, done);
+ spin_unlock_irqrestore(&dev->event_lock, irqflags);
+
+ *e = NULL;
+}
+
/**
* drm_atomic_helper_commit_hw_done - setup possible nonblocking commit
* @state: atomic state object being committed
@@ -2533,6 +2554,8 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state)
struct drm_crtc_commit *commit;
int i;
+ send_hw_done_event(state->dev, &state->hw_done_event, ktime_get());
+
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
commit = new_crtc_state->commit;
if (!commit)
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index c2726af6698e..43c16bfe65a9 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -939,6 +939,21 @@ static struct drm_pending_vblank_event *create_vblank_event(
return e;
}
+static struct drm_pending_atomic_hw_done_event *create_hw_done_event(uint64_t user_data)
+{
+ struct drm_pending_atomic_hw_done_event *e = NULL;
+
+ e = kzalloc(sizeof *e, GFP_KERNEL);
+ if (!e)
+ return NULL;
+
+ e->event.base.type = DRM_EVENT_ATOMIC_HW_DONE;
+ e->event.base.length = sizeof(e->event);
+ e->event.user_data = user_data;
+
+ return e;
+}
+
int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
struct drm_connector *connector,
int mode)
@@ -1314,6 +1329,24 @@ static int prepare_signaling(struct drm_device *dev,
return -EINVAL;
}
+ if (arg->flags & DRM_MODE_ATOMIC_HW_DONE_EVENT &&
+ file_priv) {
+ struct drm_pending_atomic_hw_done_event *e;
+
+ e = create_hw_done_event(arg->user_data);
+ if (!e)
+ return -ENOMEM;
+
+ ret = drm_event_reserve_init(dev, file_priv, &e->base,
+ &e->event.base);
+ if (ret) {
+ kfree(e);
+ return ret;
+ }
+
+ state->hw_done_event = e;
+ }
+
return 0;
}
@@ -1431,9 +1464,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
/* can't test and expect an event at the same time. */
if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
- (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) {
+ (arg->flags & (DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_HW_DONE_EVENT))) {
drm_dbg_atomic(dev,
- "commit failed: page-flip event requested with test-only commit\n");
+ "commit failed: event requested with test-only commit\n");
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index f593dc569d31..3b2221748dca 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -304,6 +304,9 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) &&
dev->mode_config.async_page_flip;
break;
+ case DRM_CAP_ATOMIC_HW_DONE_EVENT:
+ req->value = 1;
+ break;
default:
return -EINVAL;
}
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 38636a593c9d..e34c2b08e759 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -29,8 +29,23 @@
#define DRM_ATOMIC_H_
#include <drm/drm_crtc.h>
+#include <drm/drm_file.h>
#include <drm/drm_util.h>
+/**
+ * struct drm_pending_atomic_hw_done_event - pending atomic HW done event tracking
+ */
+struct drm_pending_atomic_hw_done_event {
+ /**
+ * @base: Base structure for tracking pending DRM events.
+ */
+ struct drm_pending_event base;
+ /**
+ * @event: Actual event which will be sent to userspace.
+ */
+ struct drm_event_atomic_hw_done event;
+};
+
/**
* struct drm_crtc_commit - track modeset commits on a CRTC
*
@@ -517,6 +532,13 @@ struct drm_atomic_state {
*/
struct drm_crtc_commit *fake_commit;
+ /**
+ * @hw_done_event:
+ *
+ * Used for sending an event to user space when programming a commit to HW is done.
+ */
+ struct drm_pending_atomic_hw_done_event *hw_done_event;
+
/**
* @commit_work:
*
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index d7921e633f1a..463e32919093 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -1156,7 +1156,8 @@ struct drm_mode_destroy_dumb {
DRM_MODE_PAGE_FLIP_ASYNC |\
DRM_MODE_ATOMIC_TEST_ONLY |\
DRM_MODE_ATOMIC_NONBLOCK |\
- DRM_MODE_ATOMIC_ALLOW_MODESET)
+ DRM_MODE_ATOMIC_ALLOW_MODESET |\
+ DRM_MODE_ATOMIC_HW_DONE_EVENT)
struct drm_mode_atomic {
__u32 flags;
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] drm: Add HW_DONE_DEADLINE immutable atomic CRTC property
2025-07-24 16:40 [PATCH 0/4] Add atomic commit HW done event & deadline property Michel Dänzer
2025-07-24 16:40 ` [PATCH 1/4] drm/kms: Add DRM_EVENT_ATOMIC_HW_DONE event type Michel Dänzer
2025-07-24 16:40 ` [PATCH 2/4] drm/kms: Send event when atomic commit HW programming is done Michel Dänzer
@ 2025-07-24 16:40 ` Michel Dänzer
2025-07-26 13:10 ` kernel test robot
2025-07-24 16:40 ` [PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset Michel Dänzer
3 siblings, 1 reply; 9+ messages in thread
From: Michel Dänzer @ 2025-07-24 16:40 UTC (permalink / raw)
To: Harry Wentland, Leo Li, Alex Hung, Shankar, Uma, Xaver Hugl,
victoria, David Turner
Cc: amd-gfx, dri-devel
From: Michel Dänzer <mdaenzer@redhat.com>
It lets user space know how long before start of scanout HW programming
of an atomic commit needs to finish.
This implements the default fallback deadline which corresponds to start
of vblank.
Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 15 +++++++++++++++
drivers/gpu/drm/drm_crtc.c | 30 +++++++++++++++++++++++++++++
drivers/gpu/drm/drm_mode_config.c | 7 +++++++
include/drm/drm_crtc.h | 1 +
include/drm/drm_mode_config.h | 5 +++++
5 files changed, 58 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index e55edc42a317..51213e9fba07 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2574,6 +2574,21 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state)
/* backend must have consumed any event by now */
WARN_ON(new_crtc_state->event);
complete_all(&commit->hw_done);
+
+ if (new_crtc_state->active &&
+ (!old_crtc_state->active ||
+ drm_atomic_crtc_needs_modeset(new_crtc_state))) {
+ struct drm_display_mode *mode = &new_crtc_state->mode;
+ unsigned deadline_lines, deadline_us;
+
+ /* Reset HW done deadline to start of vblank */
+ deadline_lines = mode->crtc_vtotal - mode->crtc_vdisplay;
+ deadline_us = DIV_ROUND_UP(deadline_lines * mode->crtc_htotal * 1000u,
+ mode->crtc_clock);
+ drm_crtc_set_hw_done_deadline_property(crtc, deadline_us);
+ } else if (old_crtc_state->active && !new_crtc_state->active) {
+ drm_crtc_set_hw_done_deadline_property(crtc, 0);
+ }
}
if (state->fake_commit) {
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 46655339003d..3330fa30f295 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -229,6 +229,16 @@ struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
* Driver's default scaling filter
* Nearest Neighbor:
* Nearest Neighbor scaling filter
+ * HW_DONE_DEADLINE:
+ * Immutable atomic property describing the deadline for programming an
+ * atomic commit to HW to finish, to guarantee that the commit takes
+ * effect for the next refresh cycle.
+ *
+ * With fixed refresh rate, the value is the number of microseconds before
+ * the end of vblank.
+ *
+ * With variable refresh rate (VRR), the value is the number of microseconds
+ * before the latest possible end of vblank.
*/
__printf(6, 0)
@@ -303,6 +313,8 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *
config->prop_out_fence_ptr, 0);
drm_object_attach_property(&crtc->base,
config->prop_vrr_enabled, 0);
+ drm_object_attach_property(&crtc->base,
+ config->prop_hw_done_deadline, 0);
}
return 0;
@@ -940,6 +952,24 @@ int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
}
EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);
+/**
+ * drm_crtc_set_hw_done_deadline_property - sets the HW done deadline property for a CRTC
+ * @crtc: drm CRTC
+ * @capable: True if the connector is variable refresh rate capable
+ *
+ * If the actual deadline differs from start of vblank, the atomic driver can call this to
+ * update the deadline after a modeset.
+ */
+void drm_crtc_set_hw_done_deadline_property(struct drm_crtc *crtc, unsigned deadline)
+{
+ struct drm_device *dev = crtc->dev;
+
+ drm_object_property_set_value(&crtc->base,
+ dev->mode_config.prop_hw_done_deadline,
+ deadline);
+}
+EXPORT_SYMBOL(drm_crtc_set_hw_done_deadline_property);
+
/**
* drm_crtc_in_clone_mode - check if the given CRTC state is in clone mode
*
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index b4239fd04e9d..721896d291d3 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -339,6 +339,13 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
return -ENOMEM;
dev->mode_config.prop_vrr_enabled = prop;
+ prop = drm_property_create_range(dev,
+ DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_IMMUTABLE,
+ "HW_DONE_DEADLINE", 0, UINT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_hw_done_deadline = prop;
+
prop = drm_property_create(dev,
DRM_MODE_PROP_BLOB,
"DEGAMMA_LUT", 0);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index caa56e039da2..c902040c0468 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1323,5 +1323,6 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
unsigned int supported_filters);
+void drm_crtc_set_hw_done_deadline_property(struct drm_crtc *crtc, unsigned deadline);
bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state);
#endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 9e524b51a001..11dce8be85a4 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -679,6 +679,11 @@ struct drm_mode_config {
*/
struct drm_property *prop_vrr_enabled;
+ /**
+ * @prop_hw_done_deadline: Atomic CRTC HW_DONE_DEADLINE property.
+ */
+ struct drm_property *prop_hw_done_deadline;
+
/**
* @dvi_i_subconnector_property: Optional DVI-I property to
* differentiate between analog or digital mode.
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset
2025-07-24 16:40 [PATCH 0/4] Add atomic commit HW done event & deadline property Michel Dänzer
` (2 preceding siblings ...)
2025-07-24 16:40 ` [PATCH 3/4] drm: Add HW_DONE_DEADLINE immutable atomic CRTC property Michel Dänzer
@ 2025-07-24 16:40 ` Michel Dänzer
2025-07-31 20:51 ` Harry Wentland
3 siblings, 1 reply; 9+ messages in thread
From: Michel Dänzer @ 2025-07-24 16:40 UTC (permalink / raw)
To: Harry Wentland, Leo Li, Alex Hung, Shankar, Uma, Xaver Hugl,
victoria, David Turner
Cc: amd-gfx, dri-devel
From: Michel Dänzer <mdaenzer@redhat.com>
Set it to the end of the front porch.
Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0b8ac9edc070..e78249b55345 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -10021,6 +10021,21 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm,
drm_writeback_queue_job(wb_conn, new_con_state);
}
+static void
+update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state)
+{
+ struct dc_stream_state *stream = dm_new_crtc_state->stream;
+ struct dc_crtc_timing *timing = &stream->timing;
+ struct drm_crtc *crtc = dm_new_crtc_state->base.crtc;
+ uint32_t deadline_lines, deadline_us;
+
+ /* XXX: My guess, AMD display team to the rescue! */
+ deadline_lines = timing->v_total - timing->v_addressable - timing->v_front_porch;
+ deadline_us = DIV_ROUND_UP(deadline_lines * stream->timing.h_total * 10000u,
+ stream->timing.pix_clk_100hz);
+ drm_crtc_set_hw_done_deadline_property(crtc, deadline_us);
+}
+
/**
* amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation.
* @state: The atomic state to commit
@@ -10419,6 +10434,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
/* Signal HW programming completion */
drm_atomic_helper_commit_hw_done(state);
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+ if (new_crtc_state->active &&
+ (!old_crtc_state->active ||
+ drm_atomic_crtc_needs_modeset(new_crtc_state)))
+ update_hw_done_deadline(to_dm_crtc_state(new_crtc_state));
+ }
+
if (wait_for_vblank)
drm_atomic_helper_wait_for_flip_done(dev, state);
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/4] drm: Add HW_DONE_DEADLINE immutable atomic CRTC property
2025-07-24 16:40 ` [PATCH 3/4] drm: Add HW_DONE_DEADLINE immutable atomic CRTC property Michel Dänzer
@ 2025-07-26 13:10 ` kernel test robot
0 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2025-07-26 13:10 UTC (permalink / raw)
To: Michel Dänzer, Harry Wentland, Leo Li, Alex Hung, Shankar,
Uma, Xaver Hugl, victoria, David Turner
Cc: oe-kbuild-all, amd-gfx, dri-devel
Hi Michel,
kernel test robot noticed the following build warnings:
[auto build test WARNING on drm-exynos/exynos-drm-next]
[also build test WARNING on linus/master v6.16-rc7 next-20250725]
[cannot apply to drm/drm-next drm-intel/for-linux-next drm-intel/for-linux-next-fixes drm-misc/drm-misc-next drm-tip/drm-tip]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Michel-D-nzer/drm-kms-Add-DRM_EVENT_ATOMIC_HW_DONE-event-type/20250725-010202
base: https://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git exynos-drm-next
patch link: https://lore.kernel.org/r/20250724165220.1189129-4-michel%40daenzer.net
patch subject: [PATCH 3/4] drm: Add HW_DONE_DEADLINE immutable atomic CRTC property
config: x86_64-defconfig (https://download.01.org/0day-ci/archive/20250726/202507262035.wxgiJwAZ-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250726/202507262035.wxgiJwAZ-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507262035.wxgiJwAZ-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> Warning: drivers/gpu/drm/drm_crtc.c:963 function parameter 'deadline' not described in 'drm_crtc_set_hw_done_deadline_property'
Warning: drivers/gpu/drm/drm_crtc.c:963 Excess function parameter 'capable' description in 'drm_crtc_set_hw_done_deadline_property'
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset
2025-07-24 16:40 ` [PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset Michel Dänzer
@ 2025-07-31 20:51 ` Harry Wentland
2025-08-04 8:20 ` Michel Dänzer
0 siblings, 1 reply; 9+ messages in thread
From: Harry Wentland @ 2025-07-31 20:51 UTC (permalink / raw)
To: Michel Dänzer, Leo Li, Alex Hung, Shankar, Uma, Xaver Hugl,
victoria, David Turner
Cc: amd-gfx, dri-devel
Thanks for the series. It makes sense to me.
Below are my thoughts on the deadline value on amdgpu.
On 2025-07-24 12:40, Michel Dänzer wrote:
> From: Michel Dänzer <mdaenzer@redhat.com>
>
> Set it to the end of the front porch.
>
> Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
> ---
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 +++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 0b8ac9edc070..e78249b55345 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -10021,6 +10021,21 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm,
> drm_writeback_queue_job(wb_conn, new_con_state);
> }
>
> +static void
> +update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state)
> +{
> + struct dc_stream_state *stream = dm_new_crtc_state->stream;
> + struct dc_crtc_timing *timing = &stream->timing;
> + struct drm_crtc *crtc = dm_new_crtc_state->base.crtc;
> + uint32_t deadline_lines, deadline_us;
> +
> + /* XXX: My guess, AMD display team to the rescue! */
> + deadline_lines = timing->v_total - timing->v_addressable - timing->v_front_porch;
This works on DCE. On DCN we'll need to take the offset into account.
This diff on top of your changesshould do it, but it's not tested.
The dc_stream changes probably fit in their own patch.
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 629fd21a611f..314074527216 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -10082,11 +10082,19 @@ update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state)
struct dc_crtc_timing *timing = &stream->timing;
struct drm_crtc *crtc = dm_new_crtc_state->base.crtc;
uint32_t deadline_lines, deadline_us;
+ int vupdate_offset = dc_stream_get_vupdate_offset_from_vsync(stream);
+
+ /* note:
+ * vupdate_offset is non-existant on DCE and function will return 0
+ * vupdate_offset could be positive or negative on DCN
+ * vupdate_offset depends on timing and HW bandwidth requirements
+ */
+ deadline_lines = timing->v_total - timing->v_addressable -
+ timing->v_front_porch - vupdate_offset;
- /* XXX: My guess, AMD display team to the rescue! */
- deadline_lines = timing->v_total - timing->v_addressable - timing->v_front_porch;
deadline_us = DIV_ROUND_UP(deadline_lines * stream->timing.h_total * 10000u,
stream->timing.pix_clk_100hz);
+
drm_crtc_set_hw_done_deadline_property(crtc, deadline_us);
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 4d6bc9fd4faa..ae8472a65247 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -1224,3 +1224,25 @@ bool dc_stream_can_clear_cursor_limit(struct dc *dc, struct dc_stream_state *str
return can_clear_limit;
}
+
+int dc_stream_get_vupdate_offset_from_vsync(const struct dc_stream_state *stream)
+{
+ struct dc *dc;
+ struct resource_context *res_ctx;
+ int i;
+
+ if (!stream || !stream->ctx || !stream->ctx->dc)
+ return 0;
+
+ dc = stream->ctx->dc;
+ res_ctx = &dc->current_state->res_ctx;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
+
+ if (pipe_ctx->stream == stream && dc->hwss.get_vupdate_offset_from_vsync)
+ return dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 5fc6fea211de..792a7e8b2ee7 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -601,4 +601,6 @@ void dc_dmub_update_dirty_rect(struct dc *dc,
bool dc_stream_is_cursor_limit_pending(struct dc *dc, struct dc_stream_state *stream);
bool dc_stream_can_clear_cursor_limit(struct dc *dc, struct dc_stream_state *stream);
+int dc_stream_get_vupdate_offset_from_vsync(const struct dc_stream_state *stream);
+
#endif /* DC_STREAM_H_ */
Harry
> + deadline_us = DIV_ROUND_UP(deadline_lines * stream->timing.h_total * 10000u,
> + stream->timing.pix_clk_100hz);
> + drm_crtc_set_hw_done_deadline_property(crtc, deadline_us);
> +}
> +
> /**
> * amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation.
> * @state: The atomic state to commit
> @@ -10419,6 +10434,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
> /* Signal HW programming completion */
> drm_atomic_helper_commit_hw_done(state);
>
> + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
> + if (new_crtc_state->active &&
> + (!old_crtc_state->active ||
> + drm_atomic_crtc_needs_modeset(new_crtc_state)))
> + update_hw_done_deadline(to_dm_crtc_state(new_crtc_state));
> + }
> +
> if (wait_for_vblank)
> drm_atomic_helper_wait_for_flip_done(dev, state);
>
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset
2025-07-31 20:51 ` Harry Wentland
@ 2025-08-04 8:20 ` Michel Dänzer
2025-08-05 16:28 ` Harry Wentland
0 siblings, 1 reply; 9+ messages in thread
From: Michel Dänzer @ 2025-08-04 8:20 UTC (permalink / raw)
To: Harry Wentland, Leo Li, Alex Hung, Uma Shankar, Xaver Hugl,
victoria, David Turner
Cc: amd-gfx, dri-devel
On 31.07.25 22:51, Harry Wentland wrote:
> Thanks for the series. It makes sense to me.
I'm glad to hear it, thanks for taking a look.
May I take this as R-b?
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index 0b8ac9edc070..e78249b55345 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -10021,6 +10021,21 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm,
>> drm_writeback_queue_job(wb_conn, new_con_state);
>> }
>>
>> +static void
>> +update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state)
>> +{
>> + struct dc_stream_state *stream = dm_new_crtc_state->stream;
>> + struct dc_crtc_timing *timing = &stream->timing;
>> + struct drm_crtc *crtc = dm_new_crtc_state->base.crtc;
>> + uint32_t deadline_lines, deadline_us;
>> +
>> + /* XXX: My guess, AMD display team to the rescue! */
>> + deadline_lines = timing->v_total - timing->v_addressable - timing->v_front_porch;
>
> This works on DCE. On DCN we'll need to take the offset into account.
> This diff on top of your changesshould do it, but it's not tested.
> The dc_stream changes probably fit in their own patch.
Thanks, I'll incorporate it.
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 629fd21a611f..314074527216 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -10082,11 +10082,19 @@ update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state)
> struct dc_crtc_timing *timing = &stream->timing;
> struct drm_crtc *crtc = dm_new_crtc_state->base.crtc;
> uint32_t deadline_lines, deadline_us;
> + int vupdate_offset = dc_stream_get_vupdate_offset_from_vsync(stream);
> +
> + /* note:
> + * vupdate_offset is non-existant on DCE and function will return 0
> + * vupdate_offset could be positive or negative on DCN
> + * vupdate_offset depends on timing and HW bandwidth requirements
> + */
> + deadline_lines = timing->v_total - timing->v_addressable -
> + timing->v_front_porch - vupdate_offset;
Hmm, if it depends on bandwidth, we'll need to recalculate it for all CRTCs after a modeset for any of them, right?
--
Earthling Michel Dänzer \ GNOME / Xwayland / Mesa developer
https://redhat.com \ Libre software enthusiast
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset
2025-08-04 8:20 ` Michel Dänzer
@ 2025-08-05 16:28 ` Harry Wentland
0 siblings, 0 replies; 9+ messages in thread
From: Harry Wentland @ 2025-08-05 16:28 UTC (permalink / raw)
To: Michel Dänzer, Leo Li, Alex Hung, Uma Shankar, Xaver Hugl,
victoria, David Turner
Cc: amd-gfx, dri-devel
On 2025-08-04 04:20, Michel Dänzer wrote:
> On 31.07.25 22:51, Harry Wentland wrote:
>> Thanks for the series. It makes sense to me.
> I'm glad to hear it, thanks for taking a look.
>
> May I take this as R-b?
Yes, please do. :)
Harry
>
>
>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>>> index 0b8ac9edc070..e78249b55345 100644
>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>>> @@ -10021,6 +10021,21 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm,
>>> drm_writeback_queue_job(wb_conn, new_con_state);
>>> }
>>>
>>> +static void
>>> +update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state)
>>> +{
>>> + struct dc_stream_state *stream = dm_new_crtc_state->stream;
>>> + struct dc_crtc_timing *timing = &stream->timing;
>>> + struct drm_crtc *crtc = dm_new_crtc_state->base.crtc;
>>> + uint32_t deadline_lines, deadline_us;
>>> +
>>> + /* XXX: My guess, AMD display team to the rescue! */
>>> + deadline_lines = timing->v_total - timing->v_addressable - timing->v_front_porch;
>> This works on DCE. On DCN we'll need to take the offset into account.
>> This diff on top of your changesshould do it, but it's not tested.
>> The dc_stream changes probably fit in their own patch.
> Thanks, I'll incorporate it.
>
>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index 629fd21a611f..314074527216 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -10082,11 +10082,19 @@ update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state)
>> struct dc_crtc_timing *timing = &stream->timing;
>> struct drm_crtc *crtc = dm_new_crtc_state->base.crtc;
>> uint32_t deadline_lines, deadline_us;
>> + int vupdate_offset = dc_stream_get_vupdate_offset_from_vsync(stream);
>> +
>> + /* note:
>> + * vupdate_offset is non-existant on DCE and function will return 0
>> + * vupdate_offset could be positive or negative on DCN
>> + * vupdate_offset depends on timing and HW bandwidth requirements
>> + */
>> + deadline_lines = timing->v_total - timing->v_addressable -
>> + timing->v_front_porch - vupdate_offset;
> Hmm, if it depends on bandwidth, we'll need to recalculate it for all CRTCs after a modeset for any of them, right?
>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-08-05 16:28 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-24 16:40 [PATCH 0/4] Add atomic commit HW done event & deadline property Michel Dänzer
2025-07-24 16:40 ` [PATCH 1/4] drm/kms: Add DRM_EVENT_ATOMIC_HW_DONE event type Michel Dänzer
2025-07-24 16:40 ` [PATCH 2/4] drm/kms: Send event when atomic commit HW programming is done Michel Dänzer
2025-07-24 16:40 ` [PATCH 3/4] drm: Add HW_DONE_DEADLINE immutable atomic CRTC property Michel Dänzer
2025-07-26 13:10 ` kernel test robot
2025-07-24 16:40 ` [PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset Michel Dänzer
2025-07-31 20:51 ` Harry Wentland
2025-08-04 8:20 ` Michel Dänzer
2025-08-05 16:28 ` Harry Wentland
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).