#define ptr_set_bit(ptr, bit) ((typeof(ptr))((unsigned long)(ptr) | BIT(bit)))
 #define ptr_test_bit(ptr, bit) ((unsigned long)(ptr) & BIT(bit))
 
+#define CACHELINE_BITS 6
+#define CACHELINE_FREE CACHELINE_BITS
+
 struct intel_timeline_hwsp {
        struct intel_gt *gt;
        struct intel_gt_timelines *gt_timelines;
        u64 free_bitmap;
 };
 
-struct intel_timeline_cacheline {
-       struct i915_active active;
-       struct intel_timeline_hwsp *hwsp;
-       void *vaddr;
-#define CACHELINE_BITS 6
-#define CACHELINE_FREE CACHELINE_BITS
-};
-
 static struct i915_vma *__hwsp_alloc(struct intel_gt *gt)
 {
        struct drm_i915_private *i915 = gt->i915;
        __idle_hwsp_free(cl->hwsp, ptr_unmask_bits(cl->vaddr, CACHELINE_BITS));
 
        i915_active_fini(&cl->active);
-       kfree(cl);
+       kfree_rcu(cl, rcu);
 }
 
 __i915_active_call
                             struct i915_request *to,
                             u32 *hwsp)
 {
-       struct intel_timeline *tl;
+       struct intel_timeline_cacheline *cl;
        int err;
 
+       GEM_BUG_ON(!rcu_access_pointer(from->hwsp_cacheline));
+
        rcu_read_lock();
-       tl = rcu_dereference(from->timeline);
-       if (i915_request_completed(from) || !kref_get_unless_zero(&tl->kref))
-               tl = NULL;
+       cl = rcu_dereference(from->hwsp_cacheline);
+       if (unlikely(!i915_active_acquire_if_busy(&cl->active)))
+               goto unlock; /* seqno wrapped and completed! */
+       if (unlikely(i915_request_completed(from)))
+               goto release;
        rcu_read_unlock();
-       if (!tl) /* already completed */
-               return 1;
 
-       GEM_BUG_ON(rcu_access_pointer(to->timeline) == tl);
-
-       err = -EAGAIN;
-       if (mutex_trylock(&tl->mutex)) {
-               struct intel_timeline_cacheline *cl = from->hwsp_cacheline;
-
-               if (i915_request_completed(from)) {
-                       err = 1;
-                       goto unlock;
-               }
+       err = cacheline_ref(cl, to);
+       if (err)
+               goto out;
 
-               err = cacheline_ref(cl, to);
-               if (err)
-                       goto unlock;
+       *hwsp = i915_ggtt_offset(cl->hwsp->vma) +
+               ptr_unmask_bits(cl->vaddr, CACHELINE_BITS) * CACHELINE_BYTES;
 
-               if (likely(cl == tl->hwsp_cacheline)) {
-                       *hwsp = tl->hwsp_offset;
-               } else { /* across a seqno wrap, recover the original offset */
-                       *hwsp = i915_ggtt_offset(cl->hwsp->vma) +
-                               ptr_unmask_bits(cl->vaddr, CACHELINE_BITS) *
-                               CACHELINE_BYTES;
-               }
+out:
+       i915_active_release(&cl->active);
+       return err;
 
+release:
+       i915_active_release(&cl->active);
 unlock:
-               mutex_unlock(&tl->mutex);
-       }
-       intel_timeline_put(tl);
-
-       return err;
+       rcu_read_unlock();
+       return 1;
 }
 
 void intel_timeline_unpin(struct intel_timeline *tl)
 
 
 #include "gt/intel_context_types.h"
 #include "gt/intel_engine_types.h"
+#include "gt/intel_timeline_types.h"
 
 #include "i915_gem.h"
 #include "i915_scheduler.h"
 struct drm_file;
 struct drm_i915_gem_object;
 struct i915_request;
-struct intel_timeline;
-struct intel_timeline_cacheline;
 
 struct i915_capture_list {
        struct i915_capture_list *next;
         * inside the timeline's HWSP vma, but it is only valid while this
         * request has not completed and guarded by the timeline mutex.
         */
-       struct intel_timeline_cacheline *hwsp_cacheline;
+       struct intel_timeline_cacheline __rcu *hwsp_cacheline;
 
        /** Position in the ring of the start of the request */
        u32 head;