Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dma-fence: Use a flag for 64-bit seqnos

With the goal of reducing the need for drivers to touch (and dereference)
fence->ops, we move the 64-bit seqnos flag from struct dma_fence_ops to
the fence->flags.

Drivers which were setting this flag are changed to use new
dma_fence_init64() instead of dma_fence_init().

v2:
* Streamlined init and added kerneldoc.
* Rebase for amdgpu userq which landed since.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-by: Christian König <christian.koenig@amd.com> # v1
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
Link: https://lore.kernel.org/r/20250515095004.28318-3-tvrtko.ursulin@igalia.com

authored by

Tvrtko Ursulin and committed by
Tvrtko Ursulin
bf33a000 22b929b2

+58 -35
+2 -3
drivers/dma-buf/dma-fence-chain.c
··· 218 218 } 219 219 220 220 const struct dma_fence_ops dma_fence_chain_ops = { 221 - .use_64bit_seqno = true, 222 221 .get_driver_name = dma_fence_chain_get_driver_name, 223 222 .get_timeline_name = dma_fence_chain_get_timeline_name, 224 223 .enable_signaling = dma_fence_chain_enable_signaling, ··· 261 262 seqno = max(prev->seqno, seqno); 262 263 } 263 264 264 - dma_fence_init(&chain->base, &dma_fence_chain_ops, 265 - &chain->lock, context, seqno); 265 + dma_fence_init64(&chain->base, &dma_fence_chain_ops, &chain->lock, 266 + context, seqno); 266 267 267 268 /* 268 269 * Chaining dma_fence_chain container together is only allowed through
+44 -13
drivers/dma-buf/dma-fence.c
··· 989 989 } 990 990 EXPORT_SYMBOL(dma_fence_describe); 991 991 992 + static void 993 + __dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, 994 + spinlock_t *lock, u64 context, u64 seqno, unsigned long flags) 995 + { 996 + BUG_ON(!lock); 997 + BUG_ON(!ops || !ops->get_driver_name || !ops->get_timeline_name); 998 + 999 + kref_init(&fence->refcount); 1000 + fence->ops = ops; 1001 + INIT_LIST_HEAD(&fence->cb_list); 1002 + fence->lock = lock; 1003 + fence->context = context; 1004 + fence->seqno = seqno; 1005 + fence->flags = flags; 1006 + fence->error = 0; 1007 + 1008 + trace_dma_fence_init(fence); 1009 + } 1010 + 992 1011 /** 993 1012 * dma_fence_init - Initialize a custom fence. 994 1013 * @fence: the fence to initialize ··· 1027 1008 dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, 1028 1009 spinlock_t *lock, u64 context, u64 seqno) 1029 1010 { 1030 - BUG_ON(!lock); 1031 - BUG_ON(!ops || !ops->get_driver_name || !ops->get_timeline_name); 1032 - 1033 - kref_init(&fence->refcount); 1034 - fence->ops = ops; 1035 - INIT_LIST_HEAD(&fence->cb_list); 1036 - fence->lock = lock; 1037 - fence->context = context; 1038 - fence->seqno = seqno; 1039 - fence->flags = 0UL; 1040 - fence->error = 0; 1041 - 1042 - trace_dma_fence_init(fence); 1011 + __dma_fence_init(fence, ops, lock, context, seqno, 0UL); 1043 1012 } 1044 1013 EXPORT_SYMBOL(dma_fence_init); 1014 + 1015 + /** 1016 + * dma_fence_init64 - Initialize a custom fence with 64-bit seqno support. 1017 + * @fence: the fence to initialize 1018 + * @ops: the dma_fence_ops for operations on this fence 1019 + * @lock: the irqsafe spinlock to use for locking this fence 1020 + * @context: the execution context this fence is run on 1021 + * @seqno: a linear increasing sequence number for this context 1022 + * 1023 + * Initializes an allocated fence, the caller doesn't have to keep its 1024 + * refcount after committing with this fence, but it will need to hold a 1025 + * refcount again if &dma_fence_ops.enable_signaling gets called. 1026 + * 1027 + * Context and seqno are used for easy comparison between fences, allowing 1028 + * to check which fence is later by simply using dma_fence_later(). 1029 + */ 1030 + void 1031 + dma_fence_init64(struct dma_fence *fence, const struct dma_fence_ops *ops, 1032 + spinlock_t *lock, u64 context, u64 seqno) 1033 + { 1034 + __dma_fence_init(fence, ops, lock, context, seqno, 1035 + BIT(DMA_FENCE_FLAG_SEQNO64_BIT)); 1036 + } 1037 + EXPORT_SYMBOL(dma_fence_init64);
+3 -4
drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
··· 134 134 } 135 135 136 136 static const struct dma_fence_ops amdgpu_eviction_fence_ops = { 137 - .use_64bit_seqno = true, 138 137 .get_driver_name = amdgpu_eviction_fence_get_driver_name, 139 138 .get_timeline_name = amdgpu_eviction_fence_get_timeline_name, 140 139 .enable_signaling = amdgpu_eviction_fence_enable_signaling, ··· 159 160 ev_fence->evf_mgr = evf_mgr; 160 161 get_task_comm(ev_fence->timeline_name, current); 161 162 spin_lock_init(&ev_fence->lock); 162 - dma_fence_init(&ev_fence->base, &amdgpu_eviction_fence_ops, 163 - &ev_fence->lock, evf_mgr->ev_fence_ctx, 164 - atomic_inc_return(&evf_mgr->ev_fence_seq)); 163 + dma_fence_init64(&ev_fence->base, &amdgpu_eviction_fence_ops, 164 + &ev_fence->lock, evf_mgr->ev_fence_ctx, 165 + atomic_inc_return(&evf_mgr->ev_fence_seq)); 165 166 return ev_fence; 166 167 } 167 168
+2 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
··· 239 239 fence = &userq_fence->base; 240 240 userq_fence->fence_drv = fence_drv; 241 241 242 - dma_fence_init(fence, &amdgpu_userq_fence_ops, &userq_fence->lock, 243 - fence_drv->context, seq); 242 + dma_fence_init64(fence, &amdgpu_userq_fence_ops, &userq_fence->lock, 243 + fence_drv->context, seq); 244 244 245 245 amdgpu_userq_fence_driver_get(fence_drv); 246 246 dma_fence_get(fence); ··· 334 334 } 335 335 336 336 static const struct dma_fence_ops amdgpu_userq_fence_ops = { 337 - .use_64bit_seqno = true, 338 337 .get_driver_name = amdgpu_userq_fence_get_driver_name, 339 338 .get_timeline_name = amdgpu_userq_fence_get_timeline_name, 340 339 .signaled = amdgpu_userq_fence_signaled,
+2 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_tlb_fence.c
··· 71 71 } 72 72 73 73 static const struct dma_fence_ops amdgpu_tlb_fence_ops = { 74 - .use_64bit_seqno = true, 75 74 .get_driver_name = amdgpu_tlb_fence_get_driver_name, 76 75 .get_timeline_name = amdgpu_tlb_fence_get_timeline_name 77 76 }; ··· 100 101 INIT_WORK(&f->work, amdgpu_tlb_fence_work); 101 102 spin_lock_init(&f->lock); 102 103 103 - dma_fence_init(&f->base, &amdgpu_tlb_fence_ops, &f->lock, 104 - vm->tlb_fence_context, atomic64_read(&vm->tlb_seq)); 104 + dma_fence_init64(&f->base, &amdgpu_tlb_fence_ops, &f->lock, 105 + vm->tlb_fence_context, atomic64_read(&vm->tlb_seq)); 105 106 106 107 /* TODO: We probably need a separate wq here */ 107 108 dma_fence_get(&f->base);
+5 -9
include/linux/dma-fence.h
··· 98 98 }; 99 99 100 100 enum dma_fence_flag_bits { 101 + DMA_FENCE_FLAG_SEQNO64_BIT, 101 102 DMA_FENCE_FLAG_SIGNALED_BIT, 102 103 DMA_FENCE_FLAG_TIMESTAMP_BIT, 103 104 DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, ··· 126 125 * 127 126 */ 128 127 struct dma_fence_ops { 129 - /** 130 - * @use_64bit_seqno: 131 - * 132 - * True if this dma_fence implementation uses 64bit seqno, false 133 - * otherwise. 134 - */ 135 - bool use_64bit_seqno; 136 - 137 128 /** 138 129 * @get_driver_name: 139 130 * ··· 255 262 256 263 void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, 257 264 spinlock_t *lock, u64 context, u64 seqno); 265 + 266 + void dma_fence_init64(struct dma_fence *fence, const struct dma_fence_ops *ops, 267 + spinlock_t *lock, u64 context, u64 seqno); 258 268 259 269 void dma_fence_release(struct kref *kref); 260 270 void dma_fence_free(struct dma_fence *fence); ··· 451 455 * 32bit sequence numbers. Use a 64bit compare when the driver says to 452 456 * do so. 453 457 */ 454 - if (fence->ops->use_64bit_seqno) 458 + if (test_bit(DMA_FENCE_FLAG_SEQNO64_BIT, &fence->flags)) 455 459 return f1 > f2; 456 460 457 461 return (int)(lower_32_bits(f1) - lower_32_bits(f2)) > 0;