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