i915: Only turn on user IRQs when they are needed.
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Tue, 5 Sep 2006 12:23:18 +0000 (14:23 +0200)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Tue, 5 Sep 2006 12:23:18 +0000 (14:23 +0200)
linux-core/i915_fence.c
shared-core/i915_drv.h
shared-core/i915_irq.c

index 673ebd0..80ef3ab 100644 (file)
@@ -58,13 +58,9 @@ static void i915_perform_flush(drm_device_t * dev)
                        diff = sequence - fm->exe_flush_sequence;
                        if (diff < driver->wrap_diff) {
                                fm->pending_exe_flush = 0;
-                               /*
-                                * Turn off user IRQs
-                                */
+                               i915_user_irq_off(dev_priv);
                        } else {
-                               /*
-                                * Turn on user IRQs
-                                */
+                               i915_user_irq_on(dev_priv);
                        }
                }
        }
index 8bf82ed..f8d0874 100644 (file)
@@ -103,6 +103,10 @@ typedef struct drm_i915_private {
        struct mem_block *agp_heap;
        unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
        int vblank_pipe;
+        spinlock_t user_irq_lock;
+        int user_irq_refcount;
+        uint32_t irq_enable_reg;
+        int irq_enabled;
 
 #ifdef I915_HAVE_FENCE
         uint32_t flush_sequence;
@@ -139,6 +143,8 @@ extern void i915_driver_irq_uninstall(drm_device_t * dev);
 extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
 extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
 extern int i915_emit_irq(drm_device_t * dev);
+extern void i915_user_irq_on(drm_i915_private_t *dev_priv);
+extern void i915_user_irq_off(drm_i915_private_t *dev_priv);
 
 /* i915_mem.c */
 extern int i915_mem_alloc(DRM_IOCTL_ARGS);
index 4195555..a3f6a03 100644 (file)
@@ -102,6 +102,29 @@ int i915_emit_irq(drm_device_t * dev)
 
 }
 
+void i915_user_irq_on(drm_i915_private_t *dev_priv)
+{
+
+       spin_lock(&dev_priv->user_irq_lock);
+       if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount > 0)){
+               dev_priv->irq_enable_reg |= USER_INT_FLAG;
+               I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+       }
+       spin_unlock(&dev_priv->user_irq_lock);
+
+}
+               
+void i915_user_irq_off(drm_i915_private_t *dev_priv)
+{
+       spin_lock(&dev_priv->user_irq_lock);
+       if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
+               dev_priv->irq_enable_reg &= ~USER_INT_FLAG;
+               I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+       }
+       spin_unlock(&dev_priv->user_irq_lock);
+}
+               
+
 static int i915_wait_irq(drm_device_t * dev, int irq_nr)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -114,9 +137,11 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
                return 0;
 
        dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-
+       
+       i915_user_irq_on(dev_priv);
        DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
                    READ_BREADCRUMB(dev_priv) >= irq_nr);
+       i915_user_irq_off(dev_priv);
 
        if (ret == DRM_ERR(EBUSY)) {
                DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
@@ -211,7 +236,11 @@ static int i915_enable_interrupt (drm_device_t *dev)
                          __FUNCTION__, dev_priv->vblank_pipe);
                return DRM_ERR(EINVAL);
        }
-       I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
+       dev_priv->user_irq_lock = SPIN_LOCK_UNLOCKED;
+       dev_priv->user_irq_refcount = 0;
+       dev_priv->irq_enable_reg = flag;
+       I915_WRITE16(I915REG_INT_ENABLE_R, flag);
+       dev_priv->irq_enabled = 1;
        return 0;
 }
 
@@ -290,6 +319,7 @@ void i915_driver_irq_uninstall(drm_device_t * dev)
        if (!dev_priv)
                return;
 
+       dev_priv->irq_enabled = 0;
        I915_WRITE16(I915REG_HWSTAM, 0xffff);
        I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
        I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);