mask non-chain fence sequence numbers to 32-bit for comparisons
authorjsg <jsg@openbsd.org>
Fri, 16 Sep 2022 01:48:07 +0000 (01:48 +0000)
committerjsg <jsg@openbsd.org>
Fri, 16 Sep 2022 01:48:07 +0000 (01:48 +0000)
Most of drm uses 32-bit sequence numbers in fences.
dma-fence-chain opts into 64-bit comparisons.

Wrapping is handled like i915_seqno_passed() except that if the sequence
numbers are the same one is not considered later than the other.

sys/dev/pci/drm/drm_linux.c
sys/dev/pci/drm/include/linux/dma-fence.h

index 16ff64f..2b975cd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: drm_linux.c,v 1.93 2022/06/20 01:39:44 visa Exp $     */
+/*     $OpenBSD: drm_linux.c,v 1.94 2022/09/16 01:48:07 jsg Exp $      */
 /*
  * Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org>
  * Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org>
@@ -2084,7 +2084,7 @@ dma_fence_chain_init(struct dma_fence_chain *chain, struct dma_fence *prev,
 
        /* if prev is a chain */
        if (to_dma_fence_chain(prev) != NULL) {
-               if (seqno > prev->seqno) {
+               if (__dma_fence_is_later(seqno, prev->seqno, prev->ops)) {
                        chain->prev_seqno = prev->seqno;
                        context = prev->context;
                } else {
@@ -2240,6 +2240,7 @@ const struct dma_fence_ops dma_fence_chain_ops = {
        .enable_signaling = dma_fence_chain_enable_signaling,
        .signaled = dma_fence_chain_signaled,
        .release = dma_fence_chain_release,
+       .use_64bit_seqno = true,
 };
 
 int
index 39220dc..06d2cb6 100644 (file)
@@ -41,6 +41,7 @@ struct dma_fence_ops {
        bool (*signaled)(struct dma_fence *);
        long (*wait)(struct dma_fence *, bool, long);
        void (*release)(struct dma_fence *);
+       bool use_64bit_seqno;
 };
 
 struct dma_fence_cb;
@@ -84,10 +85,30 @@ dma_fence_free(struct dma_fence *fence)
        free(fence, M_DRM, 0);
 }
 
+/*
+ * is a later than b
+ * if a and b are the same, should return false to avoid unwanted work
+ */
+static inline bool
+__dma_fence_is_later(uint64_t a, uint64_t b, const struct dma_fence_ops *ops)
+{
+       uint32_t al, bl;
+
+       if (ops->use_64bit_seqno)
+               return a > b;
+
+       al = a & 0xffffffff;
+       bl = b & 0xffffffff;
+
+       return (int)(al - bl) > 0;
+}
+
 static inline bool
 dma_fence_is_later(struct dma_fence *a, struct dma_fence *b)
 {
-       return (a->seqno > b->seqno);
+       if (a->context != b->context)
+               return false;
+       return __dma_fence_is_later(a->seqno, b->seqno, a->ops);
 }
 
 static inline void