1826f03b8SJingyu Wang // SPDX-License-Identifier: MIT
2d38ceaf9SAlex Deucher /*
3d38ceaf9SAlex Deucher * Copyright 2014 Advanced Micro Devices, Inc.
4d38ceaf9SAlex Deucher * All Rights Reserved.
5d38ceaf9SAlex Deucher *
6d38ceaf9SAlex Deucher * Permission is hereby granted, free of charge, to any person obtaining a
7d38ceaf9SAlex Deucher * copy of this software and associated documentation files (the
8d38ceaf9SAlex Deucher * "Software"), to deal in the Software without restriction, including
9d38ceaf9SAlex Deucher * without limitation the rights to use, copy, modify, merge, publish,
10d38ceaf9SAlex Deucher * distribute, sub license, and/or sell copies of the Software, and to
11d38ceaf9SAlex Deucher * permit persons to whom the Software is furnished to do so, subject to
12d38ceaf9SAlex Deucher * the following conditions:
13d38ceaf9SAlex Deucher *
14d38ceaf9SAlex Deucher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d38ceaf9SAlex Deucher * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d38ceaf9SAlex Deucher * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17d38ceaf9SAlex Deucher * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18d38ceaf9SAlex Deucher * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19d38ceaf9SAlex Deucher * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20d38ceaf9SAlex Deucher * USE OR OTHER DEALINGS IN THE SOFTWARE.
21d38ceaf9SAlex Deucher *
22d38ceaf9SAlex Deucher * The above copyright notice and this permission notice (including the
23d38ceaf9SAlex Deucher * next paragraph) shall be included in all copies or substantial portions
24d38ceaf9SAlex Deucher * of the Software.
25d38ceaf9SAlex Deucher *
26d38ceaf9SAlex Deucher */
27d38ceaf9SAlex Deucher /*
28d38ceaf9SAlex Deucher * Authors:
29d38ceaf9SAlex Deucher * Christian König <[email protected]>
30d38ceaf9SAlex Deucher */
31d38ceaf9SAlex Deucher
3222f0463aSChristian König #include <linux/dma-fence-chain.h>
3322f0463aSChristian König
34d38ceaf9SAlex Deucher #include "amdgpu.h"
35d38ceaf9SAlex Deucher #include "amdgpu_trace.h"
36d8d019ccSFelix Kuehling #include "amdgpu_amdkfd.h"
37d38ceaf9SAlex Deucher
38f91b3a69SChristian König struct amdgpu_sync_entry {
39f91b3a69SChristian König struct hlist_node node;
40f54d1867SChris Wilson struct dma_fence *fence;
41f91b3a69SChristian König };
42f91b3a69SChristian König
43257bf15aSChristian König static struct kmem_cache *amdgpu_sync_slab;
44257bf15aSChristian König
45d38ceaf9SAlex Deucher /**
46d38ceaf9SAlex Deucher * amdgpu_sync_create - zero init sync object
47d38ceaf9SAlex Deucher *
48d38ceaf9SAlex Deucher * @sync: sync object to initialize
49d38ceaf9SAlex Deucher *
50d38ceaf9SAlex Deucher * Just clear the sync object for now.
51d38ceaf9SAlex Deucher */
amdgpu_sync_create(struct amdgpu_sync * sync)52d38ceaf9SAlex Deucher void amdgpu_sync_create(struct amdgpu_sync *sync)
53d38ceaf9SAlex Deucher {
54f91b3a69SChristian König hash_init(sync->fences);
55d38ceaf9SAlex Deucher }
56d38ceaf9SAlex Deucher
57bcc634f4SChristian König /**
58bcc634f4SChristian König * amdgpu_sync_same_dev - test if fence belong to us
59bcc634f4SChristian König *
60bcc634f4SChristian König * @adev: amdgpu device to use for the test
61bcc634f4SChristian König * @f: fence to test
62bcc634f4SChristian König *
63bcc634f4SChristian König * Test if the fence was issued by us.
64bcc634f4SChristian König */
amdgpu_sync_same_dev(struct amdgpu_device * adev,struct dma_fence * f)65f54d1867SChris Wilson static bool amdgpu_sync_same_dev(struct amdgpu_device *adev,
66f54d1867SChris Wilson struct dma_fence *f)
673c62338cSChunming Zhou {
681b1f42d8SLucas Stach struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
693c62338cSChunming Zhou
704f839a24SChristian König if (s_fence) {
714f839a24SChristian König struct amdgpu_ring *ring;
724f839a24SChristian König
734f839a24SChristian König ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
744f839a24SChristian König return ring->adev == adev;
754f839a24SChristian König }
764f839a24SChristian König
773c62338cSChunming Zhou return false;
783c62338cSChunming Zhou }
793c62338cSChunming Zhou
80bcc634f4SChristian König /**
81bcc634f4SChristian König * amdgpu_sync_get_owner - extract the owner of a fence
82bcc634f4SChristian König *
831b4940bcSLee Jones * @f: fence get the owner from
84bcc634f4SChristian König *
85bcc634f4SChristian König * Extract who originally created the fence.
86bcc634f4SChristian König */
amdgpu_sync_get_owner(struct dma_fence * f)87f54d1867SChris Wilson static void *amdgpu_sync_get_owner(struct dma_fence *f)
883c62338cSChunming Zhou {
89d8d019ccSFelix Kuehling struct drm_sched_fence *s_fence;
90d8d019ccSFelix Kuehling struct amdgpu_amdkfd_fence *kfd_fence;
91bcc634f4SChristian König
92d8d019ccSFelix Kuehling if (!f)
93d8d019ccSFelix Kuehling return AMDGPU_FENCE_OWNER_UNDEFINED;
94d8d019ccSFelix Kuehling
95d8d019ccSFelix Kuehling s_fence = to_drm_sched_fence(f);
963c62338cSChunming Zhou if (s_fence)
97bcc634f4SChristian König return s_fence->owner;
98336d1f5eSChristian König
99d8d019ccSFelix Kuehling kfd_fence = to_amdgpu_amdkfd_fence(f);
100d8d019ccSFelix Kuehling if (kfd_fence)
101d8d019ccSFelix Kuehling return AMDGPU_FENCE_OWNER_KFD;
102d8d019ccSFelix Kuehling
103bcc634f4SChristian König return AMDGPU_FENCE_OWNER_UNDEFINED;
1043c62338cSChunming Zhou }
1053c62338cSChunming Zhou
106bcc634f4SChristian König /**
107bcc634f4SChristian König * amdgpu_sync_keep_later - Keep the later fence
108bcc634f4SChristian König *
109bcc634f4SChristian König * @keep: existing fence to test
110bcc634f4SChristian König * @fence: new fence
111bcc634f4SChristian König *
112bcc634f4SChristian König * Either keep the existing fence or the new one, depending which one is later.
113bcc634f4SChristian König */
amdgpu_sync_keep_later(struct dma_fence ** keep,struct dma_fence * fence)114f54d1867SChris Wilson static void amdgpu_sync_keep_later(struct dma_fence **keep,
115f54d1867SChris Wilson struct dma_fence *fence)
11624233860SChristian König {
117f54d1867SChris Wilson if (*keep && dma_fence_is_later(*keep, fence))
11824233860SChristian König return;
11924233860SChristian König
120f54d1867SChris Wilson dma_fence_put(*keep);
121f54d1867SChris Wilson *keep = dma_fence_get(fence);
12224233860SChristian König }
12324233860SChristian König
124d38ceaf9SAlex Deucher /**
125832a902fSChristian König * amdgpu_sync_add_later - add the fence to the hash
126832a902fSChristian König *
127832a902fSChristian König * @sync: sync object to add the fence to
128832a902fSChristian König * @f: fence to add
129832a902fSChristian König *
130832a902fSChristian König * Tries to add the fence to an existing hash entry. Returns true when an entry
131832a902fSChristian König * was found, false otherwise.
132832a902fSChristian König */
amdgpu_sync_add_later(struct amdgpu_sync * sync,struct dma_fence * f)133174b328bSChristian König static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f)
134832a902fSChristian König {
135832a902fSChristian König struct amdgpu_sync_entry *e;
136832a902fSChristian König
137832a902fSChristian König hash_for_each_possible(sync->fences, e, node, f->context) {
1387f11c59eSChristian König if (dma_fence_is_signaled(e->fence)) {
1397f11c59eSChristian König dma_fence_put(e->fence);
1407f11c59eSChristian König e->fence = dma_fence_get(f);
1417f11c59eSChristian König return true;
1427f11c59eSChristian König }
143832a902fSChristian König
1447f11c59eSChristian König if (likely(e->fence->context == f->context)) {
145832a902fSChristian König amdgpu_sync_keep_later(&e->fence, f);
146832a902fSChristian König return true;
147832a902fSChristian König }
1487f11c59eSChristian König }
149832a902fSChristian König return false;
150832a902fSChristian König }
151832a902fSChristian König
152832a902fSChristian König /**
15391e1a520SChristian König * amdgpu_sync_fence - remember to sync to this fence
154d38ceaf9SAlex Deucher *
155d38ceaf9SAlex Deucher * @sync: sync object to add fence to
156e095fc17SChristian König * @f: fence to sync to
157*af23d3c9SSrinivasan Shanmugam * @flags: memory allocation flags to use when allocating sync entry
158d38ceaf9SAlex Deucher *
159e095fc17SChristian König * Add the fence to the sync object.
160d38ceaf9SAlex Deucher */
amdgpu_sync_fence(struct amdgpu_sync * sync,struct dma_fence * f,gfp_t flags)16116590745SChristian König int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f,
16216590745SChristian König gfp_t flags)
163d38ceaf9SAlex Deucher {
164f91b3a69SChristian König struct amdgpu_sync_entry *e;
165d38ceaf9SAlex Deucher
16691e1a520SChristian König if (!f)
16791e1a520SChristian König return 0;
1683c62338cSChunming Zhou
169174b328bSChristian König if (amdgpu_sync_add_later(sync, f))
170f91b3a69SChristian König return 0;
171f91b3a69SChristian König
17216590745SChristian König e = kmem_cache_alloc(amdgpu_sync_slab, flags);
173f91b3a69SChristian König if (!e)
174f91b3a69SChristian König return -ENOMEM;
175f91b3a69SChristian König
176f91b3a69SChristian König hash_add(sync->fences, &e->node, f->context);
177f54d1867SChris Wilson e->fence = dma_fence_get(f);
178f91b3a69SChristian König return 0;
179f91b3a69SChristian König }
180d38ceaf9SAlex Deucher
18122f0463aSChristian König /* 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)18222f0463aSChristian König static bool amdgpu_sync_test_fence(struct amdgpu_device *adev,
18322f0463aSChristian König enum amdgpu_sync_mode mode,
18422f0463aSChristian König void *owner, struct dma_fence *f)
18522f0463aSChristian König {
18622f0463aSChristian König void *fence_owner = amdgpu_sync_get_owner(f);
18722f0463aSChristian König
18822f0463aSChristian König /* Always sync to moves, no matter what */
18922f0463aSChristian König if (fence_owner == AMDGPU_FENCE_OWNER_UNDEFINED)
19022f0463aSChristian König return true;
19122f0463aSChristian König
19222f0463aSChristian König /* We only want to trigger KFD eviction fences on
19322f0463aSChristian König * evict or move jobs. Skip KFD fences otherwise.
19422f0463aSChristian König */
19522f0463aSChristian König if (fence_owner == AMDGPU_FENCE_OWNER_KFD &&
19622f0463aSChristian König owner != AMDGPU_FENCE_OWNER_UNDEFINED)
19722f0463aSChristian König return false;
19822f0463aSChristian König
19922f0463aSChristian König /* Never sync to VM updates either. */
20022f0463aSChristian König if (fence_owner == AMDGPU_FENCE_OWNER_VM &&
201ec9ba482SFelix Kuehling owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
202ec9ba482SFelix Kuehling owner != AMDGPU_FENCE_OWNER_KFD)
20322f0463aSChristian König return false;
20422f0463aSChristian König
20522f0463aSChristian König /* Ignore fences depending on the sync mode */
20622f0463aSChristian König switch (mode) {
20722f0463aSChristian König case AMDGPU_SYNC_ALWAYS:
20822f0463aSChristian König return true;
20922f0463aSChristian König
21022f0463aSChristian König case AMDGPU_SYNC_NE_OWNER:
21122f0463aSChristian König if (amdgpu_sync_same_dev(adev, f) &&
21222f0463aSChristian König fence_owner == owner)
21322f0463aSChristian König return false;
21422f0463aSChristian König break;
21522f0463aSChristian König
21622f0463aSChristian König case AMDGPU_SYNC_EQ_OWNER:
21722f0463aSChristian König if (amdgpu_sync_same_dev(adev, f) &&
21822f0463aSChristian König fence_owner != owner)
21922f0463aSChristian König return false;
22022f0463aSChristian König break;
22122f0463aSChristian König
22222f0463aSChristian König case AMDGPU_SYNC_EXPLICIT:
22322f0463aSChristian König return false;
22422f0463aSChristian König }
22522f0463aSChristian König
22622f0463aSChristian König WARN(debug_evictions && fence_owner == AMDGPU_FENCE_OWNER_KFD,
22722f0463aSChristian König "Adding eviction fence to sync obj");
22822f0463aSChristian König return true;
22922f0463aSChristian König }
23022f0463aSChristian König
231e095fc17SChristian König /**
2322f4b9400SChunming Zhou * amdgpu_sync_resv - sync to a reservation object
233d38ceaf9SAlex Deucher *
2341b4940bcSLee Jones * @adev: amdgpu device
235d38ceaf9SAlex Deucher * @sync: sync object to add fences from reservation object to
236d38ceaf9SAlex Deucher * @resv: reservation object with embedded fence
2375d319660SChristian König * @mode: how owner affects which fences we sync to
2385d319660SChristian König * @owner: owner of the planned job submission
239d38ceaf9SAlex Deucher *
2402f4b9400SChunming Zhou * Sync to the fence
241d38ceaf9SAlex Deucher */
amdgpu_sync_resv(struct amdgpu_device * adev,struct amdgpu_sync * sync,struct dma_resv * resv,enum amdgpu_sync_mode mode,void * owner)2425d319660SChristian König int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
2435d319660SChristian König struct dma_resv *resv, enum amdgpu_sync_mode mode,
2445d319660SChristian König void *owner)
245d38ceaf9SAlex Deucher {
246930ca2a7SChristian König struct dma_resv_iter cursor;
247f54d1867SChris Wilson struct dma_fence *f;
248930ca2a7SChristian König int r;
249d38ceaf9SAlex Deucher
2504b095304SJammy Zhou if (resv == NULL)
2514b095304SJammy Zhou return -EINVAL;
2524b095304SJammy Zhou
2537bc80a54SChristian König /* TODO: Use DMA_RESV_USAGE_READ here */
2540cc848a7SChristian König dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, f) {
25522f0463aSChristian König dma_fence_chain_for_each(f, f) {
256e09b9aefSChristian König struct dma_fence *tmp = dma_fence_chain_contained(f);
25722f0463aSChristian König
258e09b9aefSChristian König if (amdgpu_sync_test_fence(adev, mode, owner, tmp)) {
25916590745SChristian König r = amdgpu_sync_fence(sync, f, GFP_KERNEL);
26022f0463aSChristian König dma_fence_put(f);
26122f0463aSChristian König if (r)
26222f0463aSChristian König return r;
26322f0463aSChristian König break;
26422f0463aSChristian König }
26522f0463aSChristian König }
26622f0463aSChristian König }
26722f0463aSChristian König return 0;
26822f0463aSChristian König }
269d38ceaf9SAlex Deucher
270126be9b2SChristian König /**
271126be9b2SChristian König * amdgpu_sync_kfd - sync to KFD fences
272126be9b2SChristian König *
273126be9b2SChristian König * @sync: sync object to add KFD fences to
274126be9b2SChristian König * @resv: reservation object with KFD fences
275126be9b2SChristian König *
276126be9b2SChristian König * Extract all KFD fences and add them to the sync object.
277126be9b2SChristian König */
amdgpu_sync_kfd(struct amdgpu_sync * sync,struct dma_resv * resv)278126be9b2SChristian König int amdgpu_sync_kfd(struct amdgpu_sync *sync, struct dma_resv *resv)
279126be9b2SChristian König {
280126be9b2SChristian König struct dma_resv_iter cursor;
281126be9b2SChristian König struct dma_fence *f;
282126be9b2SChristian König int r = 0;
283126be9b2SChristian König
284126be9b2SChristian König dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP);
285126be9b2SChristian König dma_resv_for_each_fence_unlocked(&cursor, f) {
286126be9b2SChristian König void *fence_owner = amdgpu_sync_get_owner(f);
287126be9b2SChristian König
288126be9b2SChristian König if (fence_owner != AMDGPU_FENCE_OWNER_KFD)
289126be9b2SChristian König continue;
290126be9b2SChristian König
29116590745SChristian König r = amdgpu_sync_fence(sync, f, GFP_KERNEL);
292126be9b2SChristian König if (r)
293126be9b2SChristian König break;
294126be9b2SChristian König }
295126be9b2SChristian König dma_resv_iter_end(&cursor);
296126be9b2SChristian König
297126be9b2SChristian König return r;
298126be9b2SChristian König }
299126be9b2SChristian König
300aab9cf7bSChristian König /* Free the entry back to the slab */
amdgpu_sync_entry_free(struct amdgpu_sync_entry * e)301aab9cf7bSChristian König static void amdgpu_sync_entry_free(struct amdgpu_sync_entry *e)
302aab9cf7bSChristian König {
303aab9cf7bSChristian König hash_del(&e->node);
304aab9cf7bSChristian König dma_fence_put(e->fence);
305aab9cf7bSChristian König kmem_cache_free(amdgpu_sync_slab, e);
306aab9cf7bSChristian König }
307aab9cf7bSChristian König
308832a902fSChristian König /**
3091fbb2e92SChristian König * amdgpu_sync_peek_fence - get the next fence not signaled yet
310832a902fSChristian König *
311832a902fSChristian König * @sync: the sync object
31235420238SChristian König * @ring: optional ring to use for test
313832a902fSChristian König *
3141fbb2e92SChristian König * Returns the next fence not signaled yet without removing it from the sync
3151fbb2e92SChristian König * object.
316832a902fSChristian König */
amdgpu_sync_peek_fence(struct amdgpu_sync * sync,struct amdgpu_ring * ring)317f54d1867SChris Wilson struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
31835420238SChristian König struct amdgpu_ring *ring)
319832a902fSChristian König {
320832a902fSChristian König struct amdgpu_sync_entry *e;
321832a902fSChristian König struct hlist_node *tmp;
322832a902fSChristian König int i;
323832a902fSChristian König
324832a902fSChristian König hash_for_each_safe(sync->fences, i, tmp, e, node) {
325f54d1867SChris Wilson struct dma_fence *f = e->fence;
3261b1f42d8SLucas Stach struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
32735420238SChristian König
3287a7c286dSChunming Zhou if (dma_fence_is_signaled(f)) {
329aab9cf7bSChristian König amdgpu_sync_entry_free(e);
3307a7c286dSChunming Zhou continue;
3317a7c286dSChunming Zhou }
33235420238SChristian König if (ring && s_fence) {
33335420238SChristian König /* For fences from the same ring it is sufficient
33435420238SChristian König * when they are scheduled.
33535420238SChristian König */
3361fbb2e92SChristian König if (s_fence->sched == &ring->sched) {
337f54d1867SChris Wilson if (dma_fence_is_signaled(&s_fence->scheduled))
33835420238SChristian König continue;
3391fbb2e92SChristian König
3401fbb2e92SChristian König return &s_fence->scheduled;
3411fbb2e92SChristian König }
34235420238SChristian König }
343832a902fSChristian König
3441fbb2e92SChristian König return f;
345832a902fSChristian König }
346832a902fSChristian König
3471fbb2e92SChristian König return NULL;
348832a902fSChristian König }
349832a902fSChristian König
3500e9d239bSChristian König /**
3510e9d239bSChristian König * amdgpu_sync_get_fence - get the next fence from the sync object
3520e9d239bSChristian König *
3530e9d239bSChristian König * @sync: sync object to use
3540e9d239bSChristian König *
3550e9d239bSChristian König * Get and removes the next fence from the sync object not signaled yet.
3560e9d239bSChristian König */
amdgpu_sync_get_fence(struct amdgpu_sync * sync)357174b328bSChristian König struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
358e61235dbSChristian König {
359e61235dbSChristian König struct amdgpu_sync_entry *e;
360e61235dbSChristian König struct hlist_node *tmp;
361f54d1867SChris Wilson struct dma_fence *f;
362e61235dbSChristian König int i;
363826f03b8SJingyu Wang
364e61235dbSChristian König hash_for_each_safe(sync->fences, i, tmp, e, node) {
365e61235dbSChristian König
366e61235dbSChristian König f = e->fence;
367e61235dbSChristian König
368e61235dbSChristian König hash_del(&e->node);
369257bf15aSChristian König kmem_cache_free(amdgpu_sync_slab, e);
370e61235dbSChristian König
371f54d1867SChris Wilson if (!dma_fence_is_signaled(f))
372e61235dbSChristian König return f;
373e61235dbSChristian König
374f54d1867SChris Wilson dma_fence_put(f);
375e61235dbSChristian König }
376e61235dbSChristian König return NULL;
377e61235dbSChristian König }
378e61235dbSChristian König
3793c728d3aSFelix Kuehling /**
3803c728d3aSFelix Kuehling * amdgpu_sync_clone - clone a sync object
3813c728d3aSFelix Kuehling *
3823c728d3aSFelix Kuehling * @source: sync object to clone
3833c728d3aSFelix Kuehling * @clone: pointer to destination sync object
3843c728d3aSFelix Kuehling *
3853c728d3aSFelix Kuehling * Adds references to all unsignaled fences in @source to @clone. Also
3863c728d3aSFelix Kuehling * removes signaled fences from @source while at it.
3873c728d3aSFelix Kuehling */
amdgpu_sync_clone(struct amdgpu_sync * source,struct amdgpu_sync * clone)3883c728d3aSFelix Kuehling int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone)
3893c728d3aSFelix Kuehling {
3903c728d3aSFelix Kuehling struct amdgpu_sync_entry *e;
3913c728d3aSFelix Kuehling struct hlist_node *tmp;
3923c728d3aSFelix Kuehling struct dma_fence *f;
3933c728d3aSFelix Kuehling int i, r;
3943c728d3aSFelix Kuehling
3953c728d3aSFelix Kuehling hash_for_each_safe(source->fences, i, tmp, e, node) {
3963c728d3aSFelix Kuehling f = e->fence;
3973c728d3aSFelix Kuehling if (!dma_fence_is_signaled(f)) {
39816590745SChristian König r = amdgpu_sync_fence(clone, f, GFP_KERNEL);
3993c728d3aSFelix Kuehling if (r)
4003c728d3aSFelix Kuehling return r;
4013c728d3aSFelix Kuehling } else {
402aab9cf7bSChristian König amdgpu_sync_entry_free(e);
4033c728d3aSFelix Kuehling }
4043c728d3aSFelix Kuehling }
4053c728d3aSFelix Kuehling
4063c728d3aSFelix Kuehling return 0;
4073c728d3aSFelix Kuehling }
4083c728d3aSFelix Kuehling
409aab9cf7bSChristian König /**
410bd22e44aSChristian König * amdgpu_sync_move - move all fences from src to dst
411bd22e44aSChristian König *
412bd22e44aSChristian König * @src: source of the fences, empty after function
413bd22e44aSChristian König * @dst: destination for the fences
414bd22e44aSChristian König *
415bd22e44aSChristian König * Moves all fences from source to destination. All fences in destination are
416bd22e44aSChristian König * freed and source is empty after the function call.
417bd22e44aSChristian König */
amdgpu_sync_move(struct amdgpu_sync * src,struct amdgpu_sync * dst)418bd22e44aSChristian König void amdgpu_sync_move(struct amdgpu_sync *src, struct amdgpu_sync *dst)
419bd22e44aSChristian König {
420bd22e44aSChristian König unsigned int i;
421bd22e44aSChristian König
422bd22e44aSChristian König amdgpu_sync_free(dst);
423bd22e44aSChristian König
424bd22e44aSChristian König for (i = 0; i < HASH_SIZE(src->fences); ++i)
425bd22e44aSChristian König hlist_move_list(&src->fences[i], &dst->fences[i]);
426bd22e44aSChristian König }
427bd22e44aSChristian König
428bd22e44aSChristian König /**
429aab9cf7bSChristian König * amdgpu_sync_push_to_job - push fences into job
430aab9cf7bSChristian König * @sync: sync object to get the fences from
431aab9cf7bSChristian König * @job: job to push the fences into
432aab9cf7bSChristian König *
433aab9cf7bSChristian König * Add all unsignaled fences from sync to job.
434aab9cf7bSChristian König */
amdgpu_sync_push_to_job(struct amdgpu_sync * sync,struct amdgpu_job * job)435aab9cf7bSChristian König int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job)
436aab9cf7bSChristian König {
437aab9cf7bSChristian König struct amdgpu_sync_entry *e;
438aab9cf7bSChristian König struct hlist_node *tmp;
439aab9cf7bSChristian König struct dma_fence *f;
440aab9cf7bSChristian König int i, r;
441aab9cf7bSChristian König
442aab9cf7bSChristian König hash_for_each_safe(sync->fences, i, tmp, e, node) {
443aab9cf7bSChristian König f = e->fence;
444aab9cf7bSChristian König if (dma_fence_is_signaled(f)) {
445aab9cf7bSChristian König amdgpu_sync_entry_free(e);
446aab9cf7bSChristian König continue;
447aab9cf7bSChristian König }
448aab9cf7bSChristian König
449aab9cf7bSChristian König dma_fence_get(f);
450aab9cf7bSChristian König r = drm_sched_job_add_dependency(&job->base, f);
45141cc108bSChristian König if (r) {
45241cc108bSChristian König dma_fence_put(f);
453aab9cf7bSChristian König return r;
454aab9cf7bSChristian König }
45541cc108bSChristian König }
456aab9cf7bSChristian König return 0;
457aab9cf7bSChristian König }
458aab9cf7bSChristian König
amdgpu_sync_wait(struct amdgpu_sync * sync,bool intr)459a6583af4SHarish Kasiviswanathan int amdgpu_sync_wait(struct amdgpu_sync *sync, bool intr)
460a6583af4SHarish Kasiviswanathan {
461a6583af4SHarish Kasiviswanathan struct amdgpu_sync_entry *e;
462a6583af4SHarish Kasiviswanathan struct hlist_node *tmp;
463a6583af4SHarish Kasiviswanathan int i, r;
464a6583af4SHarish Kasiviswanathan
465a6583af4SHarish Kasiviswanathan hash_for_each_safe(sync->fences, i, tmp, e, node) {
466a6583af4SHarish Kasiviswanathan r = dma_fence_wait(e->fence, intr);
467a6583af4SHarish Kasiviswanathan if (r)
468a6583af4SHarish Kasiviswanathan return r;
469a6583af4SHarish Kasiviswanathan
470aab9cf7bSChristian König amdgpu_sync_entry_free(e);
471a6583af4SHarish Kasiviswanathan }
472a6583af4SHarish Kasiviswanathan
473a6583af4SHarish Kasiviswanathan return 0;
474a6583af4SHarish Kasiviswanathan }
475a6583af4SHarish Kasiviswanathan
476d38ceaf9SAlex Deucher /**
477d38ceaf9SAlex Deucher * amdgpu_sync_free - free the sync object
478d38ceaf9SAlex Deucher *
479d38ceaf9SAlex Deucher * @sync: sync object to use
480d38ceaf9SAlex Deucher *
4812f4b9400SChunming Zhou * Free the sync object.
482d38ceaf9SAlex Deucher */
amdgpu_sync_free(struct amdgpu_sync * sync)4838a8f0b48SChristian König void amdgpu_sync_free(struct amdgpu_sync *sync)
484d38ceaf9SAlex Deucher {
485f91b3a69SChristian König struct amdgpu_sync_entry *e;
486f91b3a69SChristian König struct hlist_node *tmp;
487826f03b8SJingyu Wang unsigned int i;
488d38ceaf9SAlex Deucher
489aab9cf7bSChristian König hash_for_each_safe(sync->fences, i, tmp, e, node)
490aab9cf7bSChristian König amdgpu_sync_entry_free(e);
491d38ceaf9SAlex Deucher }
492257bf15aSChristian König
493257bf15aSChristian König /**
494257bf15aSChristian König * amdgpu_sync_init - init sync object subsystem
495257bf15aSChristian König *
496257bf15aSChristian König * Allocate the slab allocator.
497257bf15aSChristian König */
amdgpu_sync_init(void)498257bf15aSChristian König int amdgpu_sync_init(void)
499257bf15aSChristian König {
500a5fc4e50SKunwu Chan amdgpu_sync_slab = KMEM_CACHE(amdgpu_sync_entry, SLAB_HWCACHE_ALIGN);
501257bf15aSChristian König if (!amdgpu_sync_slab)
502257bf15aSChristian König return -ENOMEM;
503257bf15aSChristian König
504257bf15aSChristian König return 0;
505257bf15aSChristian König }
506257bf15aSChristian König
507257bf15aSChristian König /**
508257bf15aSChristian König * amdgpu_sync_fini - fini sync object subsystem
509257bf15aSChristian König *
510257bf15aSChristian König * Free the slab allocator.
511257bf15aSChristian König */
amdgpu_sync_fini(void)512257bf15aSChristian König void amdgpu_sync_fini(void)
513257bf15aSChristian König {
514257bf15aSChristian König kmem_cache_destroy(amdgpu_sync_slab);
515257bf15aSChristian König }
516