[PATCH 1/2] drm: Fix dirtyfb stalls

From: Rob Clark
Date: Sat May 08 2021 - 15:59:21 EST


From: Rob Clark <robdclark@xxxxxxxxxxxx>

drm_atomic_helper_dirtyfb() will end up stalling for vblank on "video
mode" type displays, which is pointless and unnecessary. Add an
optional helper vfunc to determine if a plane is attached to a CRTC
that actually needs dirtyfb, and skip over them.

Signed-off-by: Rob Clark <robdclark@xxxxxxxxxxxx>
---
drivers/gpu/drm/drm_damage_helper.c | 8 ++++++++
include/drm/drm_modeset_helper_vtables.h | 14 ++++++++++++++
2 files changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index 3a4126dc2520..a0bed1a2c2dc 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -211,6 +211,7 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
retry:
drm_for_each_plane(plane, fb->dev) {
struct drm_plane_state *plane_state;
+ struct drm_crtc *crtc;

ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
if (ret)
@@ -221,6 +222,13 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
continue;
}

+ crtc = plane->state->crtc;
+ if (crtc->helper_private->needs_dirtyfb &&
+ !crtc->helper_private->needs_dirtyfb(crtc)) {
+ drm_modeset_unlock(&plane->mutex);
+ continue;
+ }
+
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index eb706342861d..afa8ec5754e7 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -487,6 +487,20 @@ struct drm_crtc_helper_funcs {
bool in_vblank_irq, int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime,
const struct drm_display_mode *mode);
+
+ /**
+ * @needs_dirtyfb
+ *
+ * Optional callback used by damage helpers to determine if fb_damage_clips
+ * update is needed.
+ *
+ * Returns:
+ *
+ * True if fb_damage_clips update is needed to handle DIRTYFB, False
+ * otherwise. If this callback is not implemented, then True is
+ * assumed.
+ */
+ bool (*needs_dirtyfb)(struct drm_crtc *crtc);
};

/**
--
2.30.2