Since obj->frontbuffer is no longer protected by the struct_mutex, as we are processing the execbuf, it may be removed. 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@xxxxxxxxxxxxxxxxxx> Cc: Matthew Auld <matthew.auld@xxxxxxxxx> Cc: <stable@xxxxxxxxxxxxxxx> # v5.4+ --- drivers/gpu/drm/i915/display/intel_frontbuffer.c | 13 ++++++++++++- drivers/gpu/drm/i915/display/intel_frontbuffer.h | 14 +++++++++++++- drivers/gpu/drm/i915/i915_vma.c | 10 ++++++++-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 84b164f31895..6a8ef6a05133 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -237,7 +237,7 @@ static void frontbuffer_release(struct kref *ref) } struct intel_frontbuffer * -intel_frontbuffer_get(struct drm_i915_gem_object *obj) +____intel_frontbuffer_get(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = to_i915(obj->base.dev); struct intel_frontbuffer *front; @@ -247,6 +247,17 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj) if (front) kref_get(&front->ref); spin_unlock(&i915->fb_tracking.lock); + + return front; +} + +struct intel_frontbuffer * +intel_frontbuffer_get(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct intel_frontbuffer *front; + + front = __intel_frontbuffer_get(obj); if (front) return front; diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.h b/drivers/gpu/drm/i915/display/intel_frontbuffer.h index adc64d61a4a5..2b3068b61b80 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.h +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.h @@ -27,10 +27,10 @@ #include <linux/atomic.h> #include <linux/kref.h> +#include "gem/i915_gem_object_types.h" #include "i915_active.h" struct drm_i915_private; -struct drm_i915_gem_object; enum fb_op_origin { ORIGIN_GTT, @@ -54,6 +54,18 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *i915, void intel_frontbuffer_flip(struct drm_i915_private *i915, unsigned frontbuffer_bits); +struct intel_frontbuffer * +____intel_frontbuffer_get(struct drm_i915_gem_object *obj); + +static inline struct intel_frontbuffer * +__intel_frontbuffer_get(struct drm_i915_gem_object *obj) +{ + if (!READ_ONCE(obj->frontbuffer)) + return NULL; + + return ____intel_frontbuffer_get(obj); +} + struct intel_frontbuffer * intel_frontbuffer_get(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 6794c742fbbf..f8790d08f449 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1139,8 +1139,14 @@ int i915_vma_move_to_active(struct i915_vma *vma, return err; if (flags & EXEC_OBJECT_WRITE) { - if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS)) - i915_active_add_request(&obj->frontbuffer->write, rq); + struct intel_frontbuffer *front; + + front = __intel_frontbuffer_get(obj); + if (unlikely(front)) { + if (intel_frontbuffer_invalidate(front, ORIGIN_CS)) + i915_active_add_request(&front->write, rq); + intel_frontbuffer_put(front); + } dma_resv_add_excl_fence(vma->resv, &rq->fence); obj->write_domain = I915_GEM_DOMAIN_RENDER; -- 2.24.0