drm/i915: Propagate error from failing to queue a request

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 2af8e16..f168e82 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1041,10 +1041,10 @@
 		     unsigned long end);
 int i915_gpu_idle(struct drm_device *dev);
 int i915_gem_idle(struct drm_device *dev);
-uint32_t i915_add_request(struct drm_device *dev,
-			  struct drm_file *file_priv,
-			  struct drm_i915_gem_request *request,
-			  struct intel_ring_buffer *ring);
+int i915_add_request(struct drm_device *dev,
+		     struct drm_file *file_priv,
+		     struct drm_i915_gem_request *request,
+		     struct intel_ring_buffer *ring);
 int i915_do_wait_request(struct drm_device *dev,
 			 uint32_t seqno,
 			 bool interruptible,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 74f5525..d0aaf97 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1683,7 +1683,7 @@
 	}
 }
 
-uint32_t
+int
 i915_add_request(struct drm_device *dev,
 		 struct drm_file *file,
 		 struct drm_i915_gem_request *request,
@@ -1693,17 +1693,17 @@
 	struct drm_i915_file_private *file_priv = NULL;
 	uint32_t seqno;
 	int was_empty;
+	int ret;
+
+	BUG_ON(request == NULL);
 
 	if (file != NULL)
 		file_priv = file->driver_priv;
 
-	if (request == NULL) {
-		request = kzalloc(sizeof(*request), GFP_KERNEL);
-		if (request == NULL)
-			return 0;
-	}
+	ret = ring->add_request(ring, &seqno);
+	if (ret)
+	    return ret;
 
-	seqno = ring->add_request(ring, 0);
 	ring->outstanding_lazy_request = false;
 
 	request->seqno = seqno;
@@ -1727,7 +1727,7 @@
 			queue_delayed_work(dev_priv->wq,
 					   &dev_priv->mm.retire_work, HZ);
 	}
-	return seqno;
+	return 0;
 }
 
 /**
@@ -1964,9 +1964,19 @@
 		return -EAGAIN;
 
 	if (ring->outstanding_lazy_request) {
-		seqno = i915_add_request(dev, NULL, NULL, ring);
-		if (seqno == 0)
+		struct drm_i915_gem_request *request;
+
+		request = kzalloc(sizeof(*request), GFP_KERNEL);
+		if (request == NULL)
 			return -ENOMEM;
+
+		ret = i915_add_request(dev, NULL, request, ring);
+		if (ret) {
+			kfree(request);
+			return ret;
+		}
+
+		seqno = request->seqno;
 	}
 	BUG_ON(seqno == dev_priv->next_seqno);
 
@@ -3844,8 +3854,10 @@
 	 */
 	i915_retire_commands(dev, ring);
 
-	i915_add_request(dev, file, request, ring);
-	request = NULL;
+	if (i915_add_request(dev, file, request, ring))
+		ring->outstanding_lazy_request = true;
+	else
+		request = NULL;
 
 err:
 	for (i = 0; i < args->buffer_count; i++) {
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 78fa6a24..2d4a696 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -221,11 +221,12 @@
 	int ret;
 
 	BUG_ON(overlay->last_flip_req);
-	overlay->last_flip_req =
-		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
-	if (overlay->last_flip_req == 0)
-		return -ENOMEM;
-
+	ret = i915_add_request(dev, NULL, request, &dev_priv->render_ring);
+	if (ret) {
+	    kfree(request);
+	    return ret;
+	}
+	overlay->last_flip_req = request->seqno;
 	overlay->flip_tail = tail;
 	ret = i915_do_wait_request(dev,
 				   overlay->last_flip_req, true,
@@ -363,8 +364,13 @@
 	OUT_RING(flip_addr);
         ADVANCE_LP_RING();
 
-	overlay->last_flip_req =
-		i915_add_request(dev, NULL, request, &dev_priv->render_ring);
+	ret = i915_add_request(dev, NULL, request, &dev_priv->render_ring);
+	if (ret) {
+		kfree(request);
+		return ret;
+	}
+
+	overlay->last_flip_req = request->seqno;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6fe42c1..4803b32 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -234,28 +234,28 @@
  *
  * Returned sequence numbers are nonzero on success.
  */
-static u32
+static int
 render_ring_add_request(struct intel_ring_buffer *ring,
-			u32 flush_domains)
+			u32 *result)
 {
 	struct drm_device *dev = ring->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	u32 seqno;
-
-	seqno = i915_gem_get_seqno(dev);
+	u32 seqno = i915_gem_get_seqno(dev);
+	int ret;
 
 	if (IS_GEN6(dev)) {
-		if (intel_ring_begin(ring, 6) == 0) {
-			intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | 3);
-			intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE |
-					PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
-					PIPE_CONTROL_NOTIFY);
-			intel_ring_emit(ring, dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-			intel_ring_emit(ring, seqno);
-			intel_ring_emit(ring, 0);
-			intel_ring_emit(ring, 0);
-			intel_ring_advance(ring);
-		}
+		ret = intel_ring_begin(ring, 6);
+		if (ret)
+		    return ret;
+
+		intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | 3);
+		intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE |
+				PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
+				PIPE_CONTROL_NOTIFY);
+		intel_ring_emit(ring, dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+		intel_ring_emit(ring, seqno);
+		intel_ring_emit(ring, 0);
+		intel_ring_emit(ring, 0);
 	} else if (HAS_PIPE_CONTROL(dev)) {
 		u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
 
@@ -264,42 +264,47 @@
 		 * PIPE_NOTIFY buffers out to memory before requesting
 		 * an interrupt.
 		 */
-		if (intel_ring_begin(ring, 32) == 0) {
-			intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-					PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
-			intel_ring_emit(ring, dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-			intel_ring_emit(ring, seqno);
-			intel_ring_emit(ring, 0);
-			PIPE_CONTROL_FLUSH(ring, scratch_addr);
-			scratch_addr += 128; /* write to separate cachelines */
-			PIPE_CONTROL_FLUSH(ring, scratch_addr);
-			scratch_addr += 128;
-			PIPE_CONTROL_FLUSH(ring, scratch_addr);
-			scratch_addr += 128;
-			PIPE_CONTROL_FLUSH(ring, scratch_addr);
-			scratch_addr += 128;
-			PIPE_CONTROL_FLUSH(ring, scratch_addr);
-			scratch_addr += 128;
-			PIPE_CONTROL_FLUSH(ring, scratch_addr);
-			intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-					PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
-					PIPE_CONTROL_NOTIFY);
-			intel_ring_emit(ring, dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-			intel_ring_emit(ring, seqno);
-			intel_ring_emit(ring, 0);
-			intel_ring_advance(ring);
-		}
-	} else {
-		if (intel_ring_begin(ring, 4) == 0) {
-			intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
-			intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-			intel_ring_emit(ring, seqno);
+		ret = intel_ring_begin(ring, 32);
+		if (ret)
+			return ret;
 
-			intel_ring_emit(ring, MI_USER_INTERRUPT);
-			intel_ring_advance(ring);
-		}
+		intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+				PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
+		intel_ring_emit(ring, dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+		intel_ring_emit(ring, seqno);
+		intel_ring_emit(ring, 0);
+		PIPE_CONTROL_FLUSH(ring, scratch_addr);
+		scratch_addr += 128; /* write to separate cachelines */
+		PIPE_CONTROL_FLUSH(ring, scratch_addr);
+		scratch_addr += 128;
+		PIPE_CONTROL_FLUSH(ring, scratch_addr);
+		scratch_addr += 128;
+		PIPE_CONTROL_FLUSH(ring, scratch_addr);
+		scratch_addr += 128;
+		PIPE_CONTROL_FLUSH(ring, scratch_addr);
+		scratch_addr += 128;
+		PIPE_CONTROL_FLUSH(ring, scratch_addr);
+		intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+				PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
+				PIPE_CONTROL_NOTIFY);
+		intel_ring_emit(ring, dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+		intel_ring_emit(ring, seqno);
+		intel_ring_emit(ring, 0);
+	} else {
+		ret = intel_ring_begin(ring, 4);
+		if (ret)
+		    return ret;
+
+		intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
+		intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+		intel_ring_emit(ring, seqno);
+
+		intel_ring_emit(ring, MI_USER_INTERRUPT);
 	}
-	return seqno;
+
+	intel_ring_advance(ring);
+	*result = seqno;
+	return 0;
 }
 
 static u32
@@ -370,25 +375,28 @@
 	}
 }
 
-static u32
+static int
 ring_add_request(struct intel_ring_buffer *ring,
-		 u32 flush_domains)
+		 u32 *result)
 {
 	u32 seqno;
+	int ret;
+
+	ret = intel_ring_begin(ring, 4);
+	if (ret)
+		return ret;
 
 	seqno = i915_gem_get_seqno(ring->dev);
 
-	if (intel_ring_begin(ring, 4) == 0) {
-		intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
-		intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-		intel_ring_emit(ring, seqno);
-		intel_ring_emit(ring, MI_USER_INTERRUPT);
-		intel_ring_advance(ring);
-	}
+	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
+	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+	intel_ring_emit(ring, seqno);
+	intel_ring_emit(ring, MI_USER_INTERRUPT);
+	intel_ring_advance(ring);
 
 	DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
-
-	return seqno;
+	*result = seqno;
+	return 0;
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 7ad9e94..acd2337 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -48,8 +48,8 @@
 	void		(*flush)(struct intel_ring_buffer *ring,
 				 u32	invalidate_domains,
 				 u32	flush_domains);
-	u32		(*add_request)(struct intel_ring_buffer *ring,
-				       u32 flush_domains);
+	int		(*add_request)(struct intel_ring_buffer *ring,
+				       u32 *seqno);
 	u32		(*get_seqno)(struct intel_ring_buffer *ring);
 	int		(*dispatch_execbuffer)(struct intel_ring_buffer *ring,
 					       struct drm_i915_gem_execbuffer2 *exec,