Skip to contentSkip to conversation

drm/i915: use PIPE_CONTROL instruction on 965+

PATCH New Jesse Barnes 1 participant 1 message Apr 20, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 drm/i915: use PIPE_CONTROL instruction on 965+

...and hang your box even faster.

Signature · 1 line
Jesse Barnes, Intel Open Source Technology Center
drivers/gpu/drm/i915/i915_drv.h +3 -0
index 790fef3..11c25ab 100644
@@ -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;
drivers/gpu/drm/i915/i915_gem.c +105 -27

183 lines not on this page · raw message

drivers/gpu/drm/i915/i915_irq.c +27 -10
index 7701cbd..13283ed 100644
@@ -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;
 
drivers/gpu/drm/i915/i915_reg.h +9 -0
index 527d30a..6ecf53c 100644
@@ -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)