1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include <drm/drmP.h>
32#include "amdgpu.h"
33#include "amdgpu_trace.h"
34
35struct amdgpu_sync_entry {
36 struct hlist_node node;
37 struct dma_fence *fence;
38};
39
40static struct kmem_cache *amdgpu_sync_slab;
41
42
43
44
45
46
47
48
49void amdgpu_sync_create(struct amdgpu_sync *sync)
50{
51 hash_init(sync->fences);
52 sync->last_vm_update = NULL;
53}
54
55
56
57
58
59
60
61
62
63static bool amdgpu_sync_same_dev(struct amdgpu_device *adev,
64 struct dma_fence *f)
65{
66 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
67
68 if (s_fence) {
69 struct amdgpu_ring *ring;
70
71 ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
72 return ring->adev == adev;
73 }
74
75 return false;
76}
77
78
79
80
81
82
83
84
85static void *amdgpu_sync_get_owner(struct dma_fence *f)
86{
87 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
88
89 if (s_fence)
90 return s_fence->owner;
91
92 return AMDGPU_FENCE_OWNER_UNDEFINED;
93}
94
95
96
97
98
99
100
101
102
103static void amdgpu_sync_keep_later(struct dma_fence **keep,
104 struct dma_fence *fence)
105{
106 if (*keep && dma_fence_is_later(*keep, fence))
107 return;
108
109 dma_fence_put(*keep);
110 *keep = dma_fence_get(fence);
111}
112
113
114
115
116
117
118
119
120
121
122static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f)
123{
124 struct amdgpu_sync_entry *e;
125
126 hash_for_each_possible(sync->fences, e, node, f->context) {
127 if (unlikely(e->fence->context != f->context))
128 continue;
129
130 amdgpu_sync_keep_later(&e->fence, f);
131 return true;
132 }
133 return false;
134}
135
136
137
138
139
140
141
142
143int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
144 struct dma_fence *f)
145{
146 struct amdgpu_sync_entry *e;
147
148 if (!f)
149 return 0;
150
151 if (amdgpu_sync_same_dev(adev, f) &&
152 amdgpu_sync_get_owner(f) == AMDGPU_FENCE_OWNER_VM)
153 amdgpu_sync_keep_later(&sync->last_vm_update, f);
154
155 if (amdgpu_sync_add_later(sync, f))
156 return 0;
157
158 e = kmem_cache_alloc(amdgpu_sync_slab, GFP_KERNEL);
159 if (!e)
160 return -ENOMEM;
161
162 hash_add(sync->fences, &e->node, f->context);
163 e->fence = dma_fence_get(f);
164 return 0;
165}
166
167
168
169
170
171
172
173
174
175
176int amdgpu_sync_resv(struct amdgpu_device *adev,
177 struct amdgpu_sync *sync,
178 struct reservation_object *resv,
179 void *owner)
180{
181 struct reservation_object_list *flist;
182 struct dma_fence *f;
183 void *fence_owner;
184 unsigned i;
185 int r = 0;
186
187 if (resv == NULL)
188 return -EINVAL;
189
190
191 f = reservation_object_get_excl(resv);
192 r = amdgpu_sync_fence(adev, sync, f);
193
194 flist = reservation_object_get_list(resv);
195 if (!flist || r)
196 return r;
197
198 for (i = 0; i < flist->shared_count; ++i) {
199 f = rcu_dereference_protected(flist->shared[i],
200 reservation_object_held(resv));
201 if (amdgpu_sync_same_dev(adev, f)) {
202
203
204
205 fence_owner = amdgpu_sync_get_owner(f);
206 if ((owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
207 (fence_owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
208 ((owner == AMDGPU_FENCE_OWNER_VM) !=
209 (fence_owner == AMDGPU_FENCE_OWNER_VM)))
210 continue;
211
212
213
214
215 if (owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
216 fence_owner == owner)
217 continue;
218 }
219
220 r = amdgpu_sync_fence(adev, sync, f);
221 if (r)
222 break;
223 }
224 return r;
225}
226
227
228
229
230
231
232
233
234
235
236struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
237 struct amdgpu_ring *ring)
238{
239 struct amdgpu_sync_entry *e;
240 struct hlist_node *tmp;
241 int i;
242
243 hash_for_each_safe(sync->fences, i, tmp, e, node) {
244 struct dma_fence *f = e->fence;
245 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
246
247 if (dma_fence_is_signaled(f)) {
248 hash_del(&e->node);
249 dma_fence_put(f);
250 kmem_cache_free(amdgpu_sync_slab, e);
251 continue;
252 }
253 if (ring && s_fence) {
254
255
256
257 if (s_fence->sched == &ring->sched) {
258 if (dma_fence_is_signaled(&s_fence->scheduled))
259 continue;
260
261 return &s_fence->scheduled;
262 }
263 }
264
265 return f;
266 }
267
268 return NULL;
269}
270
271
272
273
274
275
276
277
278struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
279{
280 struct amdgpu_sync_entry *e;
281 struct hlist_node *tmp;
282 struct dma_fence *f;
283 int i;
284
285 hash_for_each_safe(sync->fences, i, tmp, e, node) {
286
287 f = e->fence;
288
289 hash_del(&e->node);
290 kmem_cache_free(amdgpu_sync_slab, e);
291
292 if (!dma_fence_is_signaled(f))
293 return f;
294
295 dma_fence_put(f);
296 }
297 return NULL;
298}
299
300int amdgpu_sync_wait(struct amdgpu_sync *sync, bool intr)
301{
302 struct amdgpu_sync_entry *e;
303 struct hlist_node *tmp;
304 int i, r;
305
306 hash_for_each_safe(sync->fences, i, tmp, e, node) {
307 r = dma_fence_wait(e->fence, intr);
308 if (r)
309 return r;
310
311 hash_del(&e->node);
312 dma_fence_put(e->fence);
313 kmem_cache_free(amdgpu_sync_slab, e);
314 }
315
316 return 0;
317}
318
319
320
321
322
323
324
325
326void amdgpu_sync_free(struct amdgpu_sync *sync)
327{
328 struct amdgpu_sync_entry *e;
329 struct hlist_node *tmp;
330 unsigned i;
331
332 hash_for_each_safe(sync->fences, i, tmp, e, node) {
333 hash_del(&e->node);
334 dma_fence_put(e->fence);
335 kmem_cache_free(amdgpu_sync_slab, e);
336 }
337
338 dma_fence_put(sync->last_vm_update);
339}
340
341
342
343
344
345
346int amdgpu_sync_init(void)
347{
348 amdgpu_sync_slab = kmem_cache_create(
349 "amdgpu_sync", sizeof(struct amdgpu_sync_entry), 0,
350 SLAB_HWCACHE_ALIGN, NULL);
351 if (!amdgpu_sync_slab)
352 return -ENOMEM;
353
354 return 0;
355}
356
357
358
359
360
361
362void amdgpu_sync_fini(void)
363{
364 kmem_cache_destroy(amdgpu_sync_slab);
365}
366