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