[Intel-gfx] [PATCH 2/2] drm/i915: Flush request queue when waiting for ring space
Volkin, Bradley D
bradley.d.volkin at intel.com
Wed May 7 23:18:24 CEST 2014
On Mon, May 05, 2014 at 01:07:33AM -0700, Chris Wilson wrote:
> During the review of
>
> commit 1f70999f9052f5a1b0ce1a55aff3808f2ec9fe42
> Author: Chris Wilson <chris at chris-wilson.co.uk>
> Date: Mon Jan 27 22:43:07 2014 +0000
>
> drm/i915: Prevent recursion by retiring requests when the ring is full
>
> Ville raised the point that our interaction with request->tail was
> likely to foul up other uses elsewhere (such as hang check comparing
> ACTHD against requests).
>
> However, we also need to restore the implicit retire requests that certain
> test cases depend upon (e.g. igt/gem_exec_lut_handle), this raises the
> spectre that the ppgtt will randomly call i915_gpu_idle() and recurse
> back into intel_ring_begin().
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=78023
There's one minor cleanup suggested below.
Overall I think the code is better after the patch. I don't really like
reintroducing the potential recursion, but I suppose that's a separate
issue. With the cleanup...
Reviewed-by: Brad Volkin <bradley.d.volkin at intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 1 +
> drivers/gpu/drm/i915/i915_gem.c | 3 +--
> drivers/gpu/drm/i915/intel_ringbuffer.c | 36 ++++++++++++---------------------
> 3 files changed, 15 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 5f4f631aecef..69a4e161ff37 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2155,6 +2155,7 @@ struct drm_i915_gem_request *
> i915_gem_find_active_request(struct intel_ring_buffer *ring);
>
> bool i915_gem_retire_requests(struct drm_device *dev);
> +void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
> int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
> bool interruptible);
> static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index dae51c3701f3..2f2a668c01ac 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -64,7 +64,6 @@ static unsigned long i915_gem_inactive_scan(struct shrinker *shrinker,
> static unsigned long i915_gem_purge(struct drm_i915_private *dev_priv, long target);
> static unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
> static void i915_gem_object_truncate(struct drm_i915_gem_object *obj);
> -static void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
>
> static bool cpu_cache_is_coherent(struct drm_device *dev,
> enum i915_cache_level level)
> @@ -2448,7 +2447,7 @@ void i915_gem_reset(struct drm_device *dev)
> /**
> * This function clears the request list as sequence numbers are passed.
> */
> -static void
> +void
> i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
> {
> uint32_t seqno;
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
> index d6b7b884adf9..9dce15cbce73 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
> @@ -40,14 +40,19 @@
> */
> #define CACHELINE_BYTES 64
>
> -static inline int ring_space(struct intel_ring_buffer *ring)
> +static inline int __ring_space(int head, int tail, int size)
> {
> - int space = (ring->head & HEAD_ADDR) - (ring->tail + I915_RING_FREE_SPACE);
> + int space = head - (tail + I915_RING_FREE_SPACE);
> if (space < 0)
> - space += ring->size;
> + space += size;
> return space;
> }
>
> +static inline int ring_space(struct intel_ring_buffer *ring)
> +{
> + return __ring_space(ring->head & HEAD_ADDR, ring->tail, ring->size);
> +}
> +
> static bool intel_ring_stopped(struct intel_ring_buffer *ring)
> {
> struct drm_i915_private *dev_priv = ring->dev->dev_private;
> @@ -1495,26 +1500,11 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
> }
>
> list_for_each_entry(request, &ring->request_list, list) {
> - int space;
> -
> - if (request->tail == -1)
> - continue;
> -
> - space = request->tail - (ring->tail + I915_RING_FREE_SPACE);
> - if (space < 0)
> - space += ring->size;
> - if (space >= n) {
> + if (__ring_space(request->tail, ring->tail, ring->size) >= n) {
> seqno = request->seqno;
> tail = request->tail;
We don't actually use the local 'tail' anymore.
> break;
> }
> -
> - /* Consume this request in case we need more space than
> - * is available and so need to prevent a race between
> - * updating last_retired_head and direct reads of
> - * I915_RING_HEAD. It also provides a nice sanity check.
> - */
> - request->tail = -1;
> }
>
> if (seqno == 0)
> @@ -1524,11 +1514,11 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
> if (ret)
> return ret;
>
> - ring->head = tail;
> - ring->space = ring_space(ring);
> - if (WARN_ON(ring->space < n))
> - return -ENOSPC;
> + i915_gem_retire_requests_ring(ring);
> + ring->head = ring->last_retired_head;
> + ring->last_retired_head = -1;
>
> + ring->space = ring_space(ring);
> return 0;
> }
>
> --
> 2.0.0.rc0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list