Skip to content

Commit 1a8f00d

Browse files
icklegregkh
authored andcommitted
drm/i915: Flush the pending flips on the CRTC before modification
commit 5bb6164 upstream. This was meant to be the purpose of the intel_crtc_wait_for_pending_flips() function which is called whilst preparing the CRTC for a modeset or before disabling. However, as Ville Syrjala pointed out, we set the pending flip notification on the old framebuffer that is no longer attached to the CRTC by the time we come to flush the pending operations. Instead, we can simply wait on the pending unpin work to be finished on this CRTC, knowning that the hardware has therefore finished modifying the registers, before proceeding with our direct access. Fixes i-g-t/flip_test on non-pch platforms. pch platforms simply schedule the flip immediately when the pipe is disabled, leading to other funny issues. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> [danvet: Added i-g-t note and cc: stable] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 57a38d9 commit 1a8f00d

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

drivers/gpu/drm/i915/intel_display.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,13 +2823,34 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
28232823
udelay(100);
28242824
}
28252825

2826+
static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
2827+
{
2828+
struct drm_device *dev = crtc->dev;
2829+
struct drm_i915_private *dev_priv = dev->dev_private;
2830+
unsigned long flags;
2831+
bool pending;
2832+
2833+
if (atomic_read(&dev_priv->mm.wedged))
2834+
return false;
2835+
2836+
spin_lock_irqsave(&dev->event_lock, flags);
2837+
pending = to_intel_crtc(crtc)->unpin_work != NULL;
2838+
spin_unlock_irqrestore(&dev->event_lock, flags);
2839+
2840+
return pending;
2841+
}
2842+
28262843
static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
28272844
{
28282845
struct drm_device *dev = crtc->dev;
2846+
struct drm_i915_private *dev_priv = dev->dev_private;
28292847

28302848
if (crtc->fb == NULL)
28312849
return;
28322850

2851+
wait_event(dev_priv->pending_flip_queue,
2852+
!intel_crtc_has_pending_flip(crtc));
2853+
28332854
mutex_lock(&dev->struct_mutex);
28342855
intel_finish_fb(crtc->fb);
28352856
mutex_unlock(&dev->struct_mutex);
@@ -6149,9 +6170,8 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
61496170

61506171
atomic_clear_mask(1 << intel_crtc->plane,
61516172
&obj->pending_flip.counter);
6152-
if (atomic_read(&obj->pending_flip) == 0)
6153-
wake_up(&dev_priv->pending_flip_queue);
61546173

6174+
wake_up(&dev_priv->pending_flip_queue);
61556175
schedule_work(&work->work);
61566176

61576177
trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);

0 commit comments

Comments
 (0)