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
