xref: /openbsd/sys/dev/pci/drm/amd/amdgpu/amdgpu_sync.c (revision 8e8da360)
11bb76ff1Sjsg // SPDX-License-Identifier: MIT
2fb4d8502Sjsg /*
3fb4d8502Sjsg  * Copyright 2014 Advanced Micro Devices, Inc.
4fb4d8502Sjsg  * All Rights Reserved.
5fb4d8502Sjsg  *
6fb4d8502Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
7fb4d8502Sjsg  * copy of this software and associated documentation files (the
8fb4d8502Sjsg  * "Software"), to deal in the Software without restriction, including
9fb4d8502Sjsg  * without limitation the rights to use, copy, modify, merge, publish,
10fb4d8502Sjsg  * distribute, sub license, and/or sell copies of the Software, and to
11fb4d8502Sjsg  * permit persons to whom the Software is furnished to do so, subject to
12fb4d8502Sjsg  * the following conditions:
13fb4d8502Sjsg  *
14fb4d8502Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fb4d8502Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fb4d8502Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17fb4d8502Sjsg  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18fb4d8502Sjsg  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19fb4d8502Sjsg  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20fb4d8502Sjsg  * USE OR OTHER DEALINGS IN THE SOFTWARE.
21fb4d8502Sjsg  *
22fb4d8502Sjsg  * The above copyright notice and this permission notice (including the
23fb4d8502Sjsg  * next paragraph) shall be included in all copies or substantial portions
24fb4d8502Sjsg  * of the Software.
25fb4d8502Sjsg  *
26fb4d8502Sjsg  */
27fb4d8502Sjsg /*
28fb4d8502Sjsg  * Authors:
29fb4d8502Sjsg  *    Christian König <christian.koenig@amd.com>
30fb4d8502Sjsg  */
31fb4d8502Sjsg 
325ca02815Sjsg #include <linux/dma-fence-chain.h>
335ca02815Sjsg 
34fb4d8502Sjsg #include "amdgpu.h"
35fb4d8502Sjsg #include "amdgpu_trace.h"
36fb4d8502Sjsg #include "amdgpu_amdkfd.h"
37fb4d8502Sjsg 
38fb4d8502Sjsg struct amdgpu_sync_entry {
39fb4d8502Sjsg 	struct hlist_node	node;
40fb4d8502Sjsg 	struct dma_fence	*fence;
41fb4d8502Sjsg };
42fb4d8502Sjsg 
43fb4d8502Sjsg static struct pool amdgpu_sync_slab;
44fb4d8502Sjsg 
45fb4d8502Sjsg /**
46fb4d8502Sjsg  * amdgpu_sync_create - zero init sync object
47fb4d8502Sjsg  *
48fb4d8502Sjsg  * @sync: sync object to initialize
49fb4d8502Sjsg  *
50fb4d8502Sjsg  * Just clear the sync object for now.
51fb4d8502Sjsg  */
amdgpu_sync_create(struct amdgpu_sync * sync)52fb4d8502Sjsg void amdgpu_sync_create(struct amdgpu_sync *sync)
53fb4d8502Sjsg {
54fb4d8502Sjsg 	hash_init(sync->fences);
55fb4d8502Sjsg }
56fb4d8502Sjsg 
57fb4d8502Sjsg /**
58fb4d8502Sjsg  * amdgpu_sync_same_dev - test if fence belong to us
59fb4d8502Sjsg  *
60fb4d8502Sjsg  * @adev: amdgpu device to use for the test
61fb4d8502Sjsg  * @f: fence to test
62fb4d8502Sjsg  *
63fb4d8502Sjsg  * Test if the fence was issued by us.
64fb4d8502Sjsg  */
amdgpu_sync_same_dev(struct amdgpu_device * adev,struct dma_fence * f)65fb4d8502Sjsg static bool amdgpu_sync_same_dev(struct amdgpu_device *adev,
66fb4d8502Sjsg 				 struct dma_fence *f)
67fb4d8502Sjsg {
68fb4d8502Sjsg 	struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
69fb4d8502Sjsg 
70fb4d8502Sjsg 	if (s_fence) {
71fb4d8502Sjsg 		struct amdgpu_ring *ring;
72fb4d8502Sjsg 
73fb4d8502Sjsg 		ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
74fb4d8502Sjsg 		return ring->adev == adev;
75fb4d8502Sjsg 	}
76fb4d8502Sjsg 
77fb4d8502Sjsg 	return false;
78fb4d8502Sjsg }
79fb4d8502Sjsg 
80fb4d8502Sjsg /**
81fb4d8502Sjsg  * amdgpu_sync_get_owner - extract the owner of a fence
82fb4d8502Sjsg  *
835ca02815Sjsg  * @f: fence get the owner from
84fb4d8502Sjsg  *
85fb4d8502Sjsg  * Extract who originally created the fence.
86fb4d8502Sjsg  */
amdgpu_sync_get_owner(struct dma_fence * f)87fb4d8502Sjsg static void *amdgpu_sync_get_owner(struct dma_fence *f)
88fb4d8502Sjsg {
89fb4d8502Sjsg 	struct drm_sched_fence *s_fence;
90fb4d8502Sjsg 	struct amdgpu_amdkfd_fence *kfd_fence;
91fb4d8502Sjsg 
92fb4d8502Sjsg 	if (!f)
93fb4d8502Sjsg 		return AMDGPU_FENCE_OWNER_UNDEFINED;
94fb4d8502Sjsg 
95fb4d8502Sjsg 	s_fence = to_drm_sched_fence(f);
96fb4d8502Sjsg 	if (s_fence)
97fb4d8502Sjsg 		return s_fence->owner;
98fb4d8502Sjsg 
99fb4d8502Sjsg 	kfd_fence = to_amdgpu_amdkfd_fence(f);
100fb4d8502Sjsg 	if (kfd_fence)
101fb4d8502Sjsg 		return AMDGPU_FENCE_OWNER_KFD;
102fb4d8502Sjsg 
103fb4d8502Sjsg 	return AMDGPU_FENCE_OWNER_UNDEFINED;
104fb4d8502Sjsg }
105fb4d8502Sjsg 
106fb4d8502Sjsg /**
107fb4d8502Sjsg  * amdgpu_sync_keep_later - Keep the later fence
108fb4d8502Sjsg  *
109fb4d8502Sjsg  * @keep: existing fence to test
110fb4d8502Sjsg  * @fence: new fence
111fb4d8502Sjsg  *
112fb4d8502Sjsg  * Either keep the existing fence or the new one, depending which one is later.
113fb4d8502Sjsg  */
amdgpu_sync_keep_later(struct dma_fence ** keep,struct dma_fence * fence)114fb4d8502Sjsg static void amdgpu_sync_keep_later(struct dma_fence **keep,
115fb4d8502Sjsg 				   struct dma_fence *fence)
116fb4d8502Sjsg {
117fb4d8502Sjsg 	if (*keep && dma_fence_is_later(*keep, fence))
118fb4d8502Sjsg 		return;
119fb4d8502Sjsg 
120fb4d8502Sjsg 	dma_fence_put(*keep);
121fb4d8502Sjsg 	*keep = dma_fence_get(fence);
122fb4d8502Sjsg }
123fb4d8502Sjsg 
124fb4d8502Sjsg /**
125fb4d8502Sjsg  * amdgpu_sync_add_later - add the fence to the hash
126fb4d8502Sjsg  *
127fb4d8502Sjsg  * @sync: sync object to add the fence to
128fb4d8502Sjsg  * @f: fence to add
129fb4d8502Sjsg  *
130fb4d8502Sjsg  * Tries to add the fence to an existing hash entry. Returns true when an entry
131fb4d8502Sjsg  * was found, false otherwise.
132fb4d8502Sjsg  */
amdgpu_sync_add_later(struct amdgpu_sync * sync,struct dma_fence * f)133ad8b1aafSjsg static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f)
134fb4d8502Sjsg {
135fb4d8502Sjsg 	struct amdgpu_sync_entry *e;
136fb4d8502Sjsg 
137fb4d8502Sjsg 	hash_for_each_possible(sync->fences, e, node, f->context) {
138fb4d8502Sjsg 		if (unlikely(e->fence->context != f->context))
139fb4d8502Sjsg 			continue;
140fb4d8502Sjsg 
141fb4d8502Sjsg 		amdgpu_sync_keep_later(&e->fence, f);
142fb4d8502Sjsg 		return true;
143fb4d8502Sjsg 	}
144fb4d8502Sjsg 	return false;
145fb4d8502Sjsg }
146fb4d8502Sjsg 
147fb4d8502Sjsg /**
148fb4d8502Sjsg  * amdgpu_sync_fence - remember to sync to this fence
149fb4d8502Sjsg  *
150fb4d8502Sjsg  * @sync: sync object to add fence to
151c349dbc7Sjsg  * @f: fence to sync to
152fb4d8502Sjsg  *
153c349dbc7Sjsg  * Add the fence to the sync object.
154fb4d8502Sjsg  */
amdgpu_sync_fence(struct amdgpu_sync * sync,struct dma_fence * f)155ad8b1aafSjsg int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f)
156fb4d8502Sjsg {
157fb4d8502Sjsg 	struct amdgpu_sync_entry *e;
158fb4d8502Sjsg 
159fb4d8502Sjsg 	if (!f)
160fb4d8502Sjsg 		return 0;
161fb4d8502Sjsg 
162ad8b1aafSjsg 	if (amdgpu_sync_add_later(sync, f))
163fb4d8502Sjsg 		return 0;
164fb4d8502Sjsg 
165fb4d8502Sjsg #ifdef __linux__
166fb4d8502Sjsg 	e = kmem_cache_alloc(amdgpu_sync_slab, GFP_KERNEL);
167fb4d8502Sjsg #else
168fb4d8502Sjsg 	e = pool_get(&amdgpu_sync_slab, PR_WAITOK);
169fb4d8502Sjsg #endif
170fb4d8502Sjsg 	if (!e)
171fb4d8502Sjsg 		return -ENOMEM;
172fb4d8502Sjsg 
173fb4d8502Sjsg 	hash_add(sync->fences, &e->node, f->context);
174fb4d8502Sjsg 	e->fence = dma_fence_get(f);
175fb4d8502Sjsg 	return 0;
176fb4d8502Sjsg }
177fb4d8502Sjsg 
1785ca02815Sjsg /* Determine based on the owner and mode if we should sync to a fence or not */
amdgpu_sync_test_fence(struct amdgpu_device * adev,enum amdgpu_sync_mode mode,void * owner,struct dma_fence * f)1795ca02815Sjsg static bool amdgpu_sync_test_fence(struct amdgpu_device *adev,
1805ca02815Sjsg 				   enum amdgpu_sync_mode mode,
1815ca02815Sjsg 				   void *owner, struct dma_fence *f)
1825ca02815Sjsg {
1835ca02815Sjsg 	void *fence_owner = amdgpu_sync_get_owner(f);
1845ca02815Sjsg 
1855ca02815Sjsg 	/* Always sync to moves, no matter what */
1865ca02815Sjsg 	if (fence_owner == AMDGPU_FENCE_OWNER_UNDEFINED)
1875ca02815Sjsg 		return true;
1885ca02815Sjsg 
1895ca02815Sjsg 	/* We only want to trigger KFD eviction fences on
1905ca02815Sjsg 	 * evict or move jobs. Skip KFD fences otherwise.
1915ca02815Sjsg 	 */
1925ca02815Sjsg 	if (fence_owner == AMDGPU_FENCE_OWNER_KFD &&
1935ca02815Sjsg 	    owner != AMDGPU_FENCE_OWNER_UNDEFINED)
1945ca02815Sjsg 		return false;
1955ca02815Sjsg 
1965ca02815Sjsg 	/* Never sync to VM updates either. */
1975ca02815Sjsg 	if (fence_owner == AMDGPU_FENCE_OWNER_VM &&
198*8e8da360Sjsg 	    owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
199*8e8da360Sjsg 	    owner != AMDGPU_FENCE_OWNER_KFD)
2005ca02815Sjsg 		return false;
2015ca02815Sjsg 
2025ca02815Sjsg 	/* Ignore fences depending on the sync mode */
2035ca02815Sjsg 	switch (mode) {
2045ca02815Sjsg 	case AMDGPU_SYNC_ALWAYS:
2055ca02815Sjsg 		return true;
2065ca02815Sjsg 
2075ca02815Sjsg 	case AMDGPU_SYNC_NE_OWNER:
2085ca02815Sjsg 		if (amdgpu_sync_same_dev(adev, f) &&
2095ca02815Sjsg 		    fence_owner == owner)
2105ca02815Sjsg 			return false;
2115ca02815Sjsg 		break;
2125ca02815Sjsg 
2135ca02815Sjsg 	case AMDGPU_SYNC_EQ_OWNER:
2145ca02815Sjsg 		if (amdgpu_sync_same_dev(adev, f) &&
2155ca02815Sjsg 		    fence_owner != owner)
2165ca02815Sjsg 			return false;
2175ca02815Sjsg 		break;
2185ca02815Sjsg 
2195ca02815Sjsg 	case AMDGPU_SYNC_EXPLICIT:
2205ca02815Sjsg 		return false;
2215ca02815Sjsg 	}
2225ca02815Sjsg 
2235ca02815Sjsg 	WARN(debug_evictions && fence_owner == AMDGPU_FENCE_OWNER_KFD,
2245ca02815Sjsg 	     "Adding eviction fence to sync obj");
2255ca02815Sjsg 	return true;
2265ca02815Sjsg }
2275ca02815Sjsg 
228c349dbc7Sjsg /**
229fb4d8502Sjsg  * amdgpu_sync_resv - sync to a reservation object
230fb4d8502Sjsg  *
2315ca02815Sjsg  * @adev: amdgpu device
232fb4d8502Sjsg  * @sync: sync object to add fences from reservation object to
233fb4d8502Sjsg  * @resv: reservation object with embedded fence
234c349dbc7Sjsg  * @mode: how owner affects which fences we sync to
235c349dbc7Sjsg  * @owner: owner of the planned job submission
236fb4d8502Sjsg  *
237fb4d8502Sjsg  * Sync to the fence
238fb4d8502Sjsg  */
amdgpu_sync_resv(struct amdgpu_device * adev,struct amdgpu_sync * sync,struct dma_resv * resv,enum amdgpu_sync_mode mode,void * owner)239c349dbc7Sjsg int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
240c349dbc7Sjsg 		     struct dma_resv *resv, enum amdgpu_sync_mode mode,
241c349dbc7Sjsg 		     void *owner)
242fb4d8502Sjsg {
2431bb76ff1Sjsg 	struct dma_resv_iter cursor;
244fb4d8502Sjsg 	struct dma_fence *f;
2451bb76ff1Sjsg 	int r;
246fb4d8502Sjsg 
247fb4d8502Sjsg 	if (resv == NULL)
248fb4d8502Sjsg 		return -EINVAL;
249fb4d8502Sjsg 
2501bb76ff1Sjsg 	/* TODO: Use DMA_RESV_USAGE_READ here */
2511bb76ff1Sjsg 	dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, f) {
2525ca02815Sjsg 		dma_fence_chain_for_each(f, f) {
2531bb76ff1Sjsg 			struct dma_fence *tmp = dma_fence_chain_contained(f);
254fb4d8502Sjsg 
2551bb76ff1Sjsg 			if (amdgpu_sync_test_fence(adev, mode, owner, tmp)) {
2565ca02815Sjsg 				r = amdgpu_sync_fence(sync, f);
2575ca02815Sjsg 				dma_fence_put(f);
2585ca02815Sjsg 				if (r)
259fb4d8502Sjsg 					return r;
2605ca02815Sjsg 				break;
2615ca02815Sjsg 			}
2625ca02815Sjsg 		}
2635ca02815Sjsg 	}
2645ca02815Sjsg 	return 0;
2655ca02815Sjsg }
266fb4d8502Sjsg 
267f005ef32Sjsg /* Free the entry back to the slab */
amdgpu_sync_entry_free(struct amdgpu_sync_entry * e)268f005ef32Sjsg static void amdgpu_sync_entry_free(struct amdgpu_sync_entry *e)
269f005ef32Sjsg {
270f005ef32Sjsg 	hash_del(&e->node);
271f005ef32Sjsg 	dma_fence_put(e->fence);
272f005ef32Sjsg #ifdef __linux__
273f005ef32Sjsg 	kmem_cache_free(amdgpu_sync_slab, e);
274f005ef32Sjsg #else
275f005ef32Sjsg 	pool_put(&amdgpu_sync_slab, e);
276f005ef32Sjsg #endif
277f005ef32Sjsg }
278f005ef32Sjsg 
279fb4d8502Sjsg /**
280fb4d8502Sjsg  * amdgpu_sync_peek_fence - get the next fence not signaled yet
281fb4d8502Sjsg  *
282fb4d8502Sjsg  * @sync: the sync object
283fb4d8502Sjsg  * @ring: optional ring to use for test
284fb4d8502Sjsg  *
285fb4d8502Sjsg  * Returns the next fence not signaled yet without removing it from the sync
286fb4d8502Sjsg  * object.
287fb4d8502Sjsg  */
amdgpu_sync_peek_fence(struct amdgpu_sync * sync,struct amdgpu_ring * ring)288fb4d8502Sjsg struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
289fb4d8502Sjsg 					 struct amdgpu_ring *ring)
290fb4d8502Sjsg {
291fb4d8502Sjsg 	struct amdgpu_sync_entry *e;
292fb4d8502Sjsg 	struct hlist_node *tmp;
293fb4d8502Sjsg 	int i;
294fb4d8502Sjsg 
295fb4d8502Sjsg 	hash_for_each_safe(sync->fences, i, tmp, e, node) {
296fb4d8502Sjsg 		struct dma_fence *f = e->fence;
297fb4d8502Sjsg 		struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
298fb4d8502Sjsg 
299fb4d8502Sjsg 		if (dma_fence_is_signaled(f)) {
300f005ef32Sjsg 			amdgpu_sync_entry_free(e);
301fb4d8502Sjsg 			continue;
302fb4d8502Sjsg 		}
303fb4d8502Sjsg 		if (ring && s_fence) {
304fb4d8502Sjsg 			/* For fences from the same ring it is sufficient
305fb4d8502Sjsg 			 * when they are scheduled.
306fb4d8502Sjsg 			 */
307fb4d8502Sjsg 			if (s_fence->sched == &ring->sched) {
308fb4d8502Sjsg 				if (dma_fence_is_signaled(&s_fence->scheduled))
309fb4d8502Sjsg 					continue;
310fb4d8502Sjsg 
311fb4d8502Sjsg 				return &s_fence->scheduled;
312fb4d8502Sjsg 			}
313fb4d8502Sjsg 		}
314fb4d8502Sjsg 
315fb4d8502Sjsg 		return f;
316fb4d8502Sjsg 	}
317fb4d8502Sjsg 
318fb4d8502Sjsg 	return NULL;
319fb4d8502Sjsg }
320fb4d8502Sjsg 
321fb4d8502Sjsg /**
322fb4d8502Sjsg  * amdgpu_sync_get_fence - get the next fence from the sync object
323fb4d8502Sjsg  *
324fb4d8502Sjsg  * @sync: sync object to use
325fb4d8502Sjsg  *
326fb4d8502Sjsg  * Get and removes the next fence from the sync object not signaled yet.
327fb4d8502Sjsg  */
amdgpu_sync_get_fence(struct amdgpu_sync * sync)328ad8b1aafSjsg struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
329fb4d8502Sjsg {
330fb4d8502Sjsg 	struct amdgpu_sync_entry *e;
331fb4d8502Sjsg 	struct hlist_node *tmp;
332fb4d8502Sjsg 	struct dma_fence *f;
333fb4d8502Sjsg 	int i;
3341bb76ff1Sjsg 
335fb4d8502Sjsg 	hash_for_each_safe(sync->fences, i, tmp, e, node) {
336fb4d8502Sjsg 
337fb4d8502Sjsg 		f = e->fence;
338fb4d8502Sjsg 
339fb4d8502Sjsg 		hash_del(&e->node);
340fb4d8502Sjsg #ifdef __linux__
341fb4d8502Sjsg 		kmem_cache_free(amdgpu_sync_slab, e);
342fb4d8502Sjsg #else
343fb4d8502Sjsg 		pool_put(&amdgpu_sync_slab, e);
344fb4d8502Sjsg #endif
345fb4d8502Sjsg 
346fb4d8502Sjsg 		if (!dma_fence_is_signaled(f))
347fb4d8502Sjsg 			return f;
348fb4d8502Sjsg 
349fb4d8502Sjsg 		dma_fence_put(f);
350fb4d8502Sjsg 	}
351fb4d8502Sjsg 	return NULL;
352fb4d8502Sjsg }
353fb4d8502Sjsg 
354fb4d8502Sjsg /**
355fb4d8502Sjsg  * amdgpu_sync_clone - clone a sync object
356fb4d8502Sjsg  *
357fb4d8502Sjsg  * @source: sync object to clone
358fb4d8502Sjsg  * @clone: pointer to destination sync object
359fb4d8502Sjsg  *
360fb4d8502Sjsg  * Adds references to all unsignaled fences in @source to @clone. Also
361fb4d8502Sjsg  * removes signaled fences from @source while at it.
362fb4d8502Sjsg  */
amdgpu_sync_clone(struct amdgpu_sync * source,struct amdgpu_sync * clone)363fb4d8502Sjsg int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone)
364fb4d8502Sjsg {
365fb4d8502Sjsg 	struct amdgpu_sync_entry *e;
366fb4d8502Sjsg 	struct hlist_node *tmp;
367fb4d8502Sjsg 	struct dma_fence *f;
368fb4d8502Sjsg 	int i, r;
369fb4d8502Sjsg 
370fb4d8502Sjsg 	hash_for_each_safe(source->fences, i, tmp, e, node) {
371fb4d8502Sjsg 		f = e->fence;
372fb4d8502Sjsg 		if (!dma_fence_is_signaled(f)) {
373ad8b1aafSjsg 			r = amdgpu_sync_fence(clone, f);
374fb4d8502Sjsg 			if (r)
375fb4d8502Sjsg 				return r;
376fb4d8502Sjsg 		} else {
377f005ef32Sjsg 			amdgpu_sync_entry_free(e);
378fb4d8502Sjsg 		}
379fb4d8502Sjsg 	}
380fb4d8502Sjsg 
381fb4d8502Sjsg 	return 0;
382fb4d8502Sjsg }
383fb4d8502Sjsg 
384f005ef32Sjsg /**
385f005ef32Sjsg  * amdgpu_sync_push_to_job - push fences into job
386f005ef32Sjsg  * @sync: sync object to get the fences from
387f005ef32Sjsg  * @job: job to push the fences into
388f005ef32Sjsg  *
389f005ef32Sjsg  * Add all unsignaled fences from sync to job.
390f005ef32Sjsg  */
amdgpu_sync_push_to_job(struct amdgpu_sync * sync,struct amdgpu_job * job)391f005ef32Sjsg int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job)
392f005ef32Sjsg {
393f005ef32Sjsg 	struct amdgpu_sync_entry *e;
394f005ef32Sjsg 	struct hlist_node *tmp;
395f005ef32Sjsg 	struct dma_fence *f;
396f005ef32Sjsg 	int i, r;
397f005ef32Sjsg 
398f005ef32Sjsg 	hash_for_each_safe(sync->fences, i, tmp, e, node) {
399f005ef32Sjsg 		f = e->fence;
400f005ef32Sjsg 		if (dma_fence_is_signaled(f)) {
401f005ef32Sjsg 			amdgpu_sync_entry_free(e);
402f005ef32Sjsg 			continue;
403f005ef32Sjsg 		}
404f005ef32Sjsg 
405f005ef32Sjsg 		dma_fence_get(f);
406f005ef32Sjsg 		r = drm_sched_job_add_dependency(&job->base, f);
407f005ef32Sjsg 		if (r) {
408f005ef32Sjsg 			dma_fence_put(f);
409f005ef32Sjsg 			return r;
410f005ef32Sjsg 		}
411f005ef32Sjsg 	}
412f005ef32Sjsg 	return 0;
413f005ef32Sjsg }
414f005ef32Sjsg 
amdgpu_sync_wait(struct amdgpu_sync * sync,bool intr)415fb4d8502Sjsg int amdgpu_sync_wait(struct amdgpu_sync *sync, bool intr)
416fb4d8502Sjsg {
417fb4d8502Sjsg 	struct amdgpu_sync_entry *e;
418fb4d8502Sjsg 	struct hlist_node *tmp;
419fb4d8502Sjsg 	int i, r;
420fb4d8502Sjsg 
421fb4d8502Sjsg 	hash_for_each_safe(sync->fences, i, tmp, e, node) {
422fb4d8502Sjsg 		r = dma_fence_wait(e->fence, intr);
423fb4d8502Sjsg 		if (r)
424fb4d8502Sjsg 			return r;
425fb4d8502Sjsg 
426f005ef32Sjsg 		amdgpu_sync_entry_free(e);
427fb4d8502Sjsg 	}
428fb4d8502Sjsg 
429fb4d8502Sjsg 	return 0;
430fb4d8502Sjsg }
431fb4d8502Sjsg 
432fb4d8502Sjsg /**
433fb4d8502Sjsg  * amdgpu_sync_free - free the sync object
434fb4d8502Sjsg  *
435fb4d8502Sjsg  * @sync: sync object to use
436fb4d8502Sjsg  *
437fb4d8502Sjsg  * Free the sync object.
438fb4d8502Sjsg  */
amdgpu_sync_free(struct amdgpu_sync * sync)439fb4d8502Sjsg void amdgpu_sync_free(struct amdgpu_sync *sync)
440fb4d8502Sjsg {
441fb4d8502Sjsg 	struct amdgpu_sync_entry *e;
442fb4d8502Sjsg 	struct hlist_node *tmp;
4431bb76ff1Sjsg 	unsigned int i;
444fb4d8502Sjsg 
445f005ef32Sjsg 	hash_for_each_safe(sync->fences, i, tmp, e, node)
446f005ef32Sjsg 		amdgpu_sync_entry_free(e);
447fb4d8502Sjsg }
448fb4d8502Sjsg 
449fb4d8502Sjsg /**
450fb4d8502Sjsg  * amdgpu_sync_init - init sync object subsystem
451fb4d8502Sjsg  *
452fb4d8502Sjsg  * Allocate the slab allocator.
453fb4d8502Sjsg  */
amdgpu_sync_init(void)454fb4d8502Sjsg int amdgpu_sync_init(void)
455fb4d8502Sjsg {
456fb4d8502Sjsg #ifdef __linux__
457fb4d8502Sjsg 	amdgpu_sync_slab = kmem_cache_create(
458fb4d8502Sjsg 		"amdgpu_sync", sizeof(struct amdgpu_sync_entry), 0,
459fb4d8502Sjsg 		SLAB_HWCACHE_ALIGN, NULL);
460fb4d8502Sjsg 	if (!amdgpu_sync_slab)
461fb4d8502Sjsg 		return -ENOMEM;
462fb4d8502Sjsg #else
463fb4d8502Sjsg 	pool_init(&amdgpu_sync_slab, sizeof(struct amdgpu_sync_entry),
4640f557061Sjsg 	    CACHELINESIZE, IPL_TTY, 0, "amdgpu_sync", NULL);
465fb4d8502Sjsg #endif
466fb4d8502Sjsg 
467fb4d8502Sjsg 	return 0;
468fb4d8502Sjsg }
469fb4d8502Sjsg 
470fb4d8502Sjsg /**
471fb4d8502Sjsg  * amdgpu_sync_fini - fini sync object subsystem
472fb4d8502Sjsg  *
473fb4d8502Sjsg  * Free the slab allocator.
474fb4d8502Sjsg  */
amdgpu_sync_fini(void)475fb4d8502Sjsg void amdgpu_sync_fini(void)
476fb4d8502Sjsg {
477fb4d8502Sjsg #ifdef __linux__
478fb4d8502Sjsg 	kmem_cache_destroy(amdgpu_sync_slab);
479fb4d8502Sjsg #else
480fb4d8502Sjsg 	pool_destroy(&amdgpu_sync_slab);
481fb4d8502Sjsg #endif
482fb4d8502Sjsg }
483