1 /* Public domain. */
2
3 #ifndef _LINUX_DMA_FENCE_H
4 #define _LINUX_DMA_FENCE_H
5
6 #include <sys/types.h>
7 #include <sys/mutex.h>
8 #include <linux/kref.h>
9 #include <linux/list.h>
10 #include <linux/sched.h>
11 #include <linux/rcupdate.h>
12
13 #define DMA_FENCE_TRACE(fence, fmt, args...) do {} while(0)
14
15 struct dma_fence {
16 struct kref refcount;
17 const struct dma_fence_ops *ops;
18 unsigned long flags;
19 uint64_t context;
20 uint64_t seqno;
21 struct mutex *lock;
22 union {
23 struct list_head cb_list;
24 ktime_t timestamp;
25 struct rcu_head rcu;
26 };
27 int error;
28 };
29
30 enum dma_fence_flag_bits {
31 DMA_FENCE_FLAG_SIGNALED_BIT,
32 DMA_FENCE_FLAG_TIMESTAMP_BIT,
33 DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
34 DMA_FENCE_FLAG_USER_BITS,
35 };
36
37 struct dma_fence_ops {
38 const char * (*get_driver_name)(struct dma_fence *);
39 const char * (*get_timeline_name)(struct dma_fence *);
40 bool (*enable_signaling)(struct dma_fence *);
41 bool (*signaled)(struct dma_fence *);
42 long (*wait)(struct dma_fence *, bool, long);
43 void (*release)(struct dma_fence *);
44 void (*set_deadline)(struct dma_fence *, ktime_t);
45 bool use_64bit_seqno;
46 };
47
48 struct dma_fence_cb;
49 typedef void (*dma_fence_func_t)(struct dma_fence *fence, struct dma_fence_cb *cb);
50
51 struct dma_fence_cb {
52 struct list_head node;
53 dma_fence_func_t func;
54 };
55
56 uint64_t dma_fence_context_alloc(unsigned int);
57 struct dma_fence *dma_fence_get(struct dma_fence *);
58 struct dma_fence *dma_fence_get_rcu(struct dma_fence *);
59 struct dma_fence *dma_fence_get_rcu_safe(struct dma_fence **);
60 void dma_fence_release(struct kref *);
61 void dma_fence_put(struct dma_fence *);
62 int dma_fence_signal(struct dma_fence *);
63 int dma_fence_signal_locked(struct dma_fence *);
64 int dma_fence_signal_timestamp(struct dma_fence *, ktime_t);
65 int dma_fence_signal_timestamp_locked(struct dma_fence *, ktime_t);
66 bool dma_fence_is_signaled(struct dma_fence *);
67 bool dma_fence_is_signaled_locked(struct dma_fence *);
68 ktime_t dma_fence_timestamp(struct dma_fence *);
69 long dma_fence_default_wait(struct dma_fence *, bool, long);
70 long dma_fence_wait_any_timeout(struct dma_fence **, uint32_t, bool, long,
71 uint32_t *);
72 long dma_fence_wait_timeout(struct dma_fence *, bool, long);
73 long dma_fence_wait(struct dma_fence *, bool);
74 void dma_fence_enable_sw_signaling(struct dma_fence *);
75 void dma_fence_init(struct dma_fence *, const struct dma_fence_ops *,
76 struct mutex *, uint64_t, uint64_t);
77 int dma_fence_add_callback(struct dma_fence *, struct dma_fence_cb *,
78 dma_fence_func_t);
79 bool dma_fence_remove_callback(struct dma_fence *, struct dma_fence_cb *);
80 bool dma_fence_is_container(struct dma_fence *);
81 void dma_fence_set_deadline(struct dma_fence *, ktime_t);
82
83 struct dma_fence *dma_fence_get_stub(void);
84 struct dma_fence *dma_fence_allocate_private_stub(ktime_t);
85
86 static inline void
dma_fence_free(struct dma_fence * fence)87 dma_fence_free(struct dma_fence *fence)
88 {
89 free(fence, M_DRM, 0);
90 }
91
92 /*
93 * is a later than b
94 * if a and b are the same, should return false to avoid unwanted work
95 */
96 static inline bool
__dma_fence_is_later(uint64_t a,uint64_t b,const struct dma_fence_ops * ops)97 __dma_fence_is_later(uint64_t a, uint64_t b, const struct dma_fence_ops *ops)
98 {
99 uint32_t al, bl;
100
101 if (ops->use_64bit_seqno)
102 return a > b;
103
104 al = a & 0xffffffff;
105 bl = b & 0xffffffff;
106
107 return (int)(al - bl) > 0;
108 }
109
110 static inline bool
dma_fence_is_later(struct dma_fence * a,struct dma_fence * b)111 dma_fence_is_later(struct dma_fence *a, struct dma_fence *b)
112 {
113 if (a->context != b->context)
114 return false;
115 return __dma_fence_is_later(a->seqno, b->seqno, a->ops);
116 }
117
118 static inline bool
dma_fence_is_later_or_same(struct dma_fence * a,struct dma_fence * b)119 dma_fence_is_later_or_same(struct dma_fence *a, struct dma_fence *b)
120 {
121 if (a == b)
122 return true;
123 return dma_fence_is_later(a, b);
124 }
125
126 static inline void
dma_fence_set_error(struct dma_fence * fence,int error)127 dma_fence_set_error(struct dma_fence *fence, int error)
128 {
129 fence->error = error;
130 }
131
132 static inline bool
dma_fence_begin_signalling(void)133 dma_fence_begin_signalling(void)
134 {
135 return true;
136 }
137
138 static inline void
dma_fence_end_signalling(bool x)139 dma_fence_end_signalling(bool x)
140 {
141 }
142
143 #endif
144