xref: /dragonfly/sys/dev/drm/include/linux/dma-fence.h (revision 789731325bde747251c28a37e0a00ed4efb88c46)
1 /*
2  * Copyright (c) 2019 Jonathan Gray <jsg@openbsd.org>
3  * Copyright (c) 2020 François Tigeot <ftigeot@wolfpond.org>
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #ifndef _LINUX_DMA_FENCE_H_
26 #define _LINUX_DMA_FENCE_H_
27 
28 #include <linux/err.h>
29 #include <linux/wait.h>
30 #include <linux/list.h>
31 #include <linux/bitops.h>
32 #include <linux/kref.h>
33 #include <linux/sched.h>
34 #include <linux/printk.h>
35 #include <linux/rcupdate.h>
36 
37 #define DMA_FENCE_TRACE(fence, fmt, args...) do {} while(0)
38 
39 struct dma_fence_cb;
40 
41 struct dma_fence {
42           struct kref refcount;
43           struct lock *lock;
44           const struct dma_fence_ops *ops;
45           struct rcu_head rcu;
46           struct list_head cb_list;
47           u64 context;
48           unsigned seqno;
49           unsigned long flags;
50           ktime_t timestamp;
51           int error;
52 };
53 
54 enum dma_fence_flag_bits {
55           DMA_FENCE_FLAG_SIGNALED_BIT,
56           DMA_FENCE_FLAG_TIMESTAMP_BIT,
57           DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
58           DMA_FENCE_FLAG_USER_BITS, /* must always be last member */
59 };
60 
61 typedef void (*dma_fence_func_t)(struct dma_fence *fence,
62                                          struct dma_fence_cb *cb);
63 
64 struct dma_fence_cb {
65           struct list_head node;
66           dma_fence_func_t func;
67 };
68 
69 struct dma_fence_ops {
70           const char * (*get_driver_name)(struct dma_fence *fence);
71           const char * (*get_timeline_name)(struct dma_fence *fence);
72           bool (*enable_signaling)(struct dma_fence *fence);
73           bool (*signaled)(struct dma_fence *fence);
74           signed long (*wait)(struct dma_fence *fence,
75                                   bool intr, signed long timeout);
76           void (*release)(struct dma_fence *fence);
77 
78           int (*fill_driver_data)(struct dma_fence *fence, void *data, int size);
79           void (*fence_value_str)(struct dma_fence *fence, char *str, int size);
80           void (*timeline_value_str)(struct dma_fence *fence,
81                                            char *str, int size);
82 };
83 
84 void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
85                         spinlock_t *lock, u64 context, unsigned seqno);
86 
87 void dma_fence_release(struct kref *kref);
88 
89 static inline struct dma_fence *
dma_fence_get(struct dma_fence * fence)90 dma_fence_get(struct dma_fence *fence)
91 {
92           if (fence)
93                     kref_get(&fence->refcount);
94           return fence;
95 }
96 
97 static inline struct dma_fence *
dma_fence_get_rcu(struct dma_fence * fence)98 dma_fence_get_rcu(struct dma_fence *fence)
99 {
100           if (fence)
101                     kref_get(&fence->refcount);
102           return fence;
103 }
104 
105 static inline void
dma_fence_put(struct dma_fence * fence)106 dma_fence_put(struct dma_fence *fence)
107 {
108           if (fence)
109                     kref_put(&fence->refcount, dma_fence_release);
110 }
111 
112 int dma_fence_signal(struct dma_fence *fence);
113 int dma_fence_signal_locked(struct dma_fence *fence);
114 
115 static inline bool
dma_fence_is_signaled(struct dma_fence * fence)116 dma_fence_is_signaled(struct dma_fence *fence)
117 {
118           if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
119                     return true;
120 
121           if (fence->ops->signaled && fence->ops->signaled(fence)) {
122                     dma_fence_signal(fence);
123                     return true;
124           }
125 
126           return false;
127 }
128 
129 void dma_fence_enable_sw_signaling(struct dma_fence *fence);
130 
131 signed long dma_fence_default_wait(struct dma_fence *fence,
132                                            bool intr, signed long timeout);
133 signed long dma_fence_wait_timeout(struct dma_fence *,
134                                            bool intr, signed long timeout);
135 signed long dma_fence_wait_any_timeout(struct dma_fence **fences,
136                                                uint32_t count,
137                                                bool intr, signed long timeout, uint32_t *idx);
138 
139 static inline signed long
dma_fence_wait(struct dma_fence * fence,bool intr)140 dma_fence_wait(struct dma_fence *fence, bool intr)
141 {
142           signed long ret;
143 
144           ret = dma_fence_wait_timeout(fence, intr, MAX_SCHEDULE_TIMEOUT);
145 
146           if (ret < 0)
147                     return ret;
148 
149           return 0;
150 }
151 
152 int dma_fence_add_callback(struct dma_fence *fence,
153                                  struct dma_fence_cb *cb,
154                                  dma_fence_func_t func);
155 
156 bool dma_fence_remove_callback(struct dma_fence *fence,
157                                      struct dma_fence_cb *cb);
158 
159 u64 dma_fence_context_alloc(unsigned num);
160 
161 static inline bool
dma_fence_is_later(struct dma_fence * a,struct dma_fence * b)162 dma_fence_is_later(struct dma_fence *a, struct dma_fence *b)
163 {
164           return (a->seqno > b->seqno);
165 }
166 
167 static inline void
dma_fence_set_error(struct dma_fence * fence,int error)168 dma_fence_set_error(struct dma_fence *fence, int error)
169 {
170           fence->error = error;
171 }
172 
173 static inline struct dma_fence *
dma_fence_get_rcu_safe(struct dma_fence ** dfp)174 dma_fence_get_rcu_safe(struct dma_fence **dfp)
175 {
176           struct dma_fence *fence;
177           if (dfp == NULL)
178                     return NULL;
179           fence = *dfp;
180           if (fence)
181                     kref_get(&fence->refcount);
182           return fence;
183 }
184 
185 void dma_fence_free(struct dma_fence *fence);
186 
187 #endif    /* _LINUX_DMA_FENCE_H_ */
188