[PATCH 2/3] drm/i915: Introduce intel_ring_begin_cacheline_safe()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>

Add a special variant of intel_ring_begin() which allows the caller to
specify that a certain subset of the emitted dwords must fall within
a single cacheline.

intel_ring_begin_cacheline_safe() will return the number of extra dwords
that need to be emitted by the caller to produce the desired result.

Cc: Bjoern C <lkml@xxxxxxxxxxxx>
Cc: Alexandru DAMIAN <alexandru.damian@xxxxxxxxx>
Cc: Enrico Tagliavini <enrico.tagliavini@xxxxxxxxx>
Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 67 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_ringbuffer.h |  5 +++
 2 files changed, 72 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index a2bd533..87f5cee 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1647,6 +1647,73 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
 				  ring->tail + bytes > ring->effective_size);
 }
 
+static bool range_within_cacheline(int offset, int start, int end)
+{
+	return ((offset + start) & ~63) == ((offset + end - 1) & ~63);
+}
+
+/**
+ * intel_ring_begin_cacheline_safe - Allocate ring space while
+ * making sure a specific range of dwords lands inside a single
+ * cacheline.
+ *
+ * @ring: the ring buffer
+ * @first_cl_dword: first special dword
+ * @num_cl_dwords: how many dwords after @first_cl_dword must
+ *                 be within the same cacheline.
+ * @num_dwords: total number of dwords
+ * @num_extra_dwords: return number of extra dwords
+ *
+ * Allocate ring space line intel_ring_begin but make sure
+ * @num_cl_dwords dwords starting at @first_cl_dword all
+ * end up within the same cacheline. @num_extra_dwords will
+ * indicate how many extra dwords have to emitted. The extra
+ * dwords must be emitted at or before the original
+ * @first_cl_dword position.
+ */
+int intel_ring_begin_cacheline_safe(struct intel_ring_buffer *ring,
+				    int first_cl_dword,
+				    int num_cl_dwords,
+				    int num_dwords,
+				    int *num_extra_dwords)
+{
+	int start = first_cl_dword * sizeof(uint32_t);
+	int end = start + num_cl_dwords * sizeof(uint32_t);
+	int bytes = num_dwords * sizeof(uint32_t);
+	int tail = ring->tail;
+	int extra = 0;
+
+	if (WARN_ON(end - start > 64))
+		return -EINVAL;
+
+	/* Need to wrap in any case? */
+	if (tail + bytes > ring->effective_size)
+		tail = 0;
+
+	if (!range_within_cacheline(tail, start, end)) {
+		extra = 64 - ((tail + start) & 63);
+
+		/* Need to wrap due to the extra dwords? */
+		if (tail + extra + bytes > ring->effective_size) {
+			tail = 0;
+
+			/* Recalculate extra after the wrap */
+			extra = 0;
+			if (!range_within_cacheline(tail, start, end))
+				extra = 64 - ((tail + start) & 63);
+		}
+	}
+
+	/* Sanity checks. These should never happen. */
+	if (WARN_ON(!range_within_cacheline(tail + extra, start, end) ||
+		    tail + extra + bytes > ring->effective_size))
+		return -EINVAL;
+
+	*num_extra_dwords = extra / sizeof(uint32_t);
+
+	return __intel_ring_begin(ring, extra + bytes, tail != ring->tail);
+}
+
 void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 38c757e..e48e81e 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -235,6 +235,11 @@ intel_write_status_page(struct intel_ring_buffer *ring,
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
 
 int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
+int __must_check intel_ring_begin_cacheline_safe(struct intel_ring_buffer *ring,
+						 int first_cl_dword,
+						 int num_cl_dwords,
+						 int num_dwords,
+						 int *num_extra_dwords);
 static inline void intel_ring_emit(struct intel_ring_buffer *ring,
 				   u32 data)
 {
-- 
1.8.3.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx





[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux