FAILED: patch "[PATCH] drm/i915: Hold reference to intel_frontbuffer as we track" failed to apply to 5.4-stable tree
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e85ade1f50aae464ce196672faa7a099fd1721ed Mon Sep 17 00:00:00 2001
From: Chris Wilson <[email protected]>
Date: Wed, 18 Dec 2019 10:40:43 +0000
Subject: [PATCH] drm/i915: Hold reference to intel_frontbuffer as we track
activity
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.
drivers/gpu/drm/i915/display/intel_display.c +1 -1
@@ -15112,7 +15112,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,return ret;fb_obj_bump_render_priority (obj); -intel_frontbuffer_flush (obj->frontbuffer,ORIGIN_DIRTYFB ); +i915_gem_object_flush_frontbuffer (obj,ORIGIN_DIRTYFB );if (!new_plane_state->base.fence) {/* implicit fencing */ struct dma_fence *fence;
drivers/gpu/drm/i915/display/intel_frontbuffer.c +6 -10
@@ -229,11 +229,11 @@ static void frontbuffer_release(struct kref *ref) vma->display_alignment =I915_GTT_MIN_ALIGNMENT ;spin_unlock (&obj->vma.lock); - obj->frontbuffer =NULL ; +RCU_INIT_POINTER (obj->frontbuffer,NULL );spin_unlock (&to_i915 (obj->base.dev)->fb_tracking.lock);i915_gem_object_put (obj); -kfree (front); +kfree_rcu (front, rcu); } struct intel_frontbuffer *
@@ -242,11 +242,7 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)struct drm_i915_private *i915 =to_i915 (obj->base.dev);struct intel_frontbuffer *front; -spin_lock (&i915->fb_tracking.lock); - front = obj->frontbuffer; -if (front) -kref_get (&front->ref); -spin_unlock (&i915->fb_tracking.lock); + front =__intel_frontbuffer_get (obj);if (front)return front;
@@ -262,13 +258,13 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj) i915_active_may_sleep(frontbuffer_retire));spin_lock (&i915->fb_tracking.lock); -if (obj->frontbuffer) { +if (rcu_access_pointer (obj->frontbuffer)) {kfree (front); - front = obj->frontbuffer; + front =rcu_dereference_protected (obj->frontbuffer, true);kref_get (&front->ref); }else {i915_gem_object_get (obj); - obj->frontbuffer = front; +rcu_assign_pointer (obj->frontbuffer, front); }spin_unlock (&i915->fb_tracking.lock);
drivers/gpu/drm/i915/display/intel_frontbuffer.h +31 -3
@@ -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 ,
@@ -45,6 +45,7 @@ struct intel_frontbuffer {atomic_t bits;struct i915_active write;struct drm_i915_gem_object *obj; +struct rcu_head rcu; }; void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
@@ -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 (unlikely (!kref_get_unless_zero (&front->ref))) +continue ; + +if (likely (front ==rcu_access_pointer (obj->frontbuffer))) +break ; + +intel_frontbuffer_put (front); + }while (1 ); +rcu_read_unlock (); + +return front; +} +struct intel_frontbuffer *intel_frontbuffer_get (struct drm_i915_gem_object *obj);
@@ -119,6 +149,4 @@ void intel_frontbuffer_track(struct intel_frontbuffer *old,struct intel_frontbuffer *new, unsigned int frontbuffer_bits); -void intel_frontbuffer_put (struct intel_frontbuffer *front); -#endif /* __INTEL_FRONTBUFFER_H__ */
drivers/gpu/drm/i915/display/intel_overlay.c +13 -4
@@ -279,12 +279,21 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay, struct i915_vma *vma) {enum pipe pipe = overlay->crtc->pipe; +struct intel_frontbuffer *from =NULL , *to =NULL ;WARN_ON (overlay->old_vma); -intel_frontbuffer_track (overlay->vma ? overlay->vma->obj->frontbuffer :NULL , - vma ? vma->obj->frontbuffer :NULL , -INTEL_FRONTBUFFER_OVERLAY (pipe)); +if (overlay->vma) + from =intel_frontbuffer_get (overlay->vma->obj); +if (vma) + to =intel_frontbuffer_get (vma->obj); + +intel_frontbuffer_track (from, to,INTEL_FRONTBUFFER_OVERLAY (pipe)); + +if (to) +intel_frontbuffer_put (to); +if (from) +intel_frontbuffer_put (from);intel_frontbuffer_flip_prepare (overlay->i915,INTEL_FRONTBUFFER_OVERLAY (pipe));
@@ -766,7 +775,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, ret =PTR_ERR (vma); goto out_pin_section; } -intel_frontbuffer_flush (new_bo->frontbuffer,ORIGIN_DIRTYFB ); +i915_gem_object_flush_frontbuffer (new_bo,ORIGIN_DIRTYFB );if (!overlay->active) {u32 oconfig;
drivers/gpu/drm/i915/gem/i915_gem_clflush.c +2 -1
@@ -20,7 +20,8 @@ static void __do_clflush(struct drm_i915_gem_object *obj) {GEM_BUG_ON (!i915_gem_object_has_pages (obj));drm_clflush_sg (obj->mm.pages); -intel_frontbuffer_flush (obj->frontbuffer,ORIGIN_CPU ); + +i915_gem_object_flush_frontbuffer (obj,ORIGIN_CPU ); }static int clflush_work (struct dma_fence_work *base)
drivers/gpu/drm/i915/gem/i915_gem_domain.c +2 -2
@@ -664,7 +664,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,i915_gem_object_unlock (obj);if (write_domain) -intel_frontbuffer_invalidate (obj->frontbuffer,ORIGIN_CPU ); +i915_gem_object_invalidate_frontbuffer (obj,ORIGIN_CPU ); out_unpin:i915_gem_object_unpin_pages (obj);
@@ -784,7 +784,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj, } out: -intel_frontbuffer_invalidate (obj->frontbuffer,ORIGIN_CPU ); +i915_gem_object_invalidate_frontbuffer (obj,ORIGIN_CPU ); obj->mm.dirty = true;/* return with the pages pinned */ return 0 ;
drivers/gpu/drm/i915/gem/i915_gem_object.c +25 -1
@@ -280,7 +280,7 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,for_each_ggtt_vma (vma, obj)intel_gt_flush_ggtt_writes (vma->vm->gt); -intel_frontbuffer_flush (obj->frontbuffer,ORIGIN_CPU ); +i915_gem_object_flush_frontbuffer (obj,ORIGIN_CPU );for_each_ggtt_vma (vma, obj) {if (vma->iomap)
@@ -308,6 +308,30 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj, obj->write_domain =0 ; } +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); + } +} +void i915_gem_init__objects (struct drm_i915_private *i915) {INIT_WORK (&i915->mm.free_work, __i915_gem_free_work);
drivers/gpu/drm/i915/gem/i915_gem_object.h +22 -1
@@ -13,8 +13,8 @@#include <drm/i915_drm.h> +#include "display/intel_frontbuffer.h" #include "i915_gem_object_types.h" -#include "i915_gem_gtt.h" void i915_gem_init__objects (struct drm_i915_private *i915);
@@ -463,4 +463,25 @@ int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,unsigned int flags, const struct i915_sched_attr *attr); +void __i915_gem_object_flush_frontbuffer (struct drm_i915_gem_object *obj, +enum fb_op_origin origin); +void __i915_gem_object_invalidate_frontbuffer (struct drm_i915_gem_object *obj, +enum fb_op_origin origin); + +static inline void +i915_gem_object_flush_frontbuffer (struct drm_i915_gem_object *obj, +enum fb_op_origin origin) +{ +if (unlikely (rcu_access_pointer (obj->frontbuffer))) +__i915_gem_object_flush_frontbuffer (obj, origin); +} + +static inline void +i915_gem_object_invalidate_frontbuffer (struct drm_i915_gem_object *obj, +enum fb_op_origin origin) +{ +if (unlikely (rcu_access_pointer (obj->frontbuffer))) +__i915_gem_object_invalidate_frontbuffer (obj, origin); +} +#endif
drivers/gpu/drm/i915/gem/i915_gem_object_types.h +1 -1
@@ -150,7 +150,7 @@ struct drm_i915_gem_object {*/ u16 write_domain; -struct intel_frontbuffer *frontbuffer; +struct intel_frontbuffer __rcu *frontbuffer;/** Current tiling stride for the object, if it's tiled. */ unsigned int tiling_and_stride;
drivers/gpu/drm/i915/i915_gem.c +5 -5
@@ -161,7 +161,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,* We manually control the domain here and pretend that it * remains coherent i.e. in the GTT domain, like shmem_pwrite. */ -intel_frontbuffer_invalidate (obj->frontbuffer,ORIGIN_CPU ); +i915_gem_object_invalidate_frontbuffer (obj,ORIGIN_CPU );if (copy_from_user (vaddr, user_data, args->size))return -EFAULT ;
@@ -169,7 +169,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,drm_clflush_virt_range (vaddr, args->size);intel_gt_chipset_flush (&to_i915 (obj->base.dev)->gt); -intel_frontbuffer_flush (obj->frontbuffer,ORIGIN_CPU ); +i915_gem_object_flush_frontbuffer (obj,ORIGIN_CPU );return 0 ; }
@@ -589,7 +589,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, goto out_unpin; } -intel_frontbuffer_invalidate (obj->frontbuffer,ORIGIN_CPU ); +i915_gem_object_invalidate_frontbuffer (obj,ORIGIN_CPU ); user_data =u64_to_user_ptr (args->data_ptr); offset = args->offset;
@@ -631,7 +631,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, user_data += page_length; offset += page_length; } -intel_frontbuffer_flush (obj->frontbuffer,ORIGIN_CPU ); +i915_gem_object_flush_frontbuffer (obj,ORIGIN_CPU );i915_gem_object_unlock_fence (obj, fence); out_unpin:
@@ -721,7 +721,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj, offset =0 ; } -intel_frontbuffer_flush (obj->frontbuffer,ORIGIN_CPU ); +i915_gem_object_flush_frontbuffer (obj,ORIGIN_CPU );i915_gem_object_unlock_fence (obj, fence);return ret;
drivers/gpu/drm/i915/i915_vma.c +8 -2
@@ -1104,8 +1104,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 ;