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 | 61 ++++++++++++++++++++++++------- drivers/gpu/drm/i915/intel_drv.h | 4 -- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index cb5594411bb6..4ed5b2e49691 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -192,8 +192,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 6c817215f61a..69720a126c67 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14146,7 +14146,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) { @@ -14241,7 +14241,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) { @@ -14260,6 +14260,50 @@ 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) { @@ -14280,14 +14324,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) @@ -14614,9 +14651,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 f5975fe4553d..610f2f969a9a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1292,10 +1292,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.10.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx