diff mbox

[3/5] drm/i915: Add i915_gem_alloc_seqno

Message ID 1353581490-5822-4-git-send-email-mika.kuoppala@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Mika Kuoppala Nov. 22, 2012, 10:51 a.m. UTC
Hardware can't handle seqno wrapping so all previous requests need to
be retired before seqno can wrap. As this can fail, make seqno
allocation explicit by introducing i915_gem_alloc_seqno()

Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |    1 +
 drivers/gpu/drm/i915/i915_gem.c |   51 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f511fa2..598f3b8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1387,6 +1387,7 @@  i915_seqno_passed(uint32_t seq1, uint32_t seq2)
 	return (int32_t)(seq1 - seq2) >= 0;
 }
 
+int i915_gem_alloc_seqno(struct intel_ring_buffer *ring, u32 *seqno);
 u32 i915_gem_next_request_seqno(struct intel_ring_buffer *ring);
 
 int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 7e17382..a637d5d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1933,6 +1933,34 @@  i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
 	WARN_ON(i915_verify_lists(dev));
 }
 
+static int
+i915_gem_handle_seqno_wrap(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	int ret;
+	int i;
+
+	/* The GPU can not handle its semaphore value wrapping,
+	   +	 * so every billion or so execbuffers, we need to stall
+	   * the GPU in order to reset the counters.
+	   */
+
+	ret = i915_gpu_idle(dev);
+	if (ret)
+		return ret;
+
+	i915_gem_retire_requests(dev);
+
+	for_each_ring(ring, dev_priv, i) {
+		int j;
+		for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++)
+			BUG_ON(ring->sync_seqno[j]);
+	}
+
+	return 0;
+}
+
 static u32
 i915_gem_get_seqno(struct drm_device *dev)
 {
@@ -1956,6 +1984,29 @@  i915_gem_next_request_seqno(struct intel_ring_buffer *ring)
 }
 
 int
+i915_gem_alloc_seqno(struct intel_ring_buffer *ring, u32 *seqno)
+{
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	int ret;
+
+	/* reserve 0 for non-seqno */
+	if (unlikely(dev_priv->next_seqno == ~0)) {
+		ret = i915_gem_handle_seqno_wrap(ring->dev);
+		if (ret)
+			return ret;
+
+		dev_priv->next_seqno = 1;
+	}
+
+	dev_priv->next_seqno++;
+
+	if (seqno)
+		*seqno = i915_gem_next_request_seqno(ring);
+
+	return 0;
+}
+
+int
 i915_add_request(struct intel_ring_buffer *ring,
 		 struct drm_file *file,
 		 u32 *out_seqno)