]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drm/i915: don't queue flips during a flip pending event
authorJesse Barnes <jbarnes@virtuousgeek.org>
Mon, 5 Apr 2010 21:03:51 +0000 (14:03 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 2 Aug 2010 17:30:04 +0000 (10:30 -0700)
commit 83f7fd055eb3f1e843803cd906179d309553967b upstream.

Hardware will set the flip pending ISR bit as soon as it receives the
flip instruction, and (supposedly) clear it once the flip completes
(e.g. at the next vblank).  If we try to send down a flip instruction
while the ISR bit is set, the hardware can become very confused, and we
may never receive the corresponding flip pending interrupt, effectively
hanging the chip.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/gpu/drm/i915/intel_display.c

index e53d07c2dfe02d71c79d9c60223265010534f3b1..188f50ee1f43fdbcc0a8361d72af55afa7f61f70 100644 (file)
@@ -4232,6 +4232,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        unsigned long flags;
        int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
        int ret, pipesrc;
+       u32 flip_mask;
        RING_LOCALS;
 
        work = kzalloc(sizeof *work, GFP_KERNEL);
@@ -4282,6 +4283,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        atomic_inc(&obj_priv->pending_flip);
        work->pending_flip_obj = obj;
 
+       if (intel_crtc->plane)
+               flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+       else
+               flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
+
+       /* Wait for any previous flip to finish */
+       if (IS_GEN3(dev))
+               while (I915_READ(ISR) & flip_mask)
+                       ;
+
        BEGIN_LP_RING(4);
        if (IS_I965G(dev)) {
                OUT_RING(MI_DISPLAY_FLIP |