[Intel-gfx] [PATCH 04/22] drm/i915: Hold a ref to the ring while retiring

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Mon Mar 18 10:31:57 UTC 2019


On 18/03/2019 09:51, Chris Wilson wrote:
> As the final request on a ring may hold the reference to this ring (via
> retiring the last pinned context), we may find ourselves chasing a
> dangling pointer on completion of the list.
> 
> A quick solution is to hold a reference to the ring itself as we retire
> along it so that we only free it after we stop dereferencing it.

Is there a guilty commit to reference as Fixes: ?


> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
>   drivers/gpu/drm/i915/i915_request.c          |  6 +++++-
>   drivers/gpu/drm/i915/intel_engine_types.h    |  2 ++
>   drivers/gpu/drm/i915/intel_lrc.c             |  4 ++--
>   drivers/gpu/drm/i915/intel_ringbuffer.c      |  9 +++++----
>   drivers/gpu/drm/i915/intel_ringbuffer.h      | 13 ++++++++++++-
>   drivers/gpu/drm/i915/selftests/mock_engine.c |  1 +
>   6 files changed, 27 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
> index 9533a85cb0b3..0a3d94517d0a 100644
> --- a/drivers/gpu/drm/i915/i915_request.c
> +++ b/drivers/gpu/drm/i915/i915_request.c
> @@ -1332,8 +1332,12 @@ void i915_retire_requests(struct drm_i915_private *i915)
>   	if (!i915->gt.active_requests)
>   		return;
>   
> -	list_for_each_entry_safe(ring, tmp, &i915->gt.active_rings, active_link)
> +	list_for_each_entry_safe(ring, tmp,
> +				 &i915->gt.active_rings, active_link) {
> +		intel_ring_get(ring); /* last rq holds reference! */
>   		ring_retire_requests(ring);
> +		intel_ring_put(ring);
> +	}

Where does it chase a dangling pointer? It used the safe iterator already.

>   }
>   
>   #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> diff --git a/drivers/gpu/drm/i915/intel_engine_types.h b/drivers/gpu/drm/i915/intel_engine_types.h
> index 79a166b9a81b..549fdfca17aa 100644
> --- a/drivers/gpu/drm/i915/intel_engine_types.h
> +++ b/drivers/gpu/drm/i915/intel_engine_types.h
> @@ -9,6 +9,7 @@
>   
>   #include <linux/hashtable.h>
>   #include <linux/irq_work.h>
> +#include <linux/kref.h>
>   #include <linux/list.h>
>   #include <linux/types.h>
>   
> @@ -58,6 +59,7 @@ struct intel_engine_hangcheck {
>   };
>   
>   struct intel_ring {
> +	struct kref ref;
>   	struct i915_vma *vma;
>   	void *vaddr;
>   
> diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> index aa50f03ba812..d3f1fe06d013 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/intel_lrc.c
> @@ -1236,7 +1236,7 @@ static void execlists_submit_request(struct i915_request *request)
>   
>   static void __execlists_context_fini(struct intel_context *ce)
>   {
> -	intel_ring_free(ce->ring);
> +	intel_ring_put(ce->ring);
>   
>   	GEM_BUG_ON(i915_gem_object_is_active(ce->state->obj));
>   	i915_gem_object_put(ce->state->obj);
> @@ -2867,7 +2867,7 @@ static int execlists_context_deferred_alloc(struct intel_context *ce,
>   	return 0;
>   
>   error_ring_free:
> -	intel_ring_free(ring);
> +	intel_ring_put(ring);
>   error_deref_obj:
>   	i915_gem_object_put(ctx_obj);
>   	return ret;
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
> index 746fe570466c..45a54fadc482 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
> @@ -1302,6 +1302,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine,
>   	if (!ring)
>   		return ERR_PTR(-ENOMEM);
>   
> +	kref_init(&ring->ref);
>   	INIT_LIST_HEAD(&ring->request_list);
>   	ring->timeline = i915_timeline_get(timeline);
>   
> @@ -1326,9 +1327,9 @@ intel_engine_create_ring(struct intel_engine_cs *engine,
>   	return ring;
>   }
>   
> -void
> -intel_ring_free(struct intel_ring *ring)
> +void intel_ring_free(struct kref *ref)
>   {
> +	struct intel_ring *ring = container_of(ref, typeof(*ring), ref);
>   	struct drm_i915_gem_object *obj = ring->vma->obj;
>   
>   	i915_vma_close(ring->vma);
> @@ -1571,7 +1572,7 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
>   err_unpin:
>   	intel_ring_unpin(ring);
>   err_ring:
> -	intel_ring_free(ring);
> +	intel_ring_put(ring);
>   err:
>   	intel_engine_cleanup_common(engine);
>   	return err;
> @@ -1585,7 +1586,7 @@ void intel_engine_cleanup(struct intel_engine_cs *engine)
>   		(I915_READ_MODE(engine) & MODE_IDLE) == 0);
>   
>   	intel_ring_unpin(engine->buffer);
> -	intel_ring_free(engine->buffer);
> +	intel_ring_put(engine->buffer);
>   
>   	if (engine->cleanup)
>   		engine->cleanup(engine);
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index e612bdca9fd9..a57489fcb302 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -231,7 +231,18 @@ int intel_ring_pin(struct intel_ring *ring);
>   void intel_ring_reset(struct intel_ring *ring, u32 tail);
>   unsigned int intel_ring_update_space(struct intel_ring *ring);
>   void intel_ring_unpin(struct intel_ring *ring);
> -void intel_ring_free(struct intel_ring *ring);
> +void intel_ring_free(struct kref *ref);
> +
> +static inline struct intel_ring *intel_ring_get(struct intel_ring *ring)
> +{
> +	kref_get(&ring->ref);
> +	return ring;
> +}
> +
> +static inline void intel_ring_put(struct intel_ring *ring)
> +{
> +	kref_put(&ring->ref, intel_ring_free);
> +}
>   
>   void intel_engine_stop(struct intel_engine_cs *engine);
>   void intel_engine_cleanup(struct intel_engine_cs *engine);
> diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c b/drivers/gpu/drm/i915/selftests/mock_engine.c
> index f6d120e05ee4..881450c694e9 100644
> --- a/drivers/gpu/drm/i915/selftests/mock_engine.c
> +++ b/drivers/gpu/drm/i915/selftests/mock_engine.c
> @@ -57,6 +57,7 @@ static struct intel_ring *mock_ring(struct intel_engine_cs *engine)
>   		return NULL;
>   	}
>   
> +	kref_init(&ring->base.ref);
>   	ring->base.size = sz;
>   	ring->base.effective_size = sz;
>   	ring->base.vaddr = (void *)(ring + 1);
> 

Regards,

Tvrtko


More information about the Intel-gfx mailing list