intel-gfx.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: Chris Wilson <chris@chris-wilson.co.uk>
To: intel-gfx@lists.freedesktop.org
Subject: [PATCH] drm/i915: Set DERRMR around batches required vblank events
Date: Thu, 26 Jul 2012 21:30:19 +0100	[thread overview]
Message-ID: <1343334619-28340-1-git-send-email-chris@chris-wilson.co.uk> (raw)

In order for the Display Engine to send messages to the Render Engine,
that event must be unmasked in the Display Engine Render Response Mask
Register (DERRMR). By default all events are masked to prevent unwanted
messages to conserve power, and it is strongly recommended that only
single events be unmasked at any time. So in order to pipeline the
register writes around individual batchbuffers, userspace must notify
the kernel when it requires a vblank event, this patch implements an
interface to do so with an single (pipe, event) request through the
execbuffer flags.

Note that another workaround is required for IVB, in that we must also
prevent RC6 sleeps whilst waiting upon an event. To do that we also
pipeline a forcewake into the second MT slot.

Open issues:

* How to handle failure to pipeline the register changes? Abort? Sync &
undo?

* Serialising DERRMR across rings.

* Enabling vblank interrupts?

References: https://bugs.freedesktop.org/show_bug.cgi?id=50244
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_dma.c            |    3 ++
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   65 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h            |    1 +
 include/drm/i915_drm.h                     |   17 ++++++++
 4 files changed, 86 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 8921c4f..5debf31 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1009,6 +1009,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_WAIT_TIMEOUT:
 		value = 1;
 		break;
+	case I915_PARAM_HAS_EXEC_VSYNC:
+		value = 1;
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 				 param->param);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index d84ca98..90d8847 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1050,6 +1050,48 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret)
 		goto err;
 
+	if (args->flags & I915_EXEC_VSYNC_ENABLE &&
+	    INTEL_INFO(dev)->gen >= 6) {
+		int pipe, event;
+
+		printk(KERN_ERR "enabling sync\n");
+
+		/* XXX Inter-ring serialisation? */
+
+		event = I915_EXEC_VSYNC_GET_EVENT(args->flags);
+		if (event > I915_EXEC_VSYNC_VBLANK) {
+			ret = -EINVAL;
+			goto err;
+		}
+		pipe = I915_EXEC_VSYNC_GET_PIPE(args->flags);
+		if (pipe >= dev_priv->num_pipe) {
+			ret = -EINVAL;
+			goto err;
+		}
+
+		printk(KERN_ERR "event=%x, pipe=%d\n", event, pipe);
+		event = 1 << (event + 8 * pipe);
+
+		ret = intel_ring_begin(ring, 4);
+		if (ret)
+			goto err;
+
+		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+		intel_ring_emit(ring, DERRMR);
+		intel_ring_emit(ring, ~event);
+		intel_ring_advance(ring);
+
+		if (INTEL_INFO(dev)->gen >= 7 &&
+		    intel_ring_begin(ring, 4) == 0) {
+			intel_ring_emit(ring, MI_NOOP);
+			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+			intel_ring_emit(ring, FORCEWAKE_MT);
+			intel_ring_emit(ring, _MASKED_BIT_ENABLE(2));
+			intel_ring_advance(ring);
+		}
+	}
+
 	trace_i915_gem_ring_dispatch(ring, seqno);
 
 	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
@@ -1072,6 +1114,29 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			goto err;
 	}
 
+	if (args->flags & I915_EXEC_VSYNC_ENABLE &&
+	    INTEL_INFO(dev)->gen >= 6) {
+		bool was_interruptible = dev_priv->mm.interruptible;
+
+		dev_priv->mm.interruptible = false;
+		if (INTEL_INFO(dev)->gen >= 7 &&
+		    intel_ring_begin(ring, 4) == 0) {
+			intel_ring_emit(ring, MI_NOOP);
+			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+			intel_ring_emit(ring, FORCEWAKE_MT);
+			intel_ring_emit(ring, _MASKED_BIT_DISABLE(2));
+			intel_ring_advance(ring);
+		}
+		if (intel_ring_begin(ring, 4) == 0) {
+			intel_ring_emit(ring, MI_NOOP);
+			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+			intel_ring_emit(ring, DERRMR);
+			intel_ring_emit(ring, 0xffffffff);
+			intel_ring_advance(ring);
+		}
+		dev_priv->mm.interruptible = was_interruptible;
+	}
+
 	i915_gem_execbuffer_move_to_active(&objects, ring, seqno);
 	i915_gem_execbuffer_retire_commands(dev, file, ring);
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 1a22278..2f3a8f9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3369,6 +3369,7 @@
 #define DEIMR   0x44004
 #define DEIIR   0x44008
 #define DEIER   0x4400c
+#define DERRMR  0x44050
 
 /* GT interrupt.
  * Note that for gen6+ the ring-specific interrupt bits do alias with the
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 8cafced4..24f5895 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -313,6 +313,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_LLC		 17
 #define I915_PARAM_HAS_ALIASING_PPGTT	 18
 #define I915_PARAM_HAS_WAIT_TIMEOUT	 19
+#define I915_PARAM_HAS_EXEC_VSYNC	 20
 
 typedef struct drm_i915_getparam {
 	int param;
@@ -691,6 +692,22 @@ struct drm_i915_gem_execbuffer2 {
 /** Resets the SO write offset registers for transform feedback on gen7. */
 #define I915_EXEC_GEN7_SOL_RESET	(1<<8)
 
+#define I915_EXEC_VSYNC_ENABLE		(1<<9)
+#define I915_EXEC_VSYNC_EVENT_SHIFT	(10)
+#define I915_EXEC_VSYNC_EVENT_MASK	(7)
+#define I915_EXEC_VSYNC_SCANLINE	(0)
+#define I915_EXEC_VSYNC_PRIMARY_FLIP	(1)
+#define I915_EXEC_VSYNC_SPRITE_FLIP	(2)
+#define I915_EXEC_VSYNC_VBLANK		(3)
+#define I915_EXEC_VSYNC_PIPE_SHIFT	(13)
+#define I915_EXEC_VSYNC_PIPE_MASK	(7)
+
+#define I915_EXEC_VSYNC(pipe, event) \
+	(I915_EXEC_VSYNC_ENABLE | (pipe) << I915_EXEC_VSYNC_PIPE_SHIFT | (event) << I915_EXEC_VSYNC_EVENT_SHIFT)
+
+#define I915_EXEC_VSYNC_GET_PIPE(F) (((F) >> I915_EXEC_VSYNC_PIPE_SHIFT) & I915_EXEC_VSYNC_PIPE_MASK)
+#define I915_EXEC_VSYNC_GET_EVENT(F) (((F) >> I915_EXEC_VSYNC_EVENT_SHIFT) & I915_EXEC_VSYNC_EVENT_MASK)
+
 #define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
 	(eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
-- 
1.7.10.4

             reply	other threads:[~2012-07-26 20:30 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-26 20:30 Chris Wilson [this message]
2012-08-29 15:33 ` [PATCH] drm/i915: Set DERRMR around batches required vblank events Chris Wilson
2012-10-16  9:47 Chris Wilson
2012-10-16 14:15 ` Daniel Vetter
2012-10-17 13:58   ` Chris Wilson

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=1343334619-28340-1-git-send-email-chris@chris-wilson.co.uk \
    --to=chris@chris-wilson.co.uk \
    --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;
as well as URLs for NNTP newsgroup(s).