linux_dma_fence.c revision 1.18 1 /* $NetBSD: linux_dma_fence.c,v 1.18 2021/12/19 12:00:48 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: linux_dma_fence.c,v 1.18 2021/12/19 12:00:48 riastradh Exp $");
34
35 #include <sys/atomic.h>
36 #include <sys/condvar.h>
37 #include <sys/queue.h>
38
39 #include <linux/atomic.h>
40 #include <linux/dma-fence.h>
41 #include <linux/errno.h>
42 #include <linux/kref.h>
43 #include <linux/sched.h>
44 #include <linux/spinlock.h>
45
46 /*
47 * linux_dma_fence_trace
48 *
49 * True if we print DMA_FENCE_TRACE messages, false if not. These
50 * are extremely noisy, too much even for AB_VERBOSE and AB_DEBUG
51 * in boothowto.
52 */
53 int linux_dma_fence_trace = 0;
54
55 /*
56 * dma_fence_referenced_p(fence)
57 *
58 * True if fence has a positive reference count. True after
59 * dma_fence_init; after the last dma_fence_put, this becomes
60 * false.
61 */
62 static inline bool __diagused
63 dma_fence_referenced_p(struct dma_fence *fence)
64 {
65
66 return kref_referenced_p(&fence->refcount);
67 }
68
69 /*
70 * dma_fence_init(fence, ops, lock, context, seqno)
71 *
72 * Initialize fence. Caller should call dma_fence_destroy when
73 * done, after all references have been released.
74 */
75 void
76 dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
77 spinlock_t *lock, unsigned context, unsigned seqno)
78 {
79
80 kref_init(&fence->refcount);
81 fence->lock = lock;
82 fence->flags = 0;
83 fence->context = context;
84 fence->seqno = seqno;
85 fence->ops = ops;
86 fence->error = 0;
87 TAILQ_INIT(&fence->f_callbacks);
88 cv_init(&fence->f_cv, "dmafence");
89 }
90
91 /*
92 * dma_fence_reset(fence)
93 *
94 * Ensure fence is in a quiescent state. Allowed either for newly
95 * initialized or freed fences, but not fences with more than one
96 * reference.
97 *
98 * XXX extension to Linux API
99 */
100 void
101 dma_fence_reset(struct dma_fence *fence, const struct dma_fence_ops *ops,
102 spinlock_t *lock, unsigned context, unsigned seqno)
103 {
104
105 KASSERT(kref_read(&fence->refcount) == 0 ||
106 kref_read(&fence->refcount) == 1);
107 KASSERT(TAILQ_EMPTY(&fence->f_callbacks));
108 KASSERT(fence->lock == lock);
109 KASSERT(fence->ops == ops);
110
111 kref_init(&fence->refcount);
112 fence->flags = 0;
113 fence->context = context;
114 fence->seqno = seqno;
115 fence->error = 0;
116 }
117
118 /*
119 * dma_fence_destroy(fence)
120 *
121 * Clean up memory initialized with dma_fence_init. This is meant
122 * to be used after a fence release callback.
123 */
124 void
125 dma_fence_destroy(struct dma_fence *fence)
126 {
127
128 KASSERT(!dma_fence_referenced_p(fence));
129
130 KASSERT(TAILQ_EMPTY(&fence->f_callbacks));
131 cv_destroy(&fence->f_cv);
132 }
133
134 static void
135 dma_fence_free_cb(struct rcu_head *rcu)
136 {
137 struct dma_fence *fence = container_of(rcu, struct dma_fence, f_rcu);
138
139 KASSERT(!dma_fence_referenced_p(fence));
140
141 dma_fence_destroy(fence);
142 kfree(fence);
143 }
144
145 /*
146 * dma_fence_free(fence)
147 *
148 * Schedule fence to be destroyed and then freed with kfree after
149 * any pending RCU read sections on all CPUs have completed.
150 * Caller must guarantee all references have been released. This
151 * is meant to be used after a fence release callback.
152 *
153 * NOTE: Callers assume kfree will be used. We don't even use
154 * kmalloc to allocate these -- caller is expected to allocate
155 * memory with kmalloc to be initialized with dma_fence_init.
156 */
157 void
158 dma_fence_free(struct dma_fence *fence)
159 {
160
161 KASSERT(!dma_fence_referenced_p(fence));
162
163 call_rcu(&fence->f_rcu, &dma_fence_free_cb);
164 }
165
166 /*
167 * dma_fence_context_alloc(n)
168 *
169 * Return the first of a contiguous sequence of unique
170 * identifiers, at least until the system wraps around.
171 */
172 unsigned
173 dma_fence_context_alloc(unsigned n)
174 {
175 static volatile unsigned next_context = 0;
176
177 return atomic_add_int_nv(&next_context, n) - n;
178 }
179
180 /*
181 * dma_fence_is_later(a, b)
182 *
183 * True if the sequence number of fence a is later than the
184 * sequence number of fence b. Since sequence numbers wrap
185 * around, we define this to mean that the sequence number of
186 * fence a is no more than INT_MAX past the sequence number of
187 * fence b.
188 *
189 * The two fences must have the same context.
190 */
191 bool
192 dma_fence_is_later(struct dma_fence *a, struct dma_fence *b)
193 {
194
195 KASSERTMSG(a->context == b->context, "incommensurate fences"
196 ": %u @ %p =/= %u @ %p", a->context, a, b->context, b);
197
198 return a->seqno - b->seqno < INT_MAX;
199 }
200
201 /*
202 * dma_fence_get_stub()
203 *
204 * Return a dma fence that is always already signalled.
205 */
206 struct dma_fence *
207 dma_fence_get_stub(void)
208 {
209 /*
210 * XXX This probably isn't good enough -- caller may try
211 * operations on this that require the lock, which will
212 * require us to create and destroy the lock on module
213 * load/unload.
214 */
215 static struct dma_fence fence = {
216 .refcount = {1}, /* always referenced */
217 .flags = 1u << DMA_FENCE_FLAG_SIGNALED_BIT,
218 };
219
220 return dma_fence_get(&fence);
221 }
222
223 /*
224 * dma_fence_get(fence)
225 *
226 * Acquire a reference to fence. The fence must not be being
227 * destroyed. Return the fence.
228 */
229 struct dma_fence *
230 dma_fence_get(struct dma_fence *fence)
231 {
232
233 if (fence)
234 kref_get(&fence->refcount);
235 return fence;
236 }
237
238 /*
239 * dma_fence_get_rcu(fence)
240 *
241 * Attempt to acquire a reference to a fence that may be about to
242 * be destroyed, during a read section. Return the fence on
243 * success, or NULL on failure.
244 */
245 struct dma_fence *
246 dma_fence_get_rcu(struct dma_fence *fence)
247 {
248
249 __insn_barrier();
250 if (!kref_get_unless_zero(&fence->refcount))
251 return NULL;
252 return fence;
253 }
254
255 /*
256 * dma_fence_get_rcu_safe(fencep)
257 *
258 * Attempt to acquire a reference to the fence *fencep, which may
259 * be about to be destroyed, during a read section. If the value
260 * of *fencep changes after we read *fencep but before we
261 * increment its reference count, retry. Return *fencep on
262 * success, or NULL on failure.
263 */
264 struct dma_fence *
265 dma_fence_get_rcu_safe(struct dma_fence *volatile const *fencep)
266 {
267 struct dma_fence *fence, *fence0;
268
269 retry:
270 fence = *fencep;
271
272 /* Load fence only once. */
273 __insn_barrier();
274
275 /* If there's nothing there, give up. */
276 if (fence == NULL)
277 return NULL;
278
279 /* Make sure we don't load stale fence guts. */
280 membar_datadep_consumer();
281
282 /* Try to acquire a reference. If we can't, try again. */
283 if (!dma_fence_get_rcu(fence))
284 goto retry;
285
286 /*
287 * Confirm that it's still the same fence. If not, release it
288 * and retry.
289 */
290 fence0 = *fencep;
291 __insn_barrier();
292 if (fence != fence0) {
293 dma_fence_put(fence);
294 goto retry;
295 }
296
297 /* Success! */
298 return fence;
299 }
300
301 static void
302 dma_fence_release(struct kref *refcount)
303 {
304 struct dma_fence *fence = container_of(refcount, struct dma_fence,
305 refcount);
306
307 KASSERT(!dma_fence_referenced_p(fence));
308
309 if (fence->ops->release)
310 (*fence->ops->release)(fence);
311 else
312 dma_fence_free(fence);
313 }
314
315 /*
316 * dma_fence_put(fence)
317 *
318 * Release a reference to fence. If this was the last one, call
319 * the fence's release callback.
320 */
321 void
322 dma_fence_put(struct dma_fence *fence)
323 {
324
325 if (fence == NULL)
326 return;
327 KASSERT(dma_fence_referenced_p(fence));
328 kref_put(&fence->refcount, &dma_fence_release);
329 }
330
331 /*
332 * dma_fence_ensure_signal_enabled(fence)
333 *
334 * Internal subroutine. If the fence was already signalled,
335 * return -ENOENT. Otherwise, if the enable signalling callback
336 * has not been called yet, call it. If fails, signal the fence
337 * and return -ENOENT. If it succeeds, or if it had already been
338 * called, return zero to indicate success.
339 *
340 * Caller must hold the fence's lock.
341 */
342 static int
343 dma_fence_ensure_signal_enabled(struct dma_fence *fence)
344 {
345
346 KASSERT(dma_fence_referenced_p(fence));
347 KASSERT(spin_is_locked(fence->lock));
348
349 /* If the fence was already signalled, fail with -ENOENT. */
350 if (fence->flags & (1u << DMA_FENCE_FLAG_SIGNALED_BIT))
351 return -ENOENT;
352
353 /*
354 * If the enable signaling callback has been called, success.
355 * Otherwise, set the bit indicating it.
356 */
357 if (test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags))
358 return 0;
359
360 /* Otherwise, note that we've called it and call it. */
361 KASSERT(fence->ops->enable_signaling);
362 if (!(*fence->ops->enable_signaling)(fence)) {
363 /* If it failed, signal and return -ENOENT. */
364 dma_fence_signal_locked(fence);
365 return -ENOENT;
366 }
367
368 /* Success! */
369 return 0;
370 }
371
372 /*
373 * dma_fence_add_callback(fence, fcb, fn)
374 *
375 * If fence has been signalled, return -ENOENT. If the enable
376 * signalling callback hasn't been called yet, call it; if it
377 * fails, return -ENOENT. Otherwise, arrange to call fn(fence,
378 * fcb) when it is signalled, and return 0.
379 *
380 * The fence uses memory allocated by the caller in fcb from the
381 * time of dma_fence_add_callback either to the time of
382 * dma_fence_remove_callback, or just before calling fn.
383 */
384 int
385 dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *fcb,
386 dma_fence_func_t fn)
387 {
388 int ret;
389
390 KASSERT(dma_fence_referenced_p(fence));
391
392 /* Optimistically try to skip the lock if it's already signalled. */
393 if (fence->flags & (1u << DMA_FENCE_FLAG_SIGNALED_BIT)) {
394 ret = -ENOENT;
395 goto out0;
396 }
397
398 /* Acquire the lock. */
399 spin_lock(fence->lock);
400
401 /* Ensure signalling is enabled, or fail if we can't. */
402 ret = dma_fence_ensure_signal_enabled(fence);
403 if (ret)
404 goto out1;
405
406 /* Insert the callback. */
407 fcb->func = fn;
408 TAILQ_INSERT_TAIL(&fence->f_callbacks, fcb, fcb_entry);
409 fcb->fcb_onqueue = true;
410
411 /* Release the lock and we're done. */
412 out1: spin_unlock(fence->lock);
413 out0: return ret;
414 }
415
416 /*
417 * dma_fence_remove_callback(fence, fcb)
418 *
419 * Remove the callback fcb from fence. Return true if it was
420 * removed from the list, or false if it had already run and so
421 * was no longer queued anyway. Caller must have already called
422 * dma_fence_add_callback(fence, fcb).
423 */
424 bool
425 dma_fence_remove_callback(struct dma_fence *fence, struct dma_fence_cb *fcb)
426 {
427 bool onqueue;
428
429 KASSERT(dma_fence_referenced_p(fence));
430
431 spin_lock(fence->lock);
432 onqueue = fcb->fcb_onqueue;
433 if (onqueue) {
434 TAILQ_REMOVE(&fence->f_callbacks, fcb, fcb_entry);
435 fcb->fcb_onqueue = false;
436 }
437 spin_unlock(fence->lock);
438
439 return onqueue;
440 }
441
442 /*
443 * dma_fence_enable_sw_signaling(fence)
444 *
445 * If it hasn't been called yet and the fence hasn't been
446 * signalled yet, call the fence's enable_sw_signaling callback.
447 * If when that happens, the callback indicates failure by
448 * returning false, signal the fence.
449 */
450 void
451 dma_fence_enable_sw_signaling(struct dma_fence *fence)
452 {
453
454 KASSERT(dma_fence_referenced_p(fence));
455
456 spin_lock(fence->lock);
457 (void)dma_fence_ensure_signal_enabled(fence);
458 spin_unlock(fence->lock);
459 }
460
461 /*
462 * dma_fence_is_signaled(fence)
463 *
464 * Test whether the fence has been signalled. If it has been
465 * signalled by dma_fence_signal(_locked), return true. If the
466 * signalled callback returns true indicating that some implicit
467 * external condition has changed, call the callbacks as if with
468 * dma_fence_signal.
469 */
470 bool
471 dma_fence_is_signaled(struct dma_fence *fence)
472 {
473 bool signaled;
474
475 KASSERT(dma_fence_referenced_p(fence));
476
477 spin_lock(fence->lock);
478 signaled = dma_fence_is_signaled_locked(fence);
479 spin_unlock(fence->lock);
480
481 return signaled;
482 }
483
484 /*
485 * dma_fence_is_signaled_locked(fence)
486 *
487 * Test whether the fence has been signalled. Like
488 * dma_fence_is_signaleed, but caller already holds the fence's lock.
489 */
490 bool
491 dma_fence_is_signaled_locked(struct dma_fence *fence)
492 {
493
494 KASSERT(dma_fence_referenced_p(fence));
495 KASSERT(spin_is_locked(fence->lock));
496
497 /* Check whether we already set the signalled bit. */
498 if (fence->flags & (1u << DMA_FENCE_FLAG_SIGNALED_BIT))
499 return true;
500
501 /* If there's a signalled callback, test it. */
502 if (fence->ops->signaled) {
503 if ((*fence->ops->signaled)(fence)) {
504 /*
505 * It's been signalled implicitly by some
506 * external phenomonen. Act as though someone
507 * has called dma_fence_signal.
508 */
509 dma_fence_signal_locked(fence);
510 return true;
511 }
512 }
513
514 return false;
515 }
516
517 /*
518 * dma_fence_set_error(fence, error)
519 *
520 * Set an error code prior to dma_fence_signal for use by a
521 * waiter to learn about success or failure of the fence.
522 */
523 void
524 dma_fence_set_error(struct dma_fence *fence, int error)
525 {
526
527 KASSERT(!(fence->flags & (1u << DMA_FENCE_FLAG_SIGNALED_BIT)));
528 KASSERTMSG(error >= -ELAST, "%d", error);
529 KASSERTMSG(error < 0, "%d", error);
530
531 fence->error = error;
532 }
533
534 /*
535 * dma_fence_get_status(fence)
536 *
537 * Return 0 if fence has yet to be signalled, 1 if it has been
538 * signalled without error, or negative error code if
539 * dma_fence_set_error was used.
540 */
541 int
542 dma_fence_get_status(struct dma_fence *fence)
543 {
544 int ret;
545
546 spin_lock(fence->lock);
547 if (!dma_fence_is_signaled_locked(fence)) {
548 ret = 0;
549 } else if (fence->error) {
550 ret = fence->error;
551 KASSERTMSG(ret < 0, "%d", ret);
552 } else {
553 ret = 1;
554 }
555 spin_unlock(fence->lock);
556
557 return ret;
558 }
559
560 /*
561 * dma_fence_signal(fence)
562 *
563 * Signal the fence. If it has already been signalled, return
564 * -EINVAL. If it has not been signalled, call the enable
565 * signalling callback if it hasn't been called yet, and remove
566 * each registered callback from the queue and call it; then
567 * return 0.
568 */
569 int
570 dma_fence_signal(struct dma_fence *fence)
571 {
572 int ret;
573
574 KASSERT(dma_fence_referenced_p(fence));
575
576 spin_lock(fence->lock);
577 ret = dma_fence_signal_locked(fence);
578 spin_unlock(fence->lock);
579
580 return ret;
581 }
582
583 /*
584 * dma_fence_signal_locked(fence)
585 *
586 * Signal the fence. Like dma_fence_signal, but caller already
587 * holds the fence's lock.
588 */
589 int
590 dma_fence_signal_locked(struct dma_fence *fence)
591 {
592 struct dma_fence_cb *fcb, *next;
593
594 KASSERT(dma_fence_referenced_p(fence));
595 KASSERT(spin_is_locked(fence->lock));
596
597 /* If it's been signalled, fail; otherwise set the signalled bit. */
598 if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
599 return -EINVAL;
600
601 /* Wake waiters. */
602 cv_broadcast(&fence->f_cv);
603
604 /* Remove and call the callbacks. */
605 TAILQ_FOREACH_SAFE(fcb, &fence->f_callbacks, fcb_entry, next) {
606 TAILQ_REMOVE(&fence->f_callbacks, fcb, fcb_entry);
607 fcb->fcb_onqueue = false;
608 (*fcb->func)(fence, fcb);
609 }
610
611 /* Success! */
612 return 0;
613 }
614
615 struct wait_any {
616 struct dma_fence_cb fcb;
617 struct wait_any1 {
618 kmutex_t lock;
619 kcondvar_t cv;
620 bool done;
621 uint32_t *ip;
622 struct wait_any *cb;
623 } *common;
624 };
625
626 static void
627 wait_any_cb(struct dma_fence *fence, struct dma_fence_cb *fcb)
628 {
629 struct wait_any *cb = container_of(fcb, struct wait_any, fcb);
630
631 KASSERT(dma_fence_referenced_p(fence));
632
633 mutex_enter(&cb->common->lock);
634 cb->common->done = true;
635 if (cb->common->ip)
636 *cb->common->ip = cb - cb->common->cb;
637 cv_broadcast(&cb->common->cv);
638 mutex_exit(&cb->common->lock);
639 }
640
641 /*
642 * dma_fence_wait_any_timeout(fence, nfences, intr, timeout, ip)
643 *
644 * Wait for any of fences[0], fences[1], fences[2], ...,
645 * fences[nfences-1] to be signalled. If ip is nonnull, set *ip
646 * to the index of the first one.
647 */
648 long
649 dma_fence_wait_any_timeout(struct dma_fence **fences, uint32_t nfences,
650 bool intr, long timeout, uint32_t *ip)
651 {
652 struct wait_any1 common;
653 struct wait_any *cb;
654 uint32_t i, j;
655 int start, end;
656 long ret = 0;
657
658 /* Allocate an array of callback records. */
659 cb = kcalloc(nfences, sizeof(cb[0]), GFP_KERNEL);
660 if (cb == NULL) {
661 ret = -ENOMEM;
662 goto out0;
663 }
664
665 /* Initialize a mutex and condvar for the common wait. */
666 mutex_init(&common.lock, MUTEX_DEFAULT, IPL_VM);
667 cv_init(&common.cv, "fence");
668 common.done = false;
669 common.ip = ip;
670 common.cb = cb;
671
672 /* Add a callback to each of the fences, or stop here if we can't. */
673 for (i = 0; i < nfences; i++) {
674 cb[i].common = &common;
675 KASSERT(dma_fence_referenced_p(fences[i]));
676 ret = dma_fence_add_callback(fences[i], &cb[i].fcb,
677 &wait_any_cb);
678 if (ret)
679 goto out1;
680 }
681
682 /*
683 * Test whether any of the fences has been signalled. If they
684 * have, stop here. If the haven't, we are guaranteed to be
685 * notified by one of the callbacks when they have.
686 */
687 for (j = 0; j < nfences; j++) {
688 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fences[j]->flags)) {
689 if (ip)
690 *ip = j;
691 ret = 0;
692 goto out1;
693 }
694 }
695
696 /*
697 * None of them was ready immediately. Wait for one of the
698 * callbacks to notify us when it is done.
699 */
700 mutex_enter(&common.lock);
701 while (timeout > 0 && !common.done) {
702 start = getticks();
703 __insn_barrier();
704 if (intr) {
705 if (timeout != MAX_SCHEDULE_TIMEOUT) {
706 ret = -cv_timedwait_sig(&common.cv,
707 &common.lock, MIN(timeout, /* paranoia */
708 MAX_SCHEDULE_TIMEOUT));
709 } else {
710 ret = -cv_wait_sig(&common.cv, &common.lock);
711 }
712 } else {
713 if (timeout != MAX_SCHEDULE_TIMEOUT) {
714 ret = -cv_timedwait(&common.cv,
715 &common.lock, MIN(timeout, /* paranoia */
716 MAX_SCHEDULE_TIMEOUT));
717 } else {
718 cv_wait(&common.cv, &common.lock);
719 ret = 0;
720 }
721 }
722 end = getticks();
723 __insn_barrier();
724 if (ret) {
725 if (ret == -ERESTART)
726 ret = -ERESTARTSYS;
727 break;
728 }
729 timeout -= MIN(timeout, (unsigned)end - (unsigned)start);
730 }
731 mutex_exit(&common.lock);
732
733 /*
734 * Massage the return code: if we were interrupted, return
735 * ERESTARTSYS; if cv_timedwait timed out, return 0; otherwise
736 * return the remaining time.
737 */
738 if (ret < 0) {
739 if (ret == -EINTR || ret == -ERESTART)
740 ret = -ERESTARTSYS;
741 if (ret == -EWOULDBLOCK)
742 ret = 0;
743 } else {
744 KASSERT(ret == 0);
745 ret = timeout;
746 }
747
748 out1: while (i --> 0)
749 (void)dma_fence_remove_callback(fences[i], &cb[i].fcb);
750 cv_destroy(&common.cv);
751 mutex_destroy(&common.lock);
752 kfree(cb);
753 out0: return ret;
754 }
755
756 /*
757 * dma_fence_wait_timeout(fence, intr, timeout)
758 *
759 * Wait until fence is signalled; or until interrupt, if intr is
760 * true; or until timeout, if positive. Return -ERESTARTSYS if
761 * interrupted, negative error code on any other error, zero on
762 * timeout, or positive number of ticks remaining if the fence is
763 * signalled before the timeout. Works by calling the fence wait
764 * callback.
765 *
766 * The timeout must be nonnegative and less than
767 * MAX_SCHEDULE_TIMEOUT.
768 */
769 long
770 dma_fence_wait_timeout(struct dma_fence *fence, bool intr, long timeout)
771 {
772
773 KASSERT(dma_fence_referenced_p(fence));
774 KASSERT(timeout >= 0);
775 KASSERT(timeout < MAX_SCHEDULE_TIMEOUT);
776
777 if (fence->ops->wait)
778 return (*fence->ops->wait)(fence, intr, timeout);
779 else
780 return dma_fence_default_wait(fence, intr, timeout);
781 }
782
783 /*
784 * dma_fence_wait(fence, intr)
785 *
786 * Wait until fence is signalled; or until interrupt, if intr is
787 * true. Return -ERESTARTSYS if interrupted, negative error code
788 * on any other error, zero on sucess. Works by calling the fence
789 * wait callback with MAX_SCHEDULE_TIMEOUT.
790 */
791 long
792 dma_fence_wait(struct dma_fence *fence, bool intr)
793 {
794 long ret;
795
796 KASSERT(dma_fence_referenced_p(fence));
797
798 if (fence->ops->wait)
799 ret = (*fence->ops->wait)(fence, intr, MAX_SCHEDULE_TIMEOUT);
800 else
801 ret = dma_fence_default_wait(fence, intr,
802 MAX_SCHEDULE_TIMEOUT);
803 KASSERT(ret != 0);
804
805 return (ret < 0 ? ret : 0);
806 }
807
808 /*
809 * dma_fence_default_wait(fence, intr, timeout)
810 *
811 * Default implementation of fence wait callback using a condition
812 * variable. If the fence is already signalled, return timeout,
813 * or 1 if timeout is zero meaning poll. If the enable signalling
814 * callback hasn't been called, call it, and if it fails, act as
815 * if the fence had been signalled. Otherwise, wait on the
816 * internal condvar. If timeout is MAX_SCHEDULE_TIMEOUT, wait
817 * indefinitely.
818 */
819 long
820 dma_fence_default_wait(struct dma_fence *fence, bool intr, long timeout)
821 {
822 int starttime = 0, now = 0, deadline = 0; /* XXXGCC */
823 kmutex_t *lock = &fence->lock->sl_lock;
824 long ret = 0;
825
826 KASSERT(dma_fence_referenced_p(fence));
827 KASSERTMSG(timeout >= 0, "timeout %ld", timeout);
828 KASSERTMSG(timeout <= MAX_SCHEDULE_TIMEOUT, "timeout %ld", timeout);
829
830 /* Optimistically try to skip the lock if it's already signalled. */
831 if (fence->flags & (1u << DMA_FENCE_FLAG_SIGNALED_BIT))
832 return (timeout ? timeout : 1);
833
834 /* Acquire the lock. */
835 spin_lock(fence->lock);
836
837 /* Ensure signalling is enabled, or stop if already completed. */
838 if (dma_fence_ensure_signal_enabled(fence) != 0) {
839 spin_unlock(fence->lock);
840 return (timeout ? timeout : 1);
841 }
842
843 /* If merely polling, stop here. */
844 if (timeout == 0) {
845 spin_unlock(fence->lock);
846 return 0;
847 }
848
849 /* Find out what our deadline is so we can handle spurious wakeup. */
850 if (timeout < MAX_SCHEDULE_TIMEOUT) {
851 now = getticks();
852 __insn_barrier();
853 starttime = now;
854 deadline = starttime + timeout;
855 }
856
857 /* Wait until the signalled bit is set. */
858 while (!(fence->flags & (1u << DMA_FENCE_FLAG_SIGNALED_BIT))) {
859 /*
860 * If there's a timeout and we've passed the deadline,
861 * give up.
862 */
863 if (timeout < MAX_SCHEDULE_TIMEOUT) {
864 now = getticks();
865 __insn_barrier();
866 if (deadline <= now)
867 break;
868 }
869 if (intr) {
870 if (timeout < MAX_SCHEDULE_TIMEOUT) {
871 ret = -cv_timedwait_sig(&fence->f_cv, lock,
872 deadline - now);
873 } else {
874 ret = -cv_wait_sig(&fence->f_cv, lock);
875 }
876 } else {
877 if (timeout < MAX_SCHEDULE_TIMEOUT) {
878 ret = -cv_timedwait(&fence->f_cv, lock,
879 deadline - now);
880 } else {
881 cv_wait(&fence->f_cv, lock);
882 ret = 0;
883 }
884 }
885 /* If the wait failed, give up. */
886 if (ret) {
887 if (ret == -ERESTART)
888 ret = -ERESTARTSYS;
889 break;
890 }
891 }
892
893 /* All done. Release the lock. */
894 spin_unlock(fence->lock);
895
896 /* If cv_timedwait gave up, return 0 meaning timeout. */
897 if (ret == -EWOULDBLOCK) {
898 /* Only cv_timedwait and cv_timedwait_sig can return this. */
899 KASSERT(timeout < MAX_SCHEDULE_TIMEOUT);
900 return 0;
901 }
902
903 /* If there was a timeout and the deadline passed, return 0. */
904 if (timeout < MAX_SCHEDULE_TIMEOUT) {
905 if (deadline <= now)
906 return 0;
907 }
908
909 /* If we were interrupted, return -ERESTARTSYS. */
910 if (ret == -EINTR || ret == -ERESTART)
911 return -ERESTARTSYS;
912
913 /* If there was any other kind of error, fail. */
914 if (ret)
915 return ret;
916
917 /*
918 * Success! Return the number of ticks left, at least 1, or 1
919 * if no timeout.
920 */
921 return (timeout < MAX_SCHEDULE_TIMEOUT ? MIN(deadline - now, 1) : 1);
922 }
923
924 /*
925 * __dma_fence_signal(fence)
926 *
927 * Set fence's signalled bit, without waking waiters yet. Return
928 * true if it was newly set, false if it was already set.
929 */
930 bool
931 __dma_fence_signal(struct dma_fence *fence)
932 {
933
934 if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
935 return false;
936
937 return true;
938 }
939
940 /*
941 * __dma_fence_signal_wake(fence)
942 *
943 * Wake fence's waiters. Caller must have previously called
944 * __dma_fence_signal and it must have previously returned true.
945 */
946 void
947 __dma_fence_signal_wake(struct dma_fence *fence, ktime_t timestamp)
948 {
949 struct dma_fence_cb *fcb, *next;
950
951 spin_lock(fence->lock);
952
953 KASSERT(fence->flags & DMA_FENCE_FLAG_SIGNALED_BIT);
954
955 /* Wake waiters. */
956 cv_broadcast(&fence->f_cv);
957
958 /* Remove and call the callbacks. */
959 TAILQ_FOREACH_SAFE(fcb, &fence->f_callbacks, fcb_entry, next) {
960 TAILQ_REMOVE(&fence->f_callbacks, fcb, fcb_entry);
961 fcb->fcb_onqueue = false;
962 (*fcb->func)(fence, fcb);
963 }
964
965 spin_unlock(fence->lock);
966 }
967