public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Ben Widawsky <benjamin.widawsky@intel.com>
To: Intel GFX <intel-gfx@lists.freedesktop.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>,
	Ben Widawsky <ben@bwidawsk.net>,
	Ben Widawsky <benjamin.widawsky@intel.com>
Subject: [PATCH 11/62] drm/i915/bdw: Implement interrupt changes
Date: Sat,  2 Nov 2013 21:07:09 -0700	[thread overview]
Message-ID: <1383451680-11173-12-git-send-email-benjamin.widawsky@intel.com> (raw)
In-Reply-To: <1383451680-11173-1-git-send-email-benjamin.widawsky@intel.com>

The interrupt handling implementation remains the same as previous
generations with the 4 types of registers, status, identity, mask, and
enable. However the layout of where the bits go have changed entirely.
To address these changes, all of the interrupt vfuncs needed special
gen8 code.

The way it works is there is a top level status register now which
informs the interrupt service routine which unit caused the interrupt,
and therefore which interrupt registers to read to process the
interrupt. For display the division is quite logical, a set of interrupt
registers for each pipe, and in addition to those, a set each for "misc"
and port.

For GT the things get a bit hairy, as seen by the code. Each of the GT
units has it's own bits defined. They all look *very similar* and
resides in 16 bits of a GT register. As an example, RCS and BCS share
register 0. To compact the code a bit, at a slight expense to
complexity, this is exactly how the code works as well. 2 structures are
added to the ring buffer so that our ring buffer interrupt handling code
knows which ring shares the interrupt registers, and a shift value (ie.
the top or bottom 16 bits of the register).

The above allows us to kept the interrupt register caching scheme, the
per interrupt enables, and the code to mask and unmask interrupts
relatively clean (again at the cost of some more complexity).

Most of the GT units mentioned above are command streamers, and so the
symmetry should work quite well for even the yet to be implemented rings
which Broadwell adds.

v2: Fixes up a couple of bugs, and is more verbose about errors in the
Broadwell interrupt handler.

v3: fix DE_MISC IER offset

v4: Simplify interrupts:
I totally misread the docs the first time I implemented interrupts, and
so this should greatly simplify the mess. Unlike GEN6, we never touch
the regular mask registers in irq_get/put.

v5: Rebased on to of recent pch hotplug setup changes.

v6: Fixup on top of moving num_pipes to intel_info.

v7: Rebased on top of Egbert Eich's hpd irq handling rework. Also
wired up ibx_hpd_irq_setup for gen8.

v8: Rebase on top of Jani's asle handling rework.

v9: Rebase on top of Ben's VECS enabling for Haswell, where he
unfortunately went OCD on the gt irq #defines. Not that they're still
not yet fully consistent:
- Used the GT_RENDER_ #defines + bdw shifts.
- Dropped the shift from the L3_PARITY stuff, seemed clearer.
- s/irq_refcount/irq_refcount.gt/

v10: Squash in VECS enabling patches and the gen8_gt_irq_handler
refactoring from Zhao Yakui <yakui.zhao@intel.com>

v11: Rebase on top of the interrupt cleanups in upstream.

v12: Rebase on top of Ben's DPF changes in upstream.

v13: Drop bdw from the HAS_L3_DPF feature flag for now, it's unclear what
exactly needs to be done. Requested by Ben.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net> (v4)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.h         |   5 +-
 drivers/gpu/drm/i915/i915_irq.c         | 327 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h         |  63 ++++++
 drivers/gpu/drm/i915/intel_ringbuffer.c |  90 +++++++--
 4 files changed, 473 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c1b178a..83d016c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1315,7 +1315,10 @@ typedef struct drm_i915_private {
 	struct mutex dpio_lock;
 
 	/** Cached value of IMR to avoid reads in updating the bitfield */
-	u32 irq_mask;
+	union {
+		u32 irq_mask;
+		u32 de_irq_mask[I915_MAX_PIPES];
+	};
 	u32 gt_irq_mask;
 	u32 pm_irq_mask;
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a9f0cb6..3f0c9e3 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1118,6 +1118,56 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 		ivybridge_parity_error_irq_handler(dev, gt_iir);
 }
 
+static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
+				struct drm_i915_private *dev_priv,
+				u32 master_ctl)
+{
+	u32 rcs, bcs, vcs;
+	uint32_t tmp = 0;
+	irqreturn_t ret = IRQ_NONE;
+
+	if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
+		tmp = I915_READ(GEN8_GT_IIR(0));
+		if (tmp) {
+			ret = IRQ_HANDLED;
+			rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
+			bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
+			if (rcs & GT_RENDER_USER_INTERRUPT)
+				notify_ring(dev, &dev_priv->ring[RCS]);
+			if (bcs & GT_RENDER_USER_INTERRUPT)
+				notify_ring(dev, &dev_priv->ring[BCS]);
+			I915_WRITE(GEN8_GT_IIR(0), tmp);
+		} else
+			DRM_ERROR("The master control interrupt lied (GT0)!\n");
+	}
+
+	if (master_ctl & GEN8_GT_VCS1_IRQ) {
+		tmp = I915_READ(GEN8_GT_IIR(1));
+		if (tmp) {
+			ret = IRQ_HANDLED;
+			vcs = tmp >> GEN8_VCS1_IRQ_SHIFT;
+			if (vcs & GT_RENDER_USER_INTERRUPT)
+				notify_ring(dev, &dev_priv->ring[VCS]);
+			I915_WRITE(GEN8_GT_IIR(1), tmp);
+		} else
+			DRM_ERROR("The master control interrupt lied (GT1)!\n");
+	}
+
+	if (master_ctl & GEN8_GT_VECS_IRQ) {
+		tmp = I915_READ(GEN8_GT_IIR(3));
+		if (tmp) {
+			ret = IRQ_HANDLED;
+			vcs = tmp >> GEN8_VECS_IRQ_SHIFT;
+			if (vcs & GT_RENDER_USER_INTERRUPT)
+				notify_ring(dev, &dev_priv->ring[VECS]);
+			I915_WRITE(GEN8_GT_IIR(3), tmp);
+		} else
+			DRM_ERROR("The master control interrupt lied (GT3)!\n");
+	}
+
+	return ret;
+}
+
 #define HPD_STORM_DETECT_PERIOD 1000
 #define HPD_STORM_THRESHOLD 5
 
@@ -1699,6 +1749,85 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 	return ret;
 }
 
+static irqreturn_t gen8_irq_handler(int irq, void *arg)
+{
+	struct drm_device *dev = arg;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 master_ctl;
+	irqreturn_t ret = IRQ_NONE;
+	uint32_t tmp = 0;
+
+	atomic_inc(&dev_priv->irq_received);
+
+	master_ctl = I915_READ(GEN8_MASTER_IRQ);
+	master_ctl &= ~DE_MASTER_IRQ_CONTROL;
+	if (!master_ctl)
+		return IRQ_NONE;
+
+	if ((master_ctl & ~GEN8_RSVD_IRQS) == 0) {
+		DRM_ERROR("Only received RSVD IRQs 0x%08x\n", master_ctl);
+		return IRQ_NONE;
+	}
+
+	I915_WRITE(GEN8_MASTER_IRQ, 0);
+
+	/* NB: Posting read isn't necessary here because we're required to do
+	 * another read no matter what
+	POSTING_READ(GEN8_MASTER_IRQ);
+	*/
+
+	ret = gen8_gt_irq_handler(dev, dev_priv, master_ctl);
+
+	if (master_ctl & GEN8_DE_MISC_IRQ) {
+		tmp = I915_READ(GEN8_DE_MISC_IIR);
+		if (tmp) {
+			I915_WRITE(GEN8_DE_MISC_IIR, tmp);
+			ret = IRQ_HANDLED;
+		}
+
+		if (tmp & GEN8_DE_MISC_GSE)
+			intel_opregion_asle_intr(dev);
+		else if (tmp)
+			DRM_ERROR("Unexpected DE Misc interrupt\n");
+		else
+			DRM_ERROR("The master control interrupt lied (DE MISC)!\n");
+
+	}
+
+	if (master_ctl & GEN8_DE_IRQS) {
+		int de_ret = 0;
+		int pipe;
+		for_each_pipe(pipe) {
+			uint32_t pipe_iir;
+
+		        pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe));
+			if (pipe_iir & _PIPE_VBLANK) {
+				drm_handle_vblank(dev, pipe);
+			}
+			if (pipe_iir & _PIPE_FLIP_DONE) {
+				intel_prepare_page_flip(dev, pipe);
+				intel_finish_page_flip_plane(dev, pipe);
+			}
+
+			if (pipe_iir & GEN8_DE_PIPE_IRQ_ERRORS)
+				DRM_ERROR("Errors on pipe %c\n", 'A' + pipe);
+
+			if (pipe_iir) {
+				de_ret++;
+				ret = IRQ_HANDLED;
+				I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
+			}
+		}
+		if (!de_ret)
+			DRM_ERROR("The master control interrupt lied (DE PIPE)!\n");
+	}
+
+	I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
+	POSTING_READ(GEN8_MASTER_IRQ);
+
+	return ret;
+}
+
 static void i915_error_wake_up(struct drm_i915_private *dev_priv,
 			       bool reset_completed)
 {
@@ -2052,6 +2181,25 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
 	return 0;
 }
 
+static int gen8_enable_vblank(struct drm_device *dev, int pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long irqflags;
+	uint32_t imr;
+
+	if (!i915_pipe_enabled(dev, pipe))
+		return -EINVAL;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	imr = I915_READ(GEN8_DE_PIPE_IMR(pipe));
+	if ((imr & _PIPE_VBLANK) == 1) {
+		I915_WRITE(GEN8_DE_PIPE_IMR(pipe), imr & ~_PIPE_VBLANK);
+		POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
+	}
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+	return 0;
+}
+
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
@@ -2100,6 +2248,24 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
+static void gen8_disable_vblank(struct drm_device *dev, int pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long irqflags;
+	uint32_t imr;
+
+	if (!i915_pipe_enabled(dev, pipe))
+		return;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	imr = I915_READ(GEN8_DE_PIPE_IMR(pipe));
+	if ((imr & _PIPE_VBLANK) == 0) {
+		I915_WRITE(GEN8_DE_PIPE_IMR(pipe), imr | _PIPE_VBLANK);
+		POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
+	}
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
 static u32
 ring_last_seqno(struct intel_ring_buffer *ring)
 {
@@ -2430,6 +2596,51 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
 	POSTING_READ(VLV_IER);
 }
 
+static void gen8_irq_preinstall(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe;
+
+	atomic_set(&dev_priv->irq_received, 0);
+
+	I915_WRITE(GEN8_MASTER_IRQ, 0);
+	POSTING_READ(GEN8_MASTER_IRQ);
+
+	/* IIR can theoretically queue up two events. Be paranoid */
+#define GEN8_IRQ_INIT_NDX(type, which) \
+	I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
+	POSTING_READ(GEN8_##type##_IMR(which)); \
+	I915_WRITE(GEN8_##type##_IER(which), 0); \
+	I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
+	POSTING_READ(GEN8_##type##_IIR(which)); \
+	I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff)
+
+#define GEN8_IRQ_INIT(type) \
+	I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \
+	POSTING_READ(GEN8_##type##_IMR); \
+	I915_WRITE(GEN8_##type##_IER, 0); \
+	I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
+	POSTING_READ(GEN8_##type##_IIR); \
+	I915_WRITE(GEN8_##type##_IIR, 0xffffffff)
+
+	GEN8_IRQ_INIT_NDX(GT, 0);
+	GEN8_IRQ_INIT_NDX(GT, 1);
+	GEN8_IRQ_INIT_NDX(GT, 2);
+	GEN8_IRQ_INIT_NDX(GT, 3);
+
+	for_each_pipe(pipe) {
+		GEN8_IRQ_INIT_NDX(DE_PIPE, pipe);
+	}
+
+	GEN8_IRQ_INIT(DE_PORT);
+	GEN8_IRQ_INIT(DE_MISC);
+	GEN8_IRQ_INIT(PCU);
+#undef GEN8_IRQ_INIT
+#undef GEN8_IRQ_INIT_NDX
+
+	POSTING_READ(GEN8_PCU_IIR);
+}
+
 static void ibx_hpd_irq_setup(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -2635,6 +2846,114 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
+static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+	int i;
+
+	/* These are interrupts we'll toggle with the ring mask register */
+	uint32_t gt_interrupts[] = {
+		GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
+			GT_RENDER_L3_PARITY_ERROR_INTERRUPT |
+			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT,
+		GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT |
+			GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT,
+		0,
+		GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT
+		};
+
+	for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++) {
+		u32 tmp = I915_READ(GEN8_GT_IIR(i));
+		if (tmp)
+			DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n",
+				  i, tmp);
+		I915_WRITE(GEN8_GT_IMR(i), ~gt_interrupts[i]);
+		I915_WRITE(GEN8_GT_IER(i), gt_interrupts[i]);
+	}
+	POSTING_READ(GEN8_GT_IER(0));
+}
+
+static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	uint32_t de_pipe_enables = _PIPE_FLIP_DONE |
+				   _PIPE_SCAN_LINE_EVENT |
+				   _PIPE_VBLANK |
+				   GEN8_DE_PIPE_IRQ_ERRORS;
+	int pipe;
+	dev_priv->de_irq_mask[PIPE_A] = ~de_pipe_enables;
+	dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_enables;
+	dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_enables;
+
+	for_each_pipe(pipe) {
+		u32 tmp = I915_READ(GEN8_DE_PIPE_IIR(pipe));
+		if (tmp)
+			DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n",
+				  pipe, tmp);
+		I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
+		I915_WRITE(GEN8_DE_PIPE_IER(pipe), de_pipe_enables);
+	}
+	POSTING_READ(GEN8_DE_PIPE_ISR(0));
+
+	I915_WRITE(GEN8_DE_PORT_IMR, ~_PORT_DP_A_HOTPLUG);
+	I915_WRITE(GEN8_DE_PORT_IER, _PORT_DP_A_HOTPLUG);
+	POSTING_READ(GEN8_DE_PORT_IER);
+}
+
+static int gen8_irq_postinstall(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	gen8_gt_irq_postinstall(dev_priv);
+	gen8_de_irq_postinstall(dev_priv);
+
+	ibx_irq_postinstall(dev);
+
+	I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
+	POSTING_READ(GEN8_MASTER_IRQ);
+
+	return 0;
+}
+
+static void gen8_irq_uninstall(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe;
+
+	if (!dev_priv)
+		return;
+
+	atomic_set(&dev_priv->irq_received, 0);
+
+	I915_WRITE(GEN8_MASTER_IRQ, 0);
+
+#define GEN8_IRQ_FINI_NDX(type, which) \
+	I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
+	I915_WRITE(GEN8_##type##_IER(which), 0); \
+	I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff)
+
+#define GEN8_IRQ_FINI(type) \
+	I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \
+	I915_WRITE(GEN8_##type##_IER, 0); \
+	I915_WRITE(GEN8_##type##_IIR, 0xffffffff)
+
+	GEN8_IRQ_FINI_NDX(GT, 0);
+	GEN8_IRQ_FINI_NDX(GT, 1);
+	GEN8_IRQ_FINI_NDX(GT, 2);
+	GEN8_IRQ_FINI_NDX(GT, 3);
+
+	for_each_pipe(pipe) {
+		GEN8_IRQ_FINI_NDX(DE_PIPE, pipe);
+	}
+
+	GEN8_IRQ_FINI(DE_PORT);
+	GEN8_IRQ_FINI(DE_MISC);
+	GEN8_IRQ_FINI(PCU);
+#undef GEN8_IRQ_FINI
+#undef GEN8_IRQ_FINI_NDX
+
+	POSTING_READ(GEN8_PCU_IIR);
+}
+
 static void valleyview_irq_uninstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -3414,6 +3733,14 @@ void intel_irq_init(struct drm_device *dev)
 		dev->driver->enable_vblank = valleyview_enable_vblank;
 		dev->driver->disable_vblank = valleyview_disable_vblank;
 		dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
+	} else if (IS_GEN8(dev)) {
+		dev->driver->irq_handler = gen8_irq_handler;
+		dev->driver->irq_preinstall = gen8_irq_preinstall;
+		dev->driver->irq_postinstall = gen8_irq_postinstall;
+		dev->driver->irq_uninstall = gen8_irq_uninstall;
+		dev->driver->enable_vblank = gen8_enable_vblank;
+		dev->driver->disable_vblank = gen8_disable_vblank;
+		dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		dev->driver->irq_handler = ironlake_irq_handler;
 		dev->driver->irq_preinstall = ironlake_irq_preinstall;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index fb6ad89..b801b88 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3989,6 +3989,69 @@
 #define GTIIR   0x44018
 #define GTIER   0x4401c
 
+#define GEN8_MASTER_IRQ			0x44200
+#define  GEN8_PCU_IRQ			(1<<30)
+#define  GEN8_DE_PCH_IRQ		(1<<23)
+#define  GEN8_DE_MISC_IRQ		(1<<22)
+#define  GEN8_DE_PORT_IRQ		(1<<20)
+#define  GEN8_DE_PIPE_C_IRQ		(1<<18)
+#define  GEN8_DE_PIPE_B_IRQ		(1<<17)
+#define  GEN8_DE_PIPE_A_IRQ		(1<<16)
+#define  GEN8_GT_VECS_IRQ		(1<<6)
+#define  GEN8_GT_VCS2_IRQ		(1<<3)
+#define  GEN8_GT_VCS1_IRQ		(1<<2)
+#define  GEN8_GT_BCS_IRQ		(1<<1)
+#define  GEN8_GT_RCS_IRQ		(1<<0)
+/* Lazy definition */
+#define  GEN8_GT_IRQS			0x000000ff
+#define  GEN8_DE_IRQS			0x01ff0000
+#define  GEN8_RSVD_IRQS			0xB700ff00
+
+#define GEN8_GT_ISR(which) (0x44300 + (0x10 * (which)))
+#define GEN8_GT_IMR(which) (0x44304 + (0x10 * (which)))
+#define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which)))
+#define GEN8_GT_IER(which) (0x4430c + (0x10 * (which)))
+
+#define GEN8_BCS_IRQ_SHIFT 16
+#define GEN8_RCS_IRQ_SHIFT 0
+#define GEN8_VCS2_IRQ_SHIFT 16
+#define GEN8_VCS1_IRQ_SHIFT 0
+#define GEN8_VECS_IRQ_SHIFT 0
+
+#define GEN8_DE_PIPE_ISR(pipe) (0x44400 + (0x10 * (pipe)))
+#define GEN8_DE_PIPE_IMR(pipe) (0x44404 + (0x10 * (pipe)))
+#define GEN8_DE_PIPE_IIR(pipe) (0x44408 + (0x10 * (pipe)))
+#define GEN8_DE_PIPE_IER(pipe) (0x4440c + (0x10 * (pipe)))
+#define  _PIPE_UNDERRUN			(1 << 31)
+#define  _PIPE_CDCLK_CRC_ERROR		(1 << 29)
+#define  _PIPE_CURSOR_FAULT		(1 << 10)
+#define  _PIPE_SPRITE_FAULT		(1 << 9)
+#define  _PIPE_PRIMARY_FAULT		(1 << 8)
+#define  _PIPE_SPRITE_FLIP_DONE		(1 << 5)
+#define  _PIPE_FLIP_DONE		(1 << 4)
+#define  _PIPE_SCAN_LINE_EVENT		(1 << 3)
+#define  _PIPE_VBLANK			(1 << 0)
+#define GEN8_DE_PIPE_IRQ_ERRORS	(_PIPE_UNDERRUN | _PIPE_CDCLK_CRC_ERROR | \
+				_PIPE_CURSOR_FAULT | _PIPE_SPRITE_FAULT | \
+				_PIPE_PRIMARY_FAULT)
+
+#define GEN8_DE_PORT_ISR 0x44440
+#define GEN8_DE_PORT_IMR 0x44444
+#define GEN8_DE_PORT_IIR 0x44448
+#define GEN8_DE_PORT_IER 0x4444c
+#define  _PORT_DP_A_HOTPLUG		(1 << 3)
+
+#define GEN8_DE_MISC_ISR 0x44460
+#define GEN8_DE_MISC_IMR 0x44464
+#define GEN8_DE_MISC_IIR 0x44468
+#define GEN8_DE_MISC_IER 0x4446c
+#define  GEN8_DE_MISC_GSE		(1 << 27)
+
+#define GEN8_PCU_ISR 0x444e0
+#define GEN8_PCU_IMR 0x444e4
+#define GEN8_PCU_IIR 0x444e8
+#define GEN8_PCU_IER 0x444ec
+
 #define ILK_DISPLAY_CHICKEN2	0x42004
 /* Required on all Ironlake and Sandybridge according to the B-Spec. */
 #define  ILK_ELPIN_409_SELECT	(1 << 25)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 2dec134..b2161f2 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1066,6 +1066,48 @@ hsw_vebox_put_irq(struct intel_ring_buffer *ring)
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
+static bool
+gen8_ring_get_irq(struct intel_ring_buffer *ring)
+{
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long flags;
+
+	if (!dev->irq_enabled)
+	       return false;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, flags);
+	if (ring->irq_refcount++ == 0) {
+		if (HAS_L3_DPF(dev) && ring->id == RCS)
+			I915_WRITE_IMR(ring, ~(ring->irq_enable_mask |
+						GT_RENDER_L3_PARITY_ERROR_INTERRUPT));
+		else
+			I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
+		POSTING_READ(RING_IMR(ring->mmio_base));
+	}
+	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
+
+	return true;
+}
+
+static void
+gen8_ring_put_irq(struct intel_ring_buffer *ring)
+{
+	struct drm_device *dev = ring->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, flags);
+	if (--ring->irq_refcount == 0) {
+		if (HAS_L3_DPF(dev) && ring->id == RCS)
+			I915_WRITE_IMR(ring, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
+		else
+			I915_WRITE_IMR(ring, ~0);
+		POSTING_READ(RING_IMR(ring->mmio_base));
+	}
+	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
+}
+
 static int
 i965_dispatch_execbuffer(struct intel_ring_buffer *ring,
 			 u32 offset, u32 length,
@@ -1732,8 +1774,13 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 		ring->flush = gen7_render_ring_flush;
 		if (INTEL_INFO(dev)->gen == 6)
 			ring->flush = gen6_render_ring_flush;
-		ring->irq_get = gen6_ring_get_irq;
-		ring->irq_put = gen6_ring_put_irq;
+		if (INTEL_INFO(dev)->gen >= 8) {
+			ring->irq_get = gen8_ring_get_irq;
+			ring->irq_put = gen8_ring_put_irq;
+		} else {
+			ring->irq_get = gen6_ring_get_irq;
+			ring->irq_put = gen6_ring_put_irq;
+		}
 		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
 		ring->get_seqno = gen6_ring_get_seqno;
 		ring->set_seqno = ring_set_seqno;
@@ -1897,9 +1944,15 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
 		ring->add_request = gen6_add_request;
 		ring->get_seqno = gen6_ring_get_seqno;
 		ring->set_seqno = ring_set_seqno;
-		ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
-		ring->irq_get = gen6_ring_get_irq;
-		ring->irq_put = gen6_ring_put_irq;
+		if (INTEL_INFO(dev)->gen >= 8) {
+			ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT;
+			ring->irq_get = gen8_ring_get_irq;
+			ring->irq_put = gen8_ring_put_irq;
+		} else {
+			ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
+			ring->irq_get = gen6_ring_get_irq;
+			ring->irq_put = gen6_ring_put_irq;
+		}
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 		ring->sync_to = gen6_ring_sync;
 		ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VR;
@@ -1946,9 +1999,15 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
 	ring->add_request = gen6_add_request;
 	ring->get_seqno = gen6_ring_get_seqno;
 	ring->set_seqno = ring_set_seqno;
-	ring->irq_enable_mask = GT_BLT_USER_INTERRUPT;
-	ring->irq_get = gen6_ring_get_irq;
-	ring->irq_put = gen6_ring_put_irq;
+	if (INTEL_INFO(dev)->gen >= 8) {
+		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
+		ring->irq_get = gen8_ring_get_irq;
+		ring->irq_put = gen8_ring_put_irq;
+	} else {
+		ring->irq_enable_mask = GT_BLT_USER_INTERRUPT;
+		ring->irq_get = gen6_ring_get_irq;
+		ring->irq_put = gen6_ring_put_irq;
+	}
 	ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	ring->sync_to = gen6_ring_sync;
 	ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_BR;
@@ -1978,10 +2037,19 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
 	ring->add_request = gen6_add_request;
 	ring->get_seqno = gen6_ring_get_seqno;
 	ring->set_seqno = ring_set_seqno;
-	ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
-	ring->irq_get = hsw_vebox_get_irq;
-	ring->irq_put = hsw_vebox_put_irq;
 	ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+
+	if (INTEL_INFO(dev)->gen >= 8) {
+		ring->irq_enable_mask =
+			(GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT) |
+			GT_RENDER_CS_MASTER_ERROR_INTERRUPT;
+		ring->irq_get = gen8_ring_get_irq;
+		ring->irq_put = gen8_ring_put_irq;
+	} else {
+		ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
+		ring->irq_get = hsw_vebox_get_irq;
+		ring->irq_put = hsw_vebox_put_irq;
+	}
 	ring->sync_to = gen6_ring_sync;
 	ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VER;
 	ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_VEV;
-- 
1.8.4.2

  parent reply	other threads:[~2013-11-03  4:08 UTC|newest]

Thread overview: 145+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-03  4:06 [PATCH 00/62] Broadwell kernel driver support Ben Widawsky
2013-11-03  4:06 ` [PATCH 01/62] drm/i915/bdw: IS_GEN8 definition Ben Widawsky
2013-11-03  4:07 ` [PATCH 02/62] drm/i915/bdw: Handle forcewake for writes on gen8 Ben Widawsky
2013-11-04 14:19   ` Chris Wilson
2013-11-05  9:24   ` Mika Kuoppala
2013-11-03  4:07 ` [PATCH 03/62] drm/i915/bdw: Disable PPGTT for now Ben Widawsky
2013-11-04 14:44   ` Chris Wilson
2013-11-03  4:07 ` [PATCH 04/62] drm/i915/bdw: Add device IDs Ben Widawsky
2013-11-03 21:58   ` Chris Wilson
2013-11-04  0:36     ` [PATCH 04/62] [v6] " Ben Widawsky
2013-11-04 14:49       ` Chris Wilson
2013-11-04 15:49         ` Daniel Vetter
2013-11-04 16:04           ` Chris Wilson
2013-11-04 16:56         ` Ben Widawsky
2013-11-04  0:43     ` [PATCH 04/62] " Ben Widawsky
2013-11-04  0:47     ` [PATCH 04/62] [v7] " Ben Widawsky
2013-11-05 14:45       ` Mika Kuoppala
2013-11-03  4:07 ` [PATCH 05/62] drm/i915/bdw: Fences on gen8 look just like gen7 Ben Widawsky
2013-11-03  4:07 ` [PATCH 06/62] drm/i915/bdw: Swizzling support Ben Widawsky
2013-11-05  9:59   ` Mika Kuoppala
2013-11-03  4:07 ` [PATCH 07/62] drm/i915/bdw: HW context support Ben Widawsky
2013-11-03  4:07 ` [PATCH 08/62] drm/i915/bdw: Clock gating init Ben Widawsky
2013-11-03  4:07 ` [PATCH 09/62] drm/i915/bdw: display stuff Ben Widawsky
2013-11-06  8:13   ` Daniel Vetter
2013-11-03  4:07 ` [PATCH 10/62] drm/i915/bdw: support GMS and GGMS changes Ben Widawsky
2013-11-04  0:53   ` [PATCH 10/62] [v5] " Ben Widawsky
2013-11-03  4:07 ` Ben Widawsky [this message]
2013-11-06  8:39   ` [PATCH 11/62] drm/i915/bdw: Implement interrupt changes Daniel Vetter
2013-11-03  4:07 ` [PATCH 12/62] drm/i915/bdw: Add interrupt info to debugfs Ben Widawsky
2013-11-03  4:07 ` [PATCH 13/62] drm/i915/bdw: Support 64b relocations Ben Widawsky
2013-11-03  4:07 ` [PATCH 14/62] drm/i915/bdw: dispatch updates (64b related) Ben Widawsky
2013-11-05 15:50   ` Paulo Zanoni
2013-11-03  4:07 ` [PATCH 15/62] drm/i915/bdw: Update MI_FLUSH_DW Ben Widawsky
2013-11-03  4:07 ` [PATCH 16/62] drm/i915/bdw: debugfs updates Ben Widawsky
2013-11-04 14:28   ` Chris Wilson
2013-11-05  3:03     ` Ben Widawsky
2013-11-05 16:40   ` Paulo Zanoni
2013-11-03  4:07 ` [PATCH 17/62] drm/i915/bdw: Update relevant error state Ben Widawsky
2013-11-05 17:03   ` Paulo Zanoni
2013-11-03  4:07 ` [PATCH 18/62] drm/i915/bdw: Make gen8_gmch_probe Ben Widawsky
2013-11-04 22:01   ` Imre Deak
2013-11-05  3:32     ` [PATCH 18/62] [v6] " Ben Widawsky
2013-11-03  4:07 ` [PATCH 19/62] drm/i915/bdw: Create gen8_gtt_pte_t Ben Widawsky
2013-11-04 14:36   ` Chris Wilson
2013-11-04 22:03   ` Imre Deak
2013-11-03  4:07 ` [PATCH 20/62] drm/i915/bdw: Add GTT functions Ben Widawsky
2013-11-04 22:22   ` Imre Deak
2013-11-06  8:28   ` Bloomfield, Jon
2013-11-03  4:07 ` [PATCH 21/62] drm/i915/bdw: Support BDW caching Ben Widawsky
2013-11-04 14:39   ` Chris Wilson
2013-11-05  3:56     ` [PATCH 21/62] [v4] " Ben Widawsky
2013-11-05 15:19   ` [PATCH 21/62] " Imre Deak
2013-11-03  4:07 ` [PATCH 22/62] drm/i915/bdw: Implement Full Force Miss disables Ben Widawsky
2013-11-05 15:41   ` Imre Deak
2013-11-05 16:17     ` Daniel Vetter
2013-11-06  9:33       ` Daniel Vetter
2013-11-03  4:07 ` [PATCH 23/62] drm/i915/bdw: PPGTT init & cleanup Ben Widawsky
2013-11-04 14:58   ` Imre Deak
2013-11-05  4:47     ` [PATCH] " Ben Widawsky
2013-11-03  4:07 ` [PATCH 24/62] drm/i915/bdw: Initialize the PDEs Ben Widawsky
2013-11-04 14:10   ` Damien Lespiau
2013-11-05  5:20     ` [PATCH 24/62] [v3] " Ben Widawsky
2013-11-03  4:07 ` [PATCH 25/62] drm/i915/bdw: Implement PPGTT clear range Ben Widawsky
2013-11-03  4:07 ` [PATCH 26/62] drm/i915/bdw: Implement PPGTT insert Ben Widawsky
2013-11-03  4:07 ` [PATCH 27/62] drm/i915/bdw: Implement PPGTT enable Ben Widawsky
2013-11-04 14:47   ` Damien Lespiau
2013-11-05  6:29     ` [PATCH 27/62] [v7] " Ben Widawsky
2013-11-03  4:07 ` [PATCH 28/62] drm/i915/bdw: unleash PPGTT Ben Widawsky
2013-11-03  4:07 ` [PATCH 29/62] drm/i915/bdw: Render ring flushing Ben Widawsky
2013-11-03  4:07 ` [PATCH 30/62] drm/i915/bdw: BSD init for gen8 also Ben Widawsky
2013-11-03  4:07 ` [PATCH 31/62] drm/i915/bdw: Don't muck with gtt_size on Gen8 when PPGTT setup fails Ben Widawsky
2013-11-03  4:07 ` [PATCH 32/62] drm/i915/bdw: ppgtt info in debugfs Ben Widawsky
2013-11-03  4:07 ` [PATCH 33/62] drm/i915/bdw: add IS_BROADWELL macro Ben Widawsky
2013-11-03  4:07 ` [PATCH 34/62] drm/i915/bdw: Broadwell has 3 pipes Ben Widawsky
2013-11-03  4:07 ` [PATCH 35/62] drm/i915/bdw: add Broadwell sprite/plane/cursor checks Ben Widawsky
2013-11-03  4:07 ` [PATCH 36/62] drm/i915/bdw: Broadwell also has the "power down well" Ben Widawsky
2013-11-03 11:05   ` Ville Syrjälä
2013-11-03 11:24     ` Daniel Vetter
2013-11-03 11:25       ` Ville Syrjälä
2013-11-03  4:07 ` [PATCH 37/62] drm/i915/bdw: pretend we have LPT LP on Broadwell Ben Widawsky
2013-11-03 11:19   ` Ville Syrjälä
2013-11-03  4:07 ` [PATCH 38/62] drm/i915/bdw: get the correct LCPLL frequency " Ben Widawsky
2013-11-03 11:07   ` Ville Syrjälä
2013-11-03  4:07 ` [PATCH 39/62] drm/i915/bdw: on Broadwell, the panel fitter is on the pipe Ben Widawsky
2013-11-03 11:19   ` Ville Syrjälä
2013-11-03  4:07 ` [PATCH 40/62] drm/i915/bdw: Broadwell has PIPEMISC Ben Widawsky
2013-11-03 11:11   ` Ville Syrjälä
2013-11-03  4:07 ` [PATCH 41/62] drm/i915/bdw: Use pipe CSC on Broadwell Ben Widawsky
2013-11-03  4:07 ` [PATCH 42/62] drm/i915/bdw: Implement WaSwitchSolVfFArbitrationPriority Ben Widawsky
2013-11-03 11:07   ` Ville Syrjälä
2013-11-03 17:44     ` Ben Widawsky
2013-11-04 14:23       ` Ville Syrjälä
2013-11-03  4:07 ` [PATCH 43/62] drm/i915/bdw: Add BDW DDI buffer translation values Ben Widawsky
2013-11-04 23:59   ` Ben Widawsky
2013-11-03  4:07 ` [PATCH 44/62] drm/i915/bdw: add BDW DDI buf translations for eDP Ben Widawsky
2013-11-05  0:09   ` Ben Widawsky
2013-11-03  4:07 ` [PATCH 45/62] drm/i915/bdw: add support for BDW DP voltage swings and pre-emphasis Ben Widawsky
2013-11-05  0:45   ` Ben Widawsky
2013-11-05 13:01     ` Paulo Zanoni
2013-11-06  3:15       ` Todd Previte
2013-11-03  4:07 ` [PATCH 46/62] drm/i915/bdw: BDW also has only 2 FDI lanes Ben Widawsky
2013-11-03  4:07 ` [PATCH 47/62] drm/i915/bdw: check DPD on port D when setting the DDI buffers Ben Widawsky
2013-11-05  0:46   ` Ben Widawsky
2013-11-03  4:07 ` [PATCH 48/62] drm/i915/bdw: Add Broadwell display FIFO limits Ben Widawsky
2013-11-04  9:39   ` Jani Nikula
2013-11-04 13:59     ` Ville Syrjälä
2013-11-03  4:07 ` [PATCH 49/62] drm/i915/bdw: Use The GT mailbox for IPS enable/disable Ben Widawsky
2013-11-04 10:15   ` Jani Nikula
2013-11-03  4:07 ` [PATCH 50/62] drm/i915/bdw: Support eDP PSR Ben Widawsky
2013-11-04 10:34   ` Jani Nikula
2013-11-05  6:45     ` [PATCH 50/62] [v5] " Ben Widawsky
2014-03-04  9:31       ` Kumar, Kiran S
2014-03-05  6:31         ` Ben Widawsky
2013-11-03  4:07 ` [PATCH 51/62] drm/i915/bdw: Use HSW formula for ring freq scaling Ben Widawsky
2013-11-06 13:34   ` Daniel Vetter
2013-11-03  4:07 ` [PATCH 52/62] drm/i915/bdw: Don't wait for c0 threads on forcewake Ben Widawsky
2013-11-04 13:47   ` Jani Nikula
2013-11-03  4:07 ` [PATCH 53/62] drm/i915/bdw: Broadwell has a max port clock of 300Mhz on HDMI Ben Widawsky
2013-11-04 13:33   ` Jani Nikula
2013-11-03  4:07 ` [PATCH 54/62] drm/i915/bdw: Create a separate BDW rps enable Ben Widawsky
2013-11-04 21:04   ` Jesse Barnes
2013-11-03  4:07 ` [PATCH 55/62] drm/i915/bdw: Disable semaphores Ben Widawsky
2013-11-04 18:18   ` Jesse Barnes
2013-11-05  3:45     ` [PATCH 55/62] [v2] " Ben Widawsky
2013-11-03  4:07 ` [PATCH 56/62] drm/i915/bdw: Implement edp PSR workarounds Ben Widawsky
2013-11-05 17:19   ` Jesse Barnes
2013-11-06 15:44   ` Daniel Vetter
2013-11-03  4:07 ` [PATCH 57/62] drm/i915/bdw: BWGTLB clock gate disable Ben Widawsky
2013-11-05 17:22   ` Jesse Barnes
2013-11-03  4:07 ` [PATCH 58/62] drm/i915/bdw: Disable centroid pixel perf optimization Ben Widawsky
2013-11-04 13:20   ` Paulo Zanoni
2013-11-05  6:52     ` [PATCH] " Ben Widawsky
2013-11-05 17:24       ` Jesse Barnes
2013-11-03  4:07 ` [PATCH 59/62] drm/i915/bdw: Sampler power bypass disable Ben Widawsky
2013-11-03  4:07 ` [PATCH 60/62] drm/i915/bdw: Limit SDE poly depth FIFO to 2 Ben Widawsky
2013-11-03  4:07 ` [PATCH 61/62] drm/i915/bdw: conservative SBE VUE cache mode Ben Widawsky
2013-11-03  4:08 ` [PATCH 62/62] drm/i915/bdw: WaSingleSubspanDispatchOnAALinesAndPoints Ben Widawsky
2013-11-03  8:45 ` [PATCH 00/62] Broadwell kernel driver support Daniel Vetter
2013-11-04 14:15   ` Jani Nikula
2013-11-04 15:04   ` Damien Lespiau
2013-11-05 15:14   ` Daniel Vetter
2013-11-05 15:54   ` Imre Deak
2013-11-03 11:47 ` [PATCH 63/62] drm/i915/bdw: Enable trickle feed on Broadwell ville.syrjala
2013-11-04 15:05   ` Damien Lespiau
2013-11-05  7:11 ` [PATCH 64/62] drm/i915/bdw: Change dp aux timeout to 600us on DDIA Ben Widawsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1383451680-11173-12-git-send-email-benjamin.widawsky@intel.com \
    --to=benjamin.widawsky@intel.com \
    --cc=ben@bwidawsk.net \
    --cc=daniel.vetter@ffwll.ch \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox