summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-04-05 14:03:51 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-02 10:30:04 -0700
commit430155d430dd1496ecaebc8035c79dc5506ae4f5 (patch)
treec3917d6753f66c921b792be9274eaedb40b3de76 /drivers
parentaa9d89cdfcd0ca32a36be9235023c7889c4b6b0b (diff)
drm/i915: don't queue flips during a flip pending event
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e53d07c2dfe0..188f50ee1f43 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -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 |