drm/i915/active: Fix misuse of non-idle barriers as fence trackers
authorjsg <jsg@openbsd.org>
Tue, 28 Mar 2023 04:13:21 +0000 (04:13 +0000)
committerjsg <jsg@openbsd.org>
Tue, 28 Mar 2023 04:13:21 +0000 (04:13 +0000)
From Janusz Krzysztofik
5c7591b8574c52c56b3994c2fbef1a3a311b5715 in linux-6.1.y/6.1.21
e0e6b416b25ee14716f3549e0cbec1011b193809 in mainline linux

sys/dev/pci/drm/i915/i915_active.c

index d69fa19..39c8e27 100644 (file)
@@ -434,12 +434,12 @@ replace_barrier(struct i915_active *ref, struct i915_active_fence *active)
         * we can use it to substitute for the pending idle-barrer
         * request that we want to emit on the kernel_context.
         */
-       __active_del_barrier(ref, node_from_active(active));
-       return true;
+       return __active_del_barrier(ref, node_from_active(active));
 }
 
 int i915_active_add_request(struct i915_active *ref, struct i915_request *rq)
 {
+       u64 idx = i915_request_timeline(rq)->fence_context;
        struct dma_fence *fence = &rq->fence;
        struct i915_active_fence *active;
        int err;
@@ -449,16 +449,19 @@ int i915_active_add_request(struct i915_active *ref, struct i915_request *rq)
        if (err)
                return err;
 
-       active = active_instance(ref, i915_request_timeline(rq)->fence_context);
-       if (!active) {
-               err = -ENOMEM;
-               goto out;
-       }
+       do {
+               active = active_instance(ref, idx);
+               if (!active) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+
+               if (replace_barrier(ref, active)) {
+                       RCU_INIT_POINTER(active->fence, NULL);
+                       atomic_dec(&ref->count);
+               }
+       } while (unlikely(is_barrier(active)));
 
-       if (replace_barrier(ref, active)) {
-               RCU_INIT_POINTER(active->fence, NULL);
-               atomic_dec(&ref->count);
-       }
        if (!__i915_active_fence_set(active, fence))
                __i915_active_acquire(ref);