[PATCH 3/5] drm/sti: do not sync SETPLANE on vblank if not ATOMIC

Fabien Dessenne fabien.dessenne at st.com
Tue Jan 3 16:56:50 UTC 2017


If the client does not set the ATOMIC capability, do not wait for vblank
before returning an DRM_IOCTL_MODE_SETPLANE call.

In this way, a legacy framework (eg non-atomic Weston) can call several
SETPLANE within the same Vsync cycle.

This is implemented by setting the legacy_cursor_update flag, to behave
the same way as DRM_IOCTL_MODE_CURSOR (not vblank synced).

Change-Id: Ia241b6c88411c675bf589c17d4a44db6d02f669f
Signed-off-by: Fabien Dessenne <fabien.dessenne at st.com>
---
 drivers/gpu/drm/sti/sti_cursor.c |   4 +-
 drivers/gpu/drm/sti/sti_gdp.c    |   4 +-
 drivers/gpu/drm/sti/sti_hqvdp.c  |   4 +-
 drivers/gpu/drm/sti/sti_plane.c  | 144 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sti/sti_plane.h  |   8 +++
 5 files changed, 158 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
index cca75bd..ea0dbae 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -346,8 +346,8 @@ static int sti_cursor_late_register(struct drm_plane *drm_plane)
 }
 
 static const struct drm_plane_funcs sti_cursor_plane_helpers_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
+	.update_plane = sti_plane_update_plane,
+	.disable_plane = sti_plane_disable_plane,
 	.destroy = sti_cursor_destroy,
 	.set_property = drm_atomic_helper_plane_set_property,
 	.reset = sti_plane_reset,
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 81df309..a379bbe 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -882,8 +882,8 @@ static int sti_gdp_late_register(struct drm_plane *drm_plane)
 }
 
 static const struct drm_plane_funcs sti_gdp_plane_helpers_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
+	.update_plane = sti_plane_update_plane,
+	.disable_plane = sti_plane_disable_plane,
 	.destroy = sti_gdp_destroy,
 	.set_property = drm_atomic_helper_plane_set_property,
 	.reset = sti_plane_reset,
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index f88130f..65ca43f 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1252,8 +1252,8 @@ static int sti_hqvdp_late_register(struct drm_plane *drm_plane)
 }
 
 static const struct drm_plane_funcs sti_hqvdp_plane_helpers_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
+	.update_plane = sti_plane_update_plane,
+	.disable_plane = sti_plane_disable_plane,
 	.destroy = sti_hqvdp_destroy,
 	.set_property = drm_atomic_helper_plane_set_property,
 	.reset = sti_plane_reset,
diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c
index ca4b371..22cf30d 100644
--- a/drivers/gpu/drm/sti/sti_plane.c
+++ b/drivers/gpu/drm/sti/sti_plane.c
@@ -7,6 +7,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
@@ -130,3 +131,146 @@ void sti_plane_init_property(struct sti_plane *plane,
 	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s\n",
 			 plane->drm_plane.base.id, sti_plane_to_str(plane));
 }
+
+int sti_plane_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+			   struct drm_framebuffer *fb,
+			   int crtc_x, int crtc_y,
+			   unsigned int crtc_w, unsigned int crtc_h,
+			   uint32_t src_x, uint32_t src_y,
+			   uint32_t src_w, uint32_t src_h)
+{
+	/*
+	 * Forked from drm_atomic_helper_update_plane().
+	 * Here we do not wait for vblank if the client is not atomic, so
+	 * DRM_IOCTL_MODE_SETPLANE returns before vblank.
+	 */
+
+	struct drm_atomic_state *state;
+	struct drm_plane_state *plane_state;
+	struct sti_private *private = plane->dev->dev_private;
+	int ret = 0;
+
+	state = drm_atomic_state_alloc(plane->dev);
+	if (!state)
+		return -ENOMEM;
+
+	state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
+retry:
+	plane_state = drm_atomic_get_plane_state(state, plane);
+	if (IS_ERR(plane_state)) {
+		ret = PTR_ERR(plane_state);
+		goto fail;
+	}
+
+	ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
+	if (ret != 0)
+		goto fail;
+	drm_atomic_set_fb_for_plane(plane_state, fb);
+	plane_state->crtc_x = crtc_x;
+	plane_state->crtc_y = crtc_y;
+	plane_state->crtc_w = crtc_w;
+	plane_state->crtc_h = crtc_h;
+	plane_state->src_x = src_x;
+	plane_state->src_y = src_y;
+	plane_state->src_w = src_w;
+	plane_state->src_h = src_h;
+
+	if ((plane == crtc->cursor) || !private->filp->atomic)
+		state->legacy_cursor_update = true;
+
+	ret = drm_atomic_commit(state);
+	if (ret != 0)
+		goto fail;
+
+	/* Driver takes ownership of state on successful commit. */
+	return 0;
+fail:
+	if (ret == -EDEADLK)
+		goto backoff;
+
+	drm_atomic_state_free(state);
+
+	return ret;
+backoff:
+	drm_atomic_state_clear(state);
+	drm_atomic_legacy_backoff(state);
+
+	/*
+	 * Someone might have exchanged the framebuffer while we dropped locks
+	 * in the backoff code. We need to fix up the fb refcount tracking the
+	 * core does for us.
+	 */
+	plane->old_fb = plane->fb;
+
+	goto retry;
+}
+
+int sti_plane_disable_plane(struct drm_plane *plane)
+{
+	/*
+	 * Forked from drm_atomic_helper_disable_plane().
+	 * Here we do not wait for vblank if the client is not atomic, so
+	 * DRM_IOCTL_MODE_SETPLANE returns before vblank.
+	 */
+	struct drm_atomic_state *state;
+	struct drm_plane_state *plane_state;
+	struct sti_private *private = plane->dev->dev_private;
+	int ret = 0;
+
+	/*
+	 * FIXME: Without plane->crtc set we can't get at the implicit legacy
+	 * acquire context. The real fix will be to wire the acquire ctx through
+	 * everywhere we need it, but meanwhile prevent chaos by just skipping
+	 * this noop. The critical case is the cursor ioctls which a) only grab
+	 * crtc/cursor-plane locks (so we need the crtc to get at the right
+	 * acquire context) and b) can try to disable the plane multiple times.
+	 */
+	if (!plane->crtc)
+		return 0;
+
+	state = drm_atomic_state_alloc(plane->dev);
+	if (!state)
+		return -ENOMEM;
+
+	state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc);
+retry:
+	plane_state = drm_atomic_get_plane_state(state, plane);
+	if (IS_ERR(plane_state)) {
+		ret = PTR_ERR(plane_state);
+		goto fail;
+	}
+
+	if ((plane_state->crtc && (plane == plane->crtc->cursor)) ||
+	    !private->filp->atomic)
+		plane_state->state->legacy_cursor_update = true;
+
+	ret = __drm_atomic_helper_disable_plane(plane, plane_state);
+	if (ret != 0)
+		goto fail;
+
+	ret = drm_atomic_commit(state);
+	if (ret != 0)
+		goto fail;
+
+	/* Driver takes ownership of state on successful commit. */
+	return 0;
+fail:
+	if (ret == -EDEADLK)
+		goto backoff;
+
+	drm_atomic_state_free(state);
+
+	return ret;
+backoff:
+	drm_atomic_state_clear(state);
+	drm_atomic_legacy_backoff(state);
+
+	/*
+	 * Someone might have exchanged the framebuffer while we dropped locks
+	 * in the backoff code. We need to fix up the fb refcount tracking the
+	 * core does for us.
+	 */
+	plane->old_fb = plane->fb;
+
+	goto retry;
+}
diff --git a/drivers/gpu/drm/sti/sti_plane.h b/drivers/gpu/drm/sti/sti_plane.h
index ce3e8d6..1372b9c 100644
--- a/drivers/gpu/drm/sti/sti_plane.h
+++ b/drivers/gpu/drm/sti/sti_plane.h
@@ -83,4 +83,12 @@ void sti_plane_update_fps(struct sti_plane *plane,
 void sti_plane_init_property(struct sti_plane *plane,
 			     enum drm_plane_type type);
 void sti_plane_reset(struct drm_plane *plane);
+
+int sti_plane_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+			   struct drm_framebuffer *fb,
+			   int crtc_x, int crtc_y,
+			   unsigned int crtc_w, unsigned int crtc_h,
+			   uint32_t src_x, uint32_t src_y,
+			   uint32_t src_w, uint32_t src_h);
+int sti_plane_disable_plane(struct drm_plane *plane);
 #endif
-- 
2.7.4



More information about the dri-devel mailing list