[PATCH 4/9] drm/i915: Always prepare planes at the start of an atomic commit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The generic atomic helper likes to skip a prepare_plane_fb() if it
decides that the plane->fb is unchanged. This is wrong for us for a
couple of reasons:

 - if the pipe is reconfigured (i.e. a size change) but the framebuffer
   is untouched, we still have to flush any rendering prior to the
   reconfiguration to prevent wait-for-scanline GPU hangs

 - if the framebuffer is rotated, it remains the same but has a
   different view and a different address.

Finally, even if the framebuffer is unchanged the flip/modeset should be
ordered with respect to rendering to the frontbuffer.

Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/i915/intel_atomic_plane.c |  2 --
 drivers/gpu/drm/i915/intel_display.c      | 60 ++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_drv.h          |  4 ---
 3 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index b41bf380f2ab..76a5bbbaaa98 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -190,8 +190,6 @@ static void intel_plane_atomic_update(struct drm_plane *plane,
 }
 
 const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
-	.prepare_fb = intel_prepare_plane_fb,
-	.cleanup_fb = intel_cleanup_plane_fb,
 	.atomic_check = intel_plane_atomic_check,
 	.atomic_update = intel_plane_atomic_update,
 };
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 39a0380f6b55..2b6fbded790b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14066,7 +14066,7 @@ static int intel_atomic_check(struct drm_device *dev,
  *
  * Returns 0 on success, negative error code on failure.
  */
-int
+static int
 intel_prepare_plane_fb(struct drm_plane *plane,
 		       struct drm_plane_state *new_state)
 {
@@ -14152,7 +14152,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
  *
  * Must be called with struct_mutex held.
  */
-void
+static void
 intel_cleanup_plane_fb(struct drm_plane *plane,
 		       struct drm_plane_state *old_state)
 {
@@ -14171,6 +14171,49 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
 		intel_unpin_fb_obj(old_state->fb, old_state->rotation);
 }
 
+static int intel_atomic_commit_prepare_planes(struct drm_atomic_state *state)
+{
+	struct drm_plane *plane;
+	struct drm_plane_state *plane_state;
+	int i, j, ret;
+
+	ret = mutex_lock_interruptible(&state->dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	for_each_plane_in_state(state, plane, plane_state, i) {
+		ret = intel_prepare_plane_fb(plane, plane_state);
+		if (ret)
+			break;
+	}
+
+	if (ret) {
+		for_each_plane_in_state(state, plane, plane_state, j) {
+			if (j >= i)
+				break;
+
+			intel_cleanup_plane_fb(plane, plane_state);
+		}
+	}
+
+	mutex_unlock(&state->dev->struct_mutex);
+
+	return ret;
+}
+
+static void intel_atomic_commit_cleanup_planes(struct drm_atomic_state *state)
+{
+	struct drm_plane *plane;
+	struct drm_plane_state *plane_state;
+	int i;
+
+	mutex_lock(&state->dev->struct_mutex);
+
+	for_each_plane_in_state(state, plane, plane_state, i)
+		intel_cleanup_plane_fb(plane, plane_state);
+
+	mutex_unlock(&state->dev->struct_mutex);
+}
 
 static int intel_atomic_prepare_commit(struct drm_device *dev,
 				       struct drm_atomic_state *state,
@@ -14193,14 +14236,7 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
 			flush_workqueue(dev_priv->wq);
 	}
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
-
-	ret = drm_atomic_helper_prepare_planes(dev, state);
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
+	return intel_atomic_commit_prepare_planes(state);
 }
 
 u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
@@ -14527,9 +14563,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 	if (intel_state->modeset)
 		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
 
-	mutex_lock(&dev->struct_mutex);
-	drm_atomic_helper_cleanup_planes(dev, state);
-	mutex_unlock(&dev->struct_mutex);
+	intel_atomic_commit_cleanup_planes(state);
 
 	drm_atomic_helper_commit_cleanup_done(state);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 930268afa6c1..bc7e84afdd38 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1265,10 +1265,6 @@ __intel_framebuffer_create(struct drm_device *dev,
 void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe);
 void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe);
 void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe);
-int intel_prepare_plane_fb(struct drm_plane *plane,
-			   struct drm_plane_state *new_state);
-void intel_cleanup_plane_fb(struct drm_plane *plane,
-			    struct drm_plane_state *old_state);
 int intel_plane_atomic_get_property(struct drm_plane *plane,
 				    const struct drm_plane_state *state,
 				    struct drm_property *property,
-- 
2.9.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux