dma-buf: make fence sequence numbers 64 bit v2
authorChristian König <christian.koenig@amd.com>
Wed, 14 Nov 2018 15:11:06 +0000 (16:11 +0100)
committerChristian König <christian.koenig@amd.com>
Fri, 7 Dec 2018 11:44:16 +0000 (12:44 +0100)
For a lot of use cases we need 64bit sequence numbers. Currently drivers
overload the dma_fence structure to store the additional bits.

Stop doing that and make the sequence number in the dma_fence always
64bit.

For compatibility with hardware which can do only 32bit sequences the
comparisons in __dma_fence_is_later only takes the lower 32bits as significant
when the upper 32bits are all zero.

v2: change the logic in __dma_fence_is_later

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Chunming Zhou <david1.zhou@amd.com>
Link: https://patchwork.freedesktop.org/patch/266927/
drivers/dma-buf/dma-fence.c
drivers/dma-buf/sw_sync.c
drivers/dma-buf/sync_file.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/i915/i915_sw_fence.c
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/vgem/vgem_fence.c
include/linux/dma-fence.h

index 136ec04..3aa8733 100644 (file)
@@ -649,7 +649,7 @@ EXPORT_SYMBOL(dma_fence_wait_any_timeout);
  */
 void
 dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
-              spinlock_t *lock, u64 context, unsigned seqno)
+              spinlock_t *lock, u64 context, u64 seqno)
 {
        BUG_ON(!lock);
        BUG_ON(!ops || !ops->get_driver_name || !ops->get_timeline_name);
index 53c1d6d..32dcf7b 100644 (file)
@@ -172,7 +172,7 @@ static bool timeline_fence_enable_signaling(struct dma_fence *fence)
 static void timeline_fence_value_str(struct dma_fence *fence,
                                    char *str, int size)
 {
-       snprintf(str, size, "%d", fence->seqno);
+       snprintf(str, size, "%lld", fence->seqno);
 }
 
 static void timeline_fence_timeline_value_str(struct dma_fence *fence,
index 35dd064..4f6305c 100644 (file)
@@ -144,7 +144,7 @@ char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
        } else {
                struct dma_fence *fence = sync_file->fence;
 
-               snprintf(buf, len, "%s-%s%llu-%d",
+               snprintf(buf, len, "%s-%s%llu-%lld",
                         fence->ops->get_driver_name(fence),
                         fence->ops->get_timeline_name(fence),
                         fence->context,
@@ -258,7 +258,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
 
                        i_b++;
                } else {
-                       if (pt_a->seqno - pt_b->seqno <= INT_MAX)
+                       if (__dma_fence_is_later(pt_a->seqno, pt_b->seqno))
                                add_fence(fences, &i, pt_a);
                        else
                                add_fence(fences, &i, pt_b);
index 12f2bf9..bfaf5c6 100644 (file)
@@ -388,7 +388,7 @@ void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
                           soffset, eoffset, eoffset - soffset);
 
                if (i->fence)
-                       seq_printf(m, " protected by 0x%08x on context %llu",
+                       seq_printf(m, " protected by 0x%016llx on context %llu",
                                   i->fence->seqno, i->fence->context);
 
                seq_printf(m, "\n");
index 6dbeed0..11bcdab 100644 (file)
@@ -393,7 +393,7 @@ static void timer_i915_sw_fence_wake(struct timer_list *t)
        if (!fence)
                return;
 
-       pr_notice("Asynchronous wait on fence %s:%s:%x timed out (hint:%pS)\n",
+       pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%pS)\n",
                  cb->dma->ops->get_driver_name(cb->dma),
                  cb->dma->ops->get_timeline_name(cb->dma),
                  cb->dma->seqno,
index 759c0fd..dfafa79 100644 (file)
@@ -1239,7 +1239,7 @@ static void print_request(struct drm_printer *m,
 
        x = print_sched_attr(rq->i915, &rq->sched.attr, buf, x, sizeof(buf));
 
-       drm_printf(m, "%s%x%s [%llx:%x]%s @ %dms: %s\n",
+       drm_printf(m, "%s%x%s [%llx:%llx]%s @ %dms: %s\n",
                   prefix,
                   rq->global_seqno,
                   i915_request_completed(rq) ? "!" : "",
index c1c420a..eb17c0c 100644 (file)
@@ -53,13 +53,13 @@ static void vgem_fence_release(struct dma_fence *base)
 
 static void vgem_fence_value_str(struct dma_fence *fence, char *str, int size)
 {
-       snprintf(str, size, "%u", fence->seqno);
+       snprintf(str, size, "%llu", fence->seqno);
 }
 
 static void vgem_fence_timeline_value_str(struct dma_fence *fence, char *str,
                                          int size)
 {
-       snprintf(str, size, "%u",
+       snprintf(str, size, "%llu",
                 dma_fence_is_signaled(fence) ? fence->seqno : 0);
 }
 
index 999e4b1..6b78846 100644 (file)
@@ -77,7 +77,7 @@ struct dma_fence {
        struct list_head cb_list;
        spinlock_t *lock;
        u64 context;
-       unsigned seqno;
+       u64 seqno;
        unsigned long flags;
        ktime_t timestamp;
        int error;
@@ -244,7 +244,7 @@ struct dma_fence_ops {
 };
 
 void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
-                   spinlock_t *lock, u64 context, unsigned seqno);
+                   spinlock_t *lock, u64 context, u64 seqno);
 
 void dma_fence_release(struct kref *kref);
 void dma_fence_free(struct dma_fence *fence);
@@ -414,9 +414,17 @@ dma_fence_is_signaled(struct dma_fence *fence)
  * Returns true if f1 is chronologically later than f2. Both fences must be
  * from the same context, since a seqno is not common across contexts.
  */
-static inline bool __dma_fence_is_later(u32 f1, u32 f2)
+static inline bool __dma_fence_is_later(u64 f1, u64 f2)
 {
-       return (int)(f1 - f2) > 0;
+       /* This is for backward compatibility with drivers which can only handle
+        * 32bit sequence numbers. Use a 64bit compare when any of the higher
+        * bits are none zero, otherwise use a 32bit compare with wrap around
+        * handling.
+        */
+       if (upper_32_bits(f1) || upper_32_bits(f2))
+               return f1 > f2;
+
+       return (int)(lower_32_bits(f1) - lower_32_bits(f2)) > 0;
 }
 
 /**
@@ -548,21 +556,21 @@ u64 dma_fence_context_alloc(unsigned num);
        do {                                                            \
                struct dma_fence *__ff = (f);                           \
                if (IS_ENABLED(CONFIG_DMA_FENCE_TRACE))                 \
-                       pr_info("f %llu#%u: " fmt,                      \
+                       pr_info("f %llu#%llu: " fmt,                    \
                                __ff->context, __ff->seqno, ##args);    \
        } while (0)
 
 #define DMA_FENCE_WARN(f, fmt, args...) \
        do {                                                            \
                struct dma_fence *__ff = (f);                           \
-               pr_warn("f %llu#%u: " fmt, __ff->context, __ff->seqno,  \
+               pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\
                         ##args);                                       \
        } while (0)
 
 #define DMA_FENCE_ERR(f, fmt, args...) \
        do {                                                            \
                struct dma_fence *__ff = (f);                           \
-               pr_err("f %llu#%u: " fmt, __ff->context, __ff->seqno,   \
+               pr_err("f %llu#%llu: " fmt, __ff->context, __ff->seqno, \
                        ##args);                                        \
        } while (0)