The Intel driver continues to call modeset before installing the irq
handler.  I discussed this issue several months ago, but have only
recently become painfully aware of the deeper issues.  Things seem to
work ok, when you first start X, due to the fact that nothing is
actually waiting on vblanks before the handler gets installed.  During a
Vt switch however, what I found was that with gears running synced to
vblank while switching, pre-modeset says that vblanks are on and enables
the pipestat registers.  post-modeset schedules them to be disabled at
some point in the future.  At this point, vblank_enabled = 1.  Now, the
interrupt handler gets installed, in preinstall it wipes out both
pipestat registers and again in postinstall, clearing status bits this
time.  That means that vblank_enabled is 1 and pipestat is empty.  As
long as there is a consumer asking for vblank, vblank_disable_fn never
fires to clean all of this mess up.  vblank_get won't ever actually turn
vblanks back on, because it thinks they are already on.  So the client
just hangs there.

I think that all of the libdrm code to deal with clients stalling on
vblank was probably not needed.  What happens now, is that while you are
switched away or in dpms sleep, the client requesting vblank just
repeatedly fires the timeout, rather than just stalling until you come
back and seeing that the vblank counter has jumped way ahead of it and
going on.  As it is now, it continues to render one frame / sec while it
is offscreen.


Here are the relevant bits diffed against my kernel code.

@@ -408,11 +412,8 @@
 int i915_enable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *)
dev->dev_private;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       u32 pipeconf;
 
-       pipeconf = I915_READ(pipeconf_reg);
-       if (!(pipeconf & PIPEACONF_ENABLE))
+       if (!i915_pipe_enabled(dev, pipe))
                return -EINVAL;
 
        DRM_SPINLOCK(&dev_priv->user_irq_lock);
@@ -503,8 +504,6 @@
        atomic_set_int(&dev_priv->irq_received, 0);
 
        I915_WRITE(HWSTAM, 0xeffe);
-       I915_WRITE(PIPEASTAT, 0);
-       I915_WRITE(PIPEBSTAT, 0);
        I915_WRITE(IMR, 0xffffffff);
        I915_WRITE(IER, 0x0);
        (void) I915_READ(IER);
@@ -521,12 +520,14 @@
        /* Unmask the interrupts that we always want on. */
        dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
 
-       dev_priv->pipestat[0] = 0;
-       dev_priv->pipestat[1] = 0;
-
        /* Disable pipe interrupt enables, clear pending pipe status */
-       I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
-       I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
+       /*
+        * If you driver is going to be brain-damaged and setup
+        * vblank interrupts before you install the handler, then
+        * you can't nuke it here.
+        */ 
+       I915_WRITE(PIPEASTAT, dev_priv->pipestat[0] | 0x8000ffff);
+       I915_WRITE(PIPEBSTAT, dev_priv->pipestat[1] | 0x8000ffff);
 
        /* Clear pending interrupt status */
        I915_WRITE(IIR, I915_READ(IIR));


-- 
Robert Noland <rnol...@2hip.net>
2 Hip Networks

Attachment: signature.asc
Description: This is a digitally signed message part

------------------------------------------------------------------------------
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to