1 | /* |
2 | * SPDX-License-Identifier: MIT |
3 | * |
4 | * i915_sw_fence.h - library routines for N:M synchronisation points |
5 | * |
6 | * Copyright (C) 2016 Intel Corporation |
7 | */ |
8 | |
9 | #ifndef _I915_SW_FENCE_H_ |
10 | #define _I915_SW_FENCE_H_ |
11 | |
12 | #include <linux/dma-fence.h> |
13 | #include <linux/gfp.h> |
14 | #include <linux/kref.h> |
15 | #include <linux/notifier.h> /* for NOTIFY_DONE */ |
16 | #include <linux/wait.h> |
17 | |
18 | struct completion; |
19 | struct dma_resv; |
20 | struct i915_sw_fence; |
21 | |
22 | enum i915_sw_fence_notify { |
23 | FENCE_COMPLETE, |
24 | FENCE_FREE |
25 | }; |
26 | |
27 | typedef int (*i915_sw_fence_notify_t)(struct i915_sw_fence *, |
28 | enum i915_sw_fence_notify state); |
29 | |
30 | struct i915_sw_fence { |
31 | wait_queue_head_t wait; |
32 | i915_sw_fence_notify_t fn; |
33 | #ifdef CONFIG_DRM_I915_SW_FENCE_CHECK_DAG |
34 | unsigned long flags; |
35 | #endif |
36 | atomic_t pending; |
37 | int error; |
38 | }; |
39 | |
40 | #define I915_SW_FENCE_CHECKED_BIT 0 /* used internally for DAG checking */ |
41 | |
42 | void __i915_sw_fence_init(struct i915_sw_fence *fence, |
43 | i915_sw_fence_notify_t fn, |
44 | const char *name, |
45 | struct lock_class_key *key); |
46 | #ifdef CONFIG_LOCKDEP |
47 | #define i915_sw_fence_init(fence, fn) \ |
48 | do { \ |
49 | static struct lock_class_key __key; \ |
50 | \ |
51 | BUILD_BUG_ON((fn) == NULL); \ |
52 | __i915_sw_fence_init((fence), (fn), #fence, &__key); \ |
53 | } while (0) |
54 | #else |
55 | #define i915_sw_fence_init(fence, fn) \ |
56 | do { \ |
57 | BUILD_BUG_ON((fn) == NULL); \ |
58 | __i915_sw_fence_init((fence), (fn), NULL, NULL); \ |
59 | } while (0) |
60 | #endif |
61 | |
62 | void i915_sw_fence_reinit(struct i915_sw_fence *fence); |
63 | |
64 | #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS |
65 | void i915_sw_fence_fini(struct i915_sw_fence *fence); |
66 | #else |
67 | static inline void i915_sw_fence_fini(struct i915_sw_fence *fence) {} |
68 | #endif |
69 | |
70 | void i915_sw_fence_commit(struct i915_sw_fence *fence); |
71 | |
72 | int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, |
73 | struct i915_sw_fence *after, |
74 | wait_queue_entry_t *wq); |
75 | int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence, |
76 | struct i915_sw_fence *after, |
77 | gfp_t gfp); |
78 | |
79 | struct i915_sw_dma_fence_cb { |
80 | struct dma_fence_cb base; |
81 | struct i915_sw_fence *fence; |
82 | }; |
83 | |
84 | int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, |
85 | struct dma_fence *dma, |
86 | struct i915_sw_dma_fence_cb *cb); |
87 | int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, |
88 | struct dma_fence *dma, |
89 | unsigned long timeout, |
90 | gfp_t gfp); |
91 | |
92 | int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, |
93 | struct dma_resv *resv, |
94 | bool write, |
95 | unsigned long timeout, |
96 | gfp_t gfp); |
97 | |
98 | bool i915_sw_fence_await(struct i915_sw_fence *fence); |
99 | void i915_sw_fence_complete(struct i915_sw_fence *fence); |
100 | |
101 | static inline bool i915_sw_fence_signaled(const struct i915_sw_fence *fence) |
102 | { |
103 | return atomic_read(v: &fence->pending) <= 0; |
104 | } |
105 | |
106 | static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence) |
107 | { |
108 | return atomic_read(v: &fence->pending) < 0; |
109 | } |
110 | |
111 | static inline void i915_sw_fence_wait(struct i915_sw_fence *fence) |
112 | { |
113 | wait_event(fence->wait, i915_sw_fence_done(fence)); |
114 | } |
115 | |
116 | static inline void |
117 | i915_sw_fence_set_error_once(struct i915_sw_fence *fence, int error) |
118 | { |
119 | if (unlikely(error)) |
120 | cmpxchg(&fence->error, 0, error); |
121 | } |
122 | |
123 | #endif /* _I915_SW_FENCE_H_ */ |
124 | |