...and hang your box even faster.

-- 
Jesse Barnes, Intel Open Source Technology Center

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 790fef3..11c25ab 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -240,11 +240,14 @@ typedef struct drm_i915_private {
 
        drm_dma_handle_t *status_page_dmah;
        void *hw_status_page;
+       void *seqno_page;
        dma_addr_t dma_status_page;
        uint32_t counter;
        unsigned int status_gfx_addr;
+       unsigned int seqno_gfx_addr;
        drm_local_map_t hws_map;
        struct drm_gem_object *hws_obj;
+       struct drm_gem_object *seqno_obj;
        struct drm_gem_object *pwrctx;
 
        struct resource mch_res;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b85727c..731eca5 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1621,13 +1621,24 @@ i915_add_request(struct drm_device *dev, struct 
drm_file *file_priv,
        if (dev_priv->mm.next_gem_seqno == 0)
                dev_priv->mm.next_gem_seqno++;
 
-       BEGIN_LP_RING(4);
-       OUT_RING(MI_STORE_DWORD_INDEX);
-       OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-       OUT_RING(seqno);
+       if (IS_I965G(dev)) {
+               BEGIN_LP_RING(4);
+               OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+                        PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
+                        PIPE_CONTROL_NOTIFY);
+               OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+               OUT_RING(seqno);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       } else {
+               BEGIN_LP_RING(4);
+               OUT_RING(MI_STORE_DWORD_INDEX);
+               OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+               OUT_RING(seqno);
 
-       OUT_RING(MI_USER_INTERRUPT);
-       ADVANCE_LP_RING();
+               OUT_RING(MI_USER_INTERRUPT);
+               ADVANCE_LP_RING();
+       }
 
        DRM_DEBUG_DRIVER("%d\n", seqno);
 
@@ -1666,17 +1677,24 @@ static uint32_t
 i915_retire_commands(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
        uint32_t flush_domains = 0;
        RING_LOCALS;
 
        /* The sampler always gets flushed on i965 (sigh) */
-       if (IS_I965G(dev))
+       if (IS_I965G(dev)) {
                flush_domains |= I915_GEM_DOMAIN_SAMPLER;
-       BEGIN_LP_RING(2);
-       OUT_RING(cmd);
-       OUT_RING(0); /* noop */
-       ADVANCE_LP_RING();
+               BEGIN_LP_RING(4);
+               OUT_RING(GFX_OP_PIPE_CONTROL);
+               OUT_RING(0); /* unused addr */
+               OUT_RING(0); /* unused data */
+               OUT_RING(0); /* unused data */
+               ADVANCE_LP_RING();
+       } else {
+               BEGIN_LP_RING(2);
+               OUT_RING(MI_FLUSH | MI_NO_WRITE_FLUSH);
+               OUT_RING(0); /* noop */
+               ADVANCE_LP_RING();
+       }
        return flush_domains;
 }
 
@@ -1751,7 +1769,10 @@ i915_get_gem_seqno(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
 
-       return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
+       if (IS_I965G(dev))
+               return ((volatile u32 *)(dev_priv->seqno_page))[0];
+       else
+               return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
 }
 
 /**
@@ -1930,29 +1951,45 @@ i915_gem_flush(struct drm_device *dev,
                 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
                 * are flushed at any MI_FLUSH.
                 */
-
-               cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
-               if ((invalidate_domains|flush_domains) &
-                   I915_GEM_DOMAIN_RENDER)
-                       cmd &= ~MI_NO_WRITE_FLUSH;
-               if (!IS_I965G(dev)) {
+               if (IS_I965G(dev)) {
+                       cmd = GFX_OP_PIPE_CONTROL;
+                       if ((invalidate_domains|flush_domains) &
+                           I915_GEM_DOMAIN_RENDER)
+                               cmd |= PIPE_CONTROL_WC_FLUSH;
+                       if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
+                               cmd |= PIPE_CONTROL_TC_FLUSH;
+                       if (IS_GEN6(dev) &&
+                           invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
+                               cmd |= PIPE_CONTROL_IS_FLUSH;
+                       BEGIN_LP_RING(4);
+                       OUT_RING(cmd);
+                       OUT_RING(0); /* unused addr */
+                       OUT_RING(0); /* unused data */
+                       OUT_RING(0); /* unused data */
+                       ADVANCE_LP_RING();
+               } else {
+                       cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
+                       if ((invalidate_domains|flush_domains) &
+                           I915_GEM_DOMAIN_RENDER)
+                               cmd &= ~MI_NO_WRITE_FLUSH;
                        /*
                         * On the 965, the sampler cache always gets flushed
                         * and this bit is reserved.
                         */
                        if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
                                cmd |= MI_READ_FLUSH;
-               }
-               if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
-                       cmd |= MI_EXE_FLUSH;
+                       if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
+                               cmd |= MI_EXE_FLUSH;
 
 #if WATCH_EXEC
-               DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
+                       DRM_INFO("%s: queue flush %08x to ring\n", __func__,
+                                cmd);
 #endif
-               BEGIN_LP_RING(2);
-               OUT_RING(cmd);
-               OUT_RING(MI_NOOP);
-               ADVANCE_LP_RING();
+                       BEGIN_LP_RING(2);
+                       OUT_RING(cmd);
+                       OUT_RING(MI_NOOP);
+                       ADVANCE_LP_RING();
+               }
        }
 }
 
@@ -4594,6 +4631,37 @@ i915_gem_init_hws(struct drm_device *dev)
        }
        DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
 
+       /* Set up pipe control qword area */
+       /* FIXME: cleanup hws above if this fails */
+       if (IS_I965G(dev)) {
+               obj = drm_gem_object_alloc(dev, 4096);
+               if (obj == NULL) {
+                       DRM_ERROR("Failed to allocate seqno page\n");
+                       return -ENOMEM;
+               }
+               obj_priv = to_intel_bo(obj);
+               obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
+
+               ret = i915_gem_object_pin(obj, 4096);
+               if (ret != 0) {
+                       drm_gem_object_unreference(obj);
+                       return ret;
+               }
+
+               dev_priv->seqno_gfx_addr = obj_priv->gtt_offset;
+               dev_priv->seqno_page =  kmap(obj_priv->pages[0]);
+               if (dev_priv->seqno_page == NULL) {
+                       DRM_ERROR("Failed to map seqno page.\n");
+                       i915_gem_object_unpin(obj);
+                       drm_gem_object_unreference(obj);
+                       return -EINVAL;
+               }
+               dev_priv->seqno_obj = obj;
+               memset(dev_priv->seqno_page, 0, PAGE_SIZE);
+               DRM_ERROR("seqno gfx offset: 0x%08x, kmap: %p\n",
+                         dev_priv->seqno_gfx_addr, dev_priv->seqno_page);
+       }
+
        return 0;
 }
 
@@ -4618,6 +4686,16 @@ i915_gem_cleanup_hws(struct drm_device *dev)
        memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
        dev_priv->hw_status_page = NULL;
 
+       if (IS_I965G(dev)) {
+               obj = dev_priv->seqno_obj;
+               obj_priv = to_intel_bo(obj);
+               kunmap(obj_priv->pages[0]);
+               i915_gem_object_unpin(obj);
+               drm_gem_object_unreference(obj);
+               dev_priv->seqno_obj = NULL;
+
+               dev_priv->seqno_page = NULL;
+       }
        /* Write high address into HWS_PGA when disabling. */
        I915_WRITE(HWS_PGA, 0x1ffff000);
 }
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7701cbd..13283ed 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -51,9 +51,6 @@
         I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |  \
         I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 
-/** Interrupts that we mask and unmask at runtime. */
-#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
-
 #define I915_PIPE_VBLANK_STATUS        (PIPE_START_VBLANK_INTERRUPT_STATUS |\
                                 PIPE_VBLANK_INTERRUPT_STATUS)
 
@@ -352,7 +349,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
                                READ_BREADCRUMB(dev_priv);
        }
 
-       if (gt_iir & GT_USER_INTERRUPT) {
+       if (gt_iir & GT_PIPE_NOTIFY) {
                u32 seqno = i915_get_gem_seqno(dev);
                dev_priv->mm.irq_gem_seqno = seqno;
                trace_i915_gem_request_complete(dev, seqno);
@@ -361,6 +358,9 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
                mod_timer(&dev_priv->hangcheck_timer, jiffies + 
DRM_I915_HANGCHECK_PERIOD);
        }
 
+       if (gt_iir & GT_SYNC_STATUS)
+               DRM_ERROR("sync status interrupt\n");
+
        if (de_iir & DE_GSE)
                ironlake_opregion_gse_intr(dev);
 
@@ -1005,13 +1005,19 @@ void i915_user_irq_get(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
+       u32 irq;
+
+       if (IS_I965G(dev))
+               irq = I915_PIPE_CONTROL_NOTIFY_INTERRUPT;
+       else
+               irq = I915_USER_INTERRUPT;
 
        spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
        if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
                if (HAS_PCH_SPLIT(dev))
-                       ironlake_enable_graphics_irq(dev_priv, 
GT_USER_INTERRUPT);
+                       ironlake_enable_graphics_irq(dev_priv, GT_SYNC_STATUS | 
GT_PIPE_NOTIFY);
                else
-                       i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
+                       i915_enable_irq(dev_priv, irq);
        }
        spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
 }
@@ -1020,14 +1026,20 @@ void i915_user_irq_put(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
+       u32 irq;
+
+       if (IS_I965G(dev))
+               irq = I915_PIPE_CONTROL_NOTIFY_INTERRUPT;
+       else
+               irq = I915_USER_INTERRUPT;
 
        spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
        BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
        if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
                if (HAS_PCH_SPLIT(dev))
-                       ironlake_disable_graphics_irq(dev_priv, 
GT_USER_INTERRUPT);
+                       ironlake_disable_graphics_irq(dev_priv, GT_SYNC_STATUS 
| GT_PIPE_NOTIFY);
                else
-                       i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+                       i915_disable_irq(dev_priv, irq);
        }
        spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
 }
@@ -1309,7 +1321,7 @@ static int ironlake_irq_postinstall(struct drm_device 
*dev)
        /* enable kind of interrupts always enabled */
        u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
                           DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
-       u32 render_mask = GT_USER_INTERRUPT;
+       u32 render_mask = GT_SYNC_STATUS | GT_PIPE_NOTIFY;
        u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
                           SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
 
@@ -1383,7 +1395,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
 int i915_driver_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
+       u32 enable_mask = I915_INTERRUPT_ENABLE_FIX;
        u32 error_mask;
 
        DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
@@ -1393,6 +1405,11 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        if (HAS_PCH_SPLIT(dev))
                return ironlake_irq_postinstall(dev);
 
+       if (IS_I965G(dev))
+               enable_mask |= I915_PIPE_CONTROL_NOTIFY_INTERRUPT;
+       else
+               enable_mask |= I915_USER_INTERRUPT;
+
        /* Unmask the interrupts that we always want on. */
        dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 527d30a..6ecf53c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -230,6 +230,14 @@
 #define   ASYNC_FLIP                (1<<22)
 #define   DISPLAY_PLANE_A           (0<<20)
 #define   DISPLAY_PLANE_B           (1<<20)
+#define GFX_OP_PIPE_CONTROL    ((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
+#define   PIPE_CONTROL_QW_WRITE        (1<<14)
+#define   PIPE_CONTROL_WC_FLUSH        (1<<12)
+#define   PIPE_CONTROL_IS_FLUSH        (1<<11) /* MBZ on Ironlake */
+#define   PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */
+#define   PIPE_CONTROL_ISP_DIS (1<<9)
+#define   PIPE_CONTROL_NOTIFY  (1<<8)
+#define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
 
 /*
  * Fence registers
@@ -2339,6 +2347,7 @@
 #define DEIER   0x4400c
 
 /* GT interrupt */
+#define GT_PIPE_NOTIFY         (1 << 4)
 #define GT_SYNC_STATUS          (1 << 2)
 #define GT_USER_INTERRUPT       (1 << 0)
 
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to