i915_sw_fence.c revision 1.1 1 /* $NetBSD: i915_sw_fence.c,v 1.1 2021/12/18 20:15:26 riastradh Exp $ */
2
3 /*
4 * SPDX-License-Identifier: MIT
5 *
6 * (C) Copyright 2016 Intel Corporation
7 */
8
9 #include <sys/cdefs.h>
10 __KERNEL_RCSID(0, "$NetBSD: i915_sw_fence.c,v 1.1 2021/12/18 20:15:26 riastradh Exp $");
11
12 #include <linux/slab.h>
13 #include <linux/dma-fence.h>
14 #include <linux/irq_work.h>
15 #include <linux/dma-resv.h>
16
17 #include "i915_sw_fence.h"
18 #include "i915_selftest.h"
19
20 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
21 #define I915_SW_FENCE_BUG_ON(expr) BUG_ON(expr)
22 #else
23 #define I915_SW_FENCE_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr)
24 #endif
25
26 #define I915_SW_FENCE_FLAG_ALLOC BIT(3) /* after WQ_FLAG_* for safety */
27
28 static DEFINE_SPINLOCK(i915_sw_fence_lock);
29
30 enum {
31 DEBUG_FENCE_IDLE = 0,
32 DEBUG_FENCE_NOTIFY,
33 };
34
35 static void *i915_sw_fence_debug_hint(void *addr)
36 {
37 return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK);
38 }
39
40 #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
41
42 static struct debug_obj_descr i915_sw_fence_debug_descr = {
43 .name = "i915_sw_fence",
44 .debug_hint = i915_sw_fence_debug_hint,
45 };
46
47 static inline void debug_fence_init(struct i915_sw_fence *fence)
48 {
49 debug_object_init(fence, &i915_sw_fence_debug_descr);
50 }
51
52 static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
53 {
54 debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr);
55 }
56
57 static inline void debug_fence_activate(struct i915_sw_fence *fence)
58 {
59 debug_object_activate(fence, &i915_sw_fence_debug_descr);
60 }
61
62 static inline void debug_fence_set_state(struct i915_sw_fence *fence,
63 int old, int new)
64 {
65 debug_object_active_state(fence, &i915_sw_fence_debug_descr, old, new);
66 }
67
68 static inline void debug_fence_deactivate(struct i915_sw_fence *fence)
69 {
70 debug_object_deactivate(fence, &i915_sw_fence_debug_descr);
71 }
72
73 static inline void debug_fence_destroy(struct i915_sw_fence *fence)
74 {
75 debug_object_destroy(fence, &i915_sw_fence_debug_descr);
76 }
77
78 static inline void debug_fence_free(struct i915_sw_fence *fence)
79 {
80 debug_object_free(fence, &i915_sw_fence_debug_descr);
81 smp_wmb(); /* flush the change in state before reallocation */
82 }
83
84 static inline void debug_fence_assert(struct i915_sw_fence *fence)
85 {
86 debug_object_assert_init(fence, &i915_sw_fence_debug_descr);
87 }
88
89 #else
90
91 static inline void debug_fence_init(struct i915_sw_fence *fence)
92 {
93 }
94
95 static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
96 {
97 }
98
99 static inline void debug_fence_activate(struct i915_sw_fence *fence)
100 {
101 }
102
103 static inline void debug_fence_set_state(struct i915_sw_fence *fence,
104 int old, int new)
105 {
106 }
107
108 static inline void debug_fence_deactivate(struct i915_sw_fence *fence)
109 {
110 }
111
112 static inline void debug_fence_destroy(struct i915_sw_fence *fence)
113 {
114 }
115
116 static inline void debug_fence_free(struct i915_sw_fence *fence)
117 {
118 }
119
120 static inline void debug_fence_assert(struct i915_sw_fence *fence)
121 {
122 }
123
124 #endif
125
126 static int __i915_sw_fence_notify(struct i915_sw_fence *fence,
127 enum i915_sw_fence_notify state)
128 {
129 i915_sw_fence_notify_t fn;
130
131 fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK);
132 return fn(fence, state);
133 }
134
135 #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
136 void i915_sw_fence_fini(struct i915_sw_fence *fence)
137 {
138 debug_fence_free(fence);
139 }
140 #endif
141
142 static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
143 struct list_head *continuation)
144 {
145 wait_queue_head_t *x = &fence->wait;
146 wait_queue_entry_t *pos, *next;
147 unsigned long flags;
148
149 debug_fence_deactivate(fence);
150 atomic_set_release(&fence->pending, -1); /* 0 -> -1 [done] */
151
152 /*
153 * To prevent unbounded recursion as we traverse the graph of
154 * i915_sw_fences, we move the entry list from this, the next ready
155 * fence, to the tail of the original fence's entry list
156 * (and so added to the list to be woken).
157 */
158
159 spin_lock_irqsave_nested(&x->lock, flags, 1 + !!continuation);
160 if (continuation) {
161 list_for_each_entry_safe(pos, next, &x->head, entry) {
162 if (pos->func == autoremove_wake_function)
163 pos->func(pos, TASK_NORMAL, 0, continuation);
164 else
165 list_move_tail(&pos->entry, continuation);
166 }
167 } else {
168 LIST_HEAD(extra);
169
170 do {
171 list_for_each_entry_safe(pos, next, &x->head, entry) {
172 pos->func(pos,
173 TASK_NORMAL, fence->error,
174 &extra);
175 }
176
177 if (list_empty(&extra))
178 break;
179
180 list_splice_tail_init(&extra, &x->head);
181 } while (1);
182 }
183 spin_unlock_irqrestore(&x->lock, flags);
184
185 debug_fence_assert(fence);
186 }
187
188 static void __i915_sw_fence_complete(struct i915_sw_fence *fence,
189 struct list_head *continuation)
190 {
191 debug_fence_assert(fence);
192
193 if (!atomic_dec_and_test(&fence->pending))
194 return;
195
196 debug_fence_set_state(fence, DEBUG_FENCE_IDLE, DEBUG_FENCE_NOTIFY);
197
198 if (__i915_sw_fence_notify(fence, FENCE_COMPLETE) != NOTIFY_DONE)
199 return;
200
201 debug_fence_set_state(fence, DEBUG_FENCE_NOTIFY, DEBUG_FENCE_IDLE);
202
203 __i915_sw_fence_wake_up_all(fence, continuation);
204
205 debug_fence_destroy(fence);
206 __i915_sw_fence_notify(fence, FENCE_FREE);
207 }
208
209 void i915_sw_fence_complete(struct i915_sw_fence *fence)
210 {
211 debug_fence_assert(fence);
212
213 if (WARN_ON(i915_sw_fence_done(fence)))
214 return;
215
216 __i915_sw_fence_complete(fence, NULL);
217 }
218
219 void i915_sw_fence_await(struct i915_sw_fence *fence)
220 {
221 debug_fence_assert(fence);
222 WARN_ON(atomic_inc_return(&fence->pending) <= 1);
223 }
224
225 void __i915_sw_fence_init(struct i915_sw_fence *fence,
226 i915_sw_fence_notify_t fn,
227 const char *name,
228 struct lock_class_key *key)
229 {
230 BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK);
231
232 __init_waitqueue_head(&fence->wait, name, key);
233 fence->flags = (unsigned long)fn;
234
235 i915_sw_fence_reinit(fence);
236 }
237
238 void i915_sw_fence_reinit(struct i915_sw_fence *fence)
239 {
240 debug_fence_init(fence);
241
242 atomic_set(&fence->pending, 1);
243 fence->error = 0;
244
245 I915_SW_FENCE_BUG_ON(!fence->flags);
246 I915_SW_FENCE_BUG_ON(!list_empty(&fence->wait.head));
247 }
248
249 void i915_sw_fence_commit(struct i915_sw_fence *fence)
250 {
251 debug_fence_activate(fence);
252 i915_sw_fence_complete(fence);
253 }
254
255 static int i915_sw_fence_wake(wait_queue_entry_t *wq, unsigned mode, int flags, void *key)
256 {
257 i915_sw_fence_set_error_once(wq->private, flags);
258
259 list_del(&wq->entry);
260 __i915_sw_fence_complete(wq->private, key);
261
262 if (wq->flags & I915_SW_FENCE_FLAG_ALLOC)
263 kfree(wq);
264 return 0;
265 }
266
267 static bool __i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
268 const struct i915_sw_fence * const signaler)
269 {
270 wait_queue_entry_t *wq;
271
272 if (__test_and_set_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags))
273 return false;
274
275 if (fence == signaler)
276 return true;
277
278 list_for_each_entry(wq, &fence->wait.head, entry) {
279 if (wq->func != i915_sw_fence_wake)
280 continue;
281
282 if (__i915_sw_fence_check_if_after(wq->private, signaler))
283 return true;
284 }
285
286 return false;
287 }
288
289 static void __i915_sw_fence_clear_checked_bit(struct i915_sw_fence *fence)
290 {
291 wait_queue_entry_t *wq;
292
293 if (!__test_and_clear_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags))
294 return;
295
296 list_for_each_entry(wq, &fence->wait.head, entry) {
297 if (wq->func != i915_sw_fence_wake)
298 continue;
299
300 __i915_sw_fence_clear_checked_bit(wq->private);
301 }
302 }
303
304 static bool i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
305 const struct i915_sw_fence * const signaler)
306 {
307 unsigned long flags;
308 bool err;
309
310 if (!IS_ENABLED(CONFIG_DRM_I915_SW_FENCE_CHECK_DAG))
311 return false;
312
313 spin_lock_irqsave(&i915_sw_fence_lock, flags);
314 err = __i915_sw_fence_check_if_after(fence, signaler);
315 __i915_sw_fence_clear_checked_bit(fence);
316 spin_unlock_irqrestore(&i915_sw_fence_lock, flags);
317
318 return err;
319 }
320
321 static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
322 struct i915_sw_fence *signaler,
323 wait_queue_entry_t *wq, gfp_t gfp)
324 {
325 unsigned long flags;
326 int pending;
327
328 debug_fence_assert(fence);
329 might_sleep_if(gfpflags_allow_blocking(gfp));
330
331 if (i915_sw_fence_done(signaler)) {
332 i915_sw_fence_set_error_once(fence, signaler->error);
333 return 0;
334 }
335
336 debug_fence_assert(signaler);
337
338 /* The dependency graph must be acyclic. */
339 if (unlikely(i915_sw_fence_check_if_after(fence, signaler)))
340 return -EINVAL;
341
342 pending = 0;
343 if (!wq) {
344 wq = kmalloc(sizeof(*wq), gfp);
345 if (!wq) {
346 if (!gfpflags_allow_blocking(gfp))
347 return -ENOMEM;
348
349 i915_sw_fence_wait(signaler);
350 i915_sw_fence_set_error_once(fence, signaler->error);
351 return 0;
352 }
353
354 pending |= I915_SW_FENCE_FLAG_ALLOC;
355 }
356
357 INIT_LIST_HEAD(&wq->entry);
358 wq->flags = pending;
359 wq->func = i915_sw_fence_wake;
360 wq->private = fence;
361
362 i915_sw_fence_await(fence);
363
364 spin_lock_irqsave(&signaler->wait.lock, flags);
365 if (likely(!i915_sw_fence_done(signaler))) {
366 __add_wait_queue_entry_tail(&signaler->wait, wq);
367 pending = 1;
368 } else {
369 i915_sw_fence_wake(wq, 0, signaler->error, NULL);
370 pending = 0;
371 }
372 spin_unlock_irqrestore(&signaler->wait.lock, flags);
373
374 return pending;
375 }
376
377 int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
378 struct i915_sw_fence *signaler,
379 wait_queue_entry_t *wq)
380 {
381 return __i915_sw_fence_await_sw_fence(fence, signaler, wq, 0);
382 }
383
384 int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
385 struct i915_sw_fence *signaler,
386 gfp_t gfp)
387 {
388 return __i915_sw_fence_await_sw_fence(fence, signaler, NULL, gfp);
389 }
390
391 struct i915_sw_dma_fence_cb_timer {
392 struct i915_sw_dma_fence_cb base;
393 struct dma_fence *dma;
394 struct timer_list timer;
395 struct irq_work work;
396 struct rcu_head rcu;
397 };
398
399 static void dma_i915_sw_fence_wake(struct dma_fence *dma,
400 struct dma_fence_cb *data)
401 {
402 struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
403
404 i915_sw_fence_set_error_once(cb->fence, dma->error);
405 i915_sw_fence_complete(cb->fence);
406 kfree(cb);
407 }
408
409 static void timer_i915_sw_fence_wake(struct timer_list *t)
410 {
411 struct i915_sw_dma_fence_cb_timer *cb = from_timer(cb, t, timer);
412 struct i915_sw_fence *fence;
413
414 fence = xchg(&cb->base.fence, NULL);
415 if (!fence)
416 return;
417
418 pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%pS)\n",
419 cb->dma->ops->get_driver_name(cb->dma),
420 cb->dma->ops->get_timeline_name(cb->dma),
421 cb->dma->seqno,
422 i915_sw_fence_debug_hint(fence));
423
424 i915_sw_fence_set_error_once(fence, -ETIMEDOUT);
425 i915_sw_fence_complete(fence);
426 }
427
428 static void dma_i915_sw_fence_wake_timer(struct dma_fence *dma,
429 struct dma_fence_cb *data)
430 {
431 struct i915_sw_dma_fence_cb_timer *cb =
432 container_of(data, typeof(*cb), base.base);
433 struct i915_sw_fence *fence;
434
435 fence = xchg(&cb->base.fence, NULL);
436 if (fence) {
437 i915_sw_fence_set_error_once(fence, dma->error);
438 i915_sw_fence_complete(fence);
439 }
440
441 irq_work_queue(&cb->work);
442 }
443
444 static void irq_i915_sw_fence_work(struct irq_work *wrk)
445 {
446 struct i915_sw_dma_fence_cb_timer *cb =
447 container_of(wrk, typeof(*cb), work);
448
449 del_timer_sync(&cb->timer);
450 dma_fence_put(cb->dma);
451
452 kfree_rcu(cb, rcu);
453 }
454
455 int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
456 struct dma_fence *dma,
457 unsigned long timeout,
458 gfp_t gfp)
459 {
460 struct i915_sw_dma_fence_cb *cb;
461 dma_fence_func_t func;
462 int ret;
463
464 debug_fence_assert(fence);
465 might_sleep_if(gfpflags_allow_blocking(gfp));
466
467 if (dma_fence_is_signaled(dma)) {
468 i915_sw_fence_set_error_once(fence, dma->error);
469 return 0;
470 }
471
472 cb = kmalloc(timeout ?
473 sizeof(struct i915_sw_dma_fence_cb_timer) :
474 sizeof(struct i915_sw_dma_fence_cb),
475 gfp);
476 if (!cb) {
477 if (!gfpflags_allow_blocking(gfp))
478 return -ENOMEM;
479
480 ret = dma_fence_wait(dma, false);
481 if (ret)
482 return ret;
483
484 i915_sw_fence_set_error_once(fence, dma->error);
485 return 0;
486 }
487
488 cb->fence = fence;
489 i915_sw_fence_await(fence);
490
491 func = dma_i915_sw_fence_wake;
492 if (timeout) {
493 struct i915_sw_dma_fence_cb_timer *timer =
494 container_of(cb, typeof(*timer), base);
495
496 timer->dma = dma_fence_get(dma);
497 init_irq_work(&timer->work, irq_i915_sw_fence_work);
498
499 timer_setup(&timer->timer,
500 timer_i915_sw_fence_wake, TIMER_IRQSAFE);
501 mod_timer(&timer->timer, round_jiffies_up(jiffies + timeout));
502
503 func = dma_i915_sw_fence_wake_timer;
504 }
505
506 ret = dma_fence_add_callback(dma, &cb->base, func);
507 if (ret == 0) {
508 ret = 1;
509 } else {
510 func(dma, &cb->base);
511 if (ret == -ENOENT) /* fence already signaled */
512 ret = 0;
513 }
514
515 return ret;
516 }
517
518 static void __dma_i915_sw_fence_wake(struct dma_fence *dma,
519 struct dma_fence_cb *data)
520 {
521 struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
522
523 i915_sw_fence_set_error_once(cb->fence, dma->error);
524 i915_sw_fence_complete(cb->fence);
525 }
526
527 int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
528 struct dma_fence *dma,
529 struct i915_sw_dma_fence_cb *cb)
530 {
531 int ret;
532
533 debug_fence_assert(fence);
534
535 if (dma_fence_is_signaled(dma)) {
536 i915_sw_fence_set_error_once(fence, dma->error);
537 return 0;
538 }
539
540 cb->fence = fence;
541 i915_sw_fence_await(fence);
542
543 ret = dma_fence_add_callback(dma, &cb->base, __dma_i915_sw_fence_wake);
544 if (ret == 0) {
545 ret = 1;
546 } else {
547 __dma_i915_sw_fence_wake(dma, &cb->base);
548 if (ret == -ENOENT) /* fence already signaled */
549 ret = 0;
550 }
551
552 return ret;
553 }
554
555 int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
556 struct dma_resv *resv,
557 const struct dma_fence_ops *exclude,
558 bool write,
559 unsigned long timeout,
560 gfp_t gfp)
561 {
562 struct dma_fence *excl;
563 int ret = 0, pending;
564
565 debug_fence_assert(fence);
566 might_sleep_if(gfpflags_allow_blocking(gfp));
567
568 if (write) {
569 struct dma_fence **shared;
570 unsigned int count, i;
571
572 ret = dma_resv_get_fences_rcu(resv, &excl, &count, &shared);
573 if (ret)
574 return ret;
575
576 for (i = 0; i < count; i++) {
577 if (shared[i]->ops == exclude)
578 continue;
579
580 pending = i915_sw_fence_await_dma_fence(fence,
581 shared[i],
582 timeout,
583 gfp);
584 if (pending < 0) {
585 ret = pending;
586 break;
587 }
588
589 ret |= pending;
590 }
591
592 for (i = 0; i < count; i++)
593 dma_fence_put(shared[i]);
594 kfree(shared);
595 } else {
596 excl = dma_resv_get_excl_rcu(resv);
597 }
598
599 if (ret >= 0 && excl && excl->ops != exclude) {
600 pending = i915_sw_fence_await_dma_fence(fence,
601 excl,
602 timeout,
603 gfp);
604 if (pending < 0)
605 ret = pending;
606 else
607 ret |= pending;
608 }
609
610 dma_fence_put(excl);
611
612 return ret;
613 }
614
615 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
616 #include "selftests/lib_sw_fence.c"
617 #include "selftests/i915_sw_fence.c"
618 #endif
619