[Intel-gfx] [PATCH 2/2] drm/i915: Hold reference to intel_frontbuffer as we track activity

Joonas Lahtinen joonas.lahtinen at linux.intel.com
Wed Dec 18 10:32:50 UTC 2019


Quoting Chris Wilson (2019-12-16 18:17:17)
> Since obj->frontbuffer is no longer protected by the struct_mutex, as we
> are processing the execbuf, it may be removed. Mark the
> intel_frontbuffer as rcu protected, and so acquire a reference to
> the struct as we track activity upon it.
> 
> Closes: https://gitlab.freedesktop.org/drm/intel/issues/827
> Fixes: 8e7cb1799b4f ("drm/i915: Extract intel_frontbuffer active tracking")
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Matthew Auld <matthew.auld at intel.com>
> Cc: <stable at vger.kernel.org> # v5.4+

<SNIP>

> @@ -54,6 +55,35 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
>  void intel_frontbuffer_flip(struct drm_i915_private *i915,
>                             unsigned frontbuffer_bits);
>  
> +void intel_frontbuffer_put(struct intel_frontbuffer *front);
> +
> +static inline struct intel_frontbuffer *
> +__intel_frontbuffer_get(const struct drm_i915_gem_object *obj)
> +{
> +       struct intel_frontbuffer *front;
> +
> +       if (likely(!rcu_access_pointer(obj->frontbuffer)))
> +               return NULL;
> +
> +       rcu_read_lock();
> +       do {
> +               front = rcu_dereference(obj->frontbuffer);
> +               if (!front)
> +                       break;
> +
> +               if (!kref_get_unless_zero(&front->ref))
> +                       continue;
> +
> +               if (front == rcu_access_pointer(obj->frontbuffer))
> +                       break;
> +
> +               intel_frontbuffer_put(front);
> +       } while (1);
> +       rcu_read_unlock();
> +
> +       return front;
> +}

Understood that there can only be so many writers, so it's not
technically blocking, but the constructs looks like it was designed to
spin.

It would look more appropriate without the loop:

if (unlikely(!kref_get_unless_zero(&front->ref)))
	goto retry;

<SNIP>

> +void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
> +                                        enum fb_op_origin origin)
> +{
> +       struct intel_frontbuffer *front;
> +
> +       front = __intel_frontbuffer_get(obj);
> +       if (front) {
> +               intel_frontbuffer_flush(front, origin);
> +               intel_frontbuffer_put(front);
> +       }
> +}
> +
> +void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
> +                                             enum fb_op_origin origin)
> +{
> +       struct intel_frontbuffer *front;
> +
> +       front = __intel_frontbuffer_get(obj);
> +       if (front) {
> +               intel_frontbuffer_invalidate(front, origin);
> +               intel_frontbuffer_put(front);
> +       }
> +}

Could be de-duped as by taking the vfunc as parameter, but that's
just by coincidence that parameters match.

The rest checks out, so with the loop removed:

Reviewed-by: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>

Regards, Joonas


More information about the Intel-gfx mailing list