2 * Copyright (c) 2019-2020 Jonathan Gray <jsg@openbsd.org>
3 * Copyright (c) 2020 François Tigeot <ftigeot@wolfpond.org>
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:
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
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
25 #include <linux/slab.h>
26 #include <linux/dma-fence.h>
29 dma_fence_init(struct dma_fence
*fence
, const struct dma_fence_ops
*ops
,
30 spinlock_t
*lock
, u64 context
, unsigned seqno
)
34 fence
->context
= context
;
38 kref_init(&fence
->refcount
);
39 INIT_LIST_HEAD(&fence
->cb_list
);
43 dma_fence_release(struct kref
*ref
)
45 struct dma_fence
*fence
= container_of(ref
, struct dma_fence
, refcount
);
47 if (fence
->ops
&& fence
->ops
->release
)
48 fence
->ops
->release(fence
);
54 dma_fence_wait_timeout(struct dma_fence
*fence
, bool intr
, long timeout
)
60 return fence
->ops
->wait(fence
, intr
, timeout
);
62 return dma_fence_default_wait(fence
, intr
, timeout
);
65 static atomic64_t drm_fence_context_count
= ATOMIC_INIT(1);
68 dma_fence_context_alloc(unsigned num
)
70 return atomic64_add_return(num
, &drm_fence_context_count
) - num
;
73 struct default_wait_cb
{
74 struct dma_fence_cb base
;
75 struct task_struct
*task
;
79 dma_fence_default_wait_cb(struct dma_fence
*fence
, struct dma_fence_cb
*cb
)
81 struct default_wait_cb
*wait
=
82 container_of(cb
, struct default_wait_cb
, base
);
84 wake_up_process(wait
->task
);
88 dma_fence_default_wait(struct dma_fence
*fence
, bool intr
, signed long timeout
)
90 long ret
= timeout
? timeout
: 1;
93 struct default_wait_cb cb
;
96 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT
, &fence
->flags
))
99 lockmgr(fence
->lock
, LK_EXCLUSIVE
);
101 was_set
= test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT
,
104 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT
, &fence
->flags
))
107 if (!was_set
&& fence
->ops
->enable_signaling
) {
108 if (!fence
->ops
->enable_signaling(fence
)) {
109 dma_fence_signal_locked(fence
);
119 cb
.base
.func
= dma_fence_default_wait_cb
;
121 list_add(&cb
.base
.node
, &fence
->cb_list
);
123 end
= jiffies
+ timeout
;
124 for (ret
= timeout
; ret
> 0; ret
= MAX(0, end
- jiffies
)) {
125 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT
, &fence
->flags
)) {
129 __set_current_state(TASK_INTERRUPTIBLE
);
132 __set_current_state(TASK_UNINTERRUPTIBLE
);
134 /* wake_up_process() directly uses task_struct pointers as sleep identifiers */
135 err
= lksleep(current
, fence
->lock
, intr
? PCATCH
: 0, "dmafence", ret
);
136 if (err
== EINTR
|| err
== ERESTART
) {
142 if (!list_empty(&cb
.base
.node
))
143 list_del(&cb
.base
.node
);
144 __set_current_state(TASK_RUNNING
);
146 lockmgr(fence
->lock
, LK_RELEASE
);
151 dma_fence_test_signaled_any(struct dma_fence
**fences
, uint32_t count
,
156 for (i
= 0; i
< count
; ++i
) {
157 struct dma_fence
*fence
= fences
[i
];
158 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT
, &fence
->flags
)) {
168 dma_fence_wait_any_timeout(struct dma_fence
**fences
, uint32_t count
,
169 bool intr
, long timeout
, uint32_t *idx
)
171 struct default_wait_cb
*cb
;
177 for (i
= 0; i
< count
; i
++) {
178 if (dma_fence_is_signaled(fences
[i
])) {
187 cb
= kcalloc(count
, sizeof(struct default_wait_cb
), GFP_KERNEL
);
191 for (i
= 0; i
< count
; i
++) {
192 struct dma_fence
*fence
= fences
[i
];
193 cb
[i
].task
= current
;
194 if (dma_fence_add_callback(fence
, &cb
[i
].base
,
195 dma_fence_default_wait_cb
)) {
202 end
= jiffies
+ timeout
;
203 for (ret
= timeout
; ret
> 0; ret
= MAX(0, end
- jiffies
)) {
204 if (dma_fence_test_signaled_any(fences
, count
, idx
))
206 err
= tsleep(current
, intr
? PCATCH
: 0, "dfwat", ret
);
207 if (err
== EINTR
|| err
== ERESTART
) {
215 dma_fence_remove_callback(fences
[i
], &cb
[i
].base
);
221 dma_fence_signal_locked(struct dma_fence
*fence
)
223 struct dma_fence_cb
*cur
, *tmp
;
224 struct list_head cb_list
;
229 if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT
, &fence
->flags
))
232 list_replace(&fence
->cb_list
, &cb_list
);
234 fence
->timestamp
= ktime_get();
235 set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT
, &fence
->flags
);
237 list_for_each_entry_safe(cur
, tmp
, &cb_list
, node
) {
238 INIT_LIST_HEAD(&cur
->node
);
239 cur
->func(fence
, cur
);
246 dma_fence_signal(struct dma_fence
*fence
)
253 lockmgr(fence
->lock
, LK_EXCLUSIVE
);
254 r
= dma_fence_signal_locked(fence
);
255 lockmgr(fence
->lock
, LK_RELEASE
);
261 dma_fence_enable_sw_signaling(struct dma_fence
*fence
)
263 if (!test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT
, &fence
->flags
) &&
264 !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT
, &fence
->flags
) &&
265 fence
->ops
->enable_signaling
) {
266 lockmgr(fence
->lock
, LK_EXCLUSIVE
);
267 if (!fence
->ops
->enable_signaling(fence
))
268 dma_fence_signal_locked(fence
);
269 lockmgr(fence
->lock
, LK_RELEASE
);
274 dma_fence_add_callback(struct dma_fence
*fence
, struct dma_fence_cb
*cb
,
275 dma_fence_func_t func
)
280 if (WARN_ON(!fence
|| !func
))
283 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT
, &fence
->flags
)) {
284 INIT_LIST_HEAD(&cb
->node
);
288 lockmgr(fence
->lock
, LK_EXCLUSIVE
);
290 was_set
= test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT
, &fence
->flags
);
292 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT
, &fence
->flags
))
294 else if (!was_set
&& fence
->ops
->enable_signaling
) {
295 if (!fence
->ops
->enable_signaling(fence
)) {
296 dma_fence_signal_locked(fence
);
303 list_add_tail(&cb
->node
, &fence
->cb_list
);
305 INIT_LIST_HEAD(&cb
->node
);
306 lockmgr(fence
->lock
, LK_RELEASE
);
312 dma_fence_remove_callback(struct dma_fence
*fence
, struct dma_fence_cb
*cb
)
316 lockmgr(fence
->lock
, LK_EXCLUSIVE
);
318 ret
= !list_empty(&cb
->node
);
320 list_del_init(&cb
->node
);
322 lockmgr(fence
->lock
, LK_RELEASE
);
328 dma_fence_free(struct dma_fence
*fence
)