drm/amdgpu: remove some more semaphore leftovers
[deliverable/linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_sync.c
CommitLineData
d38ceaf9
AD
1/*
2 * Copyright 2014 Advanced Micro Devices, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19 * USE OR OTHER DEALINGS IN THE SOFTWARE.
20 *
21 * The above copyright notice and this permission notice (including the
22 * next paragraph) shall be included in all copies or substantial portions
23 * of the Software.
24 *
25 */
26/*
27 * Authors:
28 * Christian König <christian.koenig@amd.com>
29 */
30
31#include <drm/drmP.h>
32#include "amdgpu.h"
33#include "amdgpu_trace.h"
34
f91b3a69
CK
35struct amdgpu_sync_entry {
36 struct hlist_node node;
37 struct fence *fence;
38};
39
d38ceaf9
AD
40/**
41 * amdgpu_sync_create - zero init sync object
42 *
43 * @sync: sync object to initialize
44 *
45 * Just clear the sync object for now.
46 */
47void amdgpu_sync_create(struct amdgpu_sync *sync)
48{
49 unsigned i;
50
d38ceaf9
AD
51 for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
52 sync->sync_to[i] = NULL;
53
f91b3a69 54 hash_init(sync->fences);
d38ceaf9
AD
55 sync->last_vm_update = NULL;
56}
57
3c62338c
CZ
58static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f)
59{
60 struct amdgpu_fence *a_fence = to_amdgpu_fence(f);
61 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
62
63 if (a_fence)
64 return a_fence->ring->adev == adev;
4f839a24
CK
65
66 if (s_fence) {
67 struct amdgpu_ring *ring;
68
69 ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
70 return ring->adev == adev;
71 }
72
3c62338c
CZ
73 return false;
74}
75
76static bool amdgpu_sync_test_owner(struct fence *f, void *owner)
77{
78 struct amdgpu_fence *a_fence = to_amdgpu_fence(f);
79 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
80 if (s_fence)
81 return s_fence->owner == owner;
82 if (a_fence)
83 return a_fence->owner == owner;
84 return false;
85}
86
24233860
CK
87static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence)
88{
89 if (*keep && fence_is_later(*keep, fence))
90 return;
91
92 fence_put(*keep);
93 *keep = fence_get(fence);
94}
95
d38ceaf9 96/**
91e1a520 97 * amdgpu_sync_fence - remember to sync to this fence
d38ceaf9
AD
98 *
99 * @sync: sync object to add fence to
100 * @fence: fence to sync to
101 *
d38ceaf9 102 */
91e1a520
CK
103int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
104 struct fence *f)
d38ceaf9 105{
f91b3a69 106 struct amdgpu_sync_entry *e;
91e1a520 107 struct amdgpu_fence *fence;
d38ceaf9 108
91e1a520
CK
109 if (!f)
110 return 0;
111
3c62338c 112 if (amdgpu_sync_same_dev(adev, f) &&
24233860
CK
113 amdgpu_sync_test_owner(f, AMDGPU_FENCE_OWNER_VM))
114 amdgpu_sync_keep_later(&sync->last_vm_update, f);
3c62338c 115
91e1a520 116 fence = to_amdgpu_fence(f);
f91b3a69
CK
117 if (!fence || fence->ring->adev != adev) {
118 hash_for_each_possible(sync->fences, e, node, f->context) {
f91b3a69
CK
119 if (unlikely(e->fence->context != f->context))
120 continue;
24233860
CK
121
122 amdgpu_sync_keep_later(&e->fence, f);
f91b3a69
CK
123 return 0;
124 }
125
126 e = kmalloc(sizeof(struct amdgpu_sync_entry), GFP_KERNEL);
127 if (!e)
128 return -ENOMEM;
129
130 hash_add(sync->fences, &e->node, f->context);
131 e->fence = fence_get(f);
132 return 0;
133 }
d38ceaf9 134
16545c32 135 amdgpu_sync_keep_later(&sync->sync_to[fence->ring->idx], f);
d38ceaf9 136
91e1a520 137 return 0;
d38ceaf9
AD
138}
139
423a9480
CZ
140static void *amdgpu_sync_get_owner(struct fence *f)
141{
142 struct amdgpu_fence *a_fence = to_amdgpu_fence(f);
143 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
144
145 if (s_fence)
146 return s_fence->owner;
147 else if (a_fence)
148 return a_fence->owner;
149 return AMDGPU_FENCE_OWNER_UNDEFINED;
150}
151
d38ceaf9 152/**
2f4b9400 153 * amdgpu_sync_resv - sync to a reservation object
d38ceaf9
AD
154 *
155 * @sync: sync object to add fences from reservation object to
156 * @resv: reservation object with embedded fence
157 * @shared: true if we should only sync to the exclusive fence
158 *
2f4b9400 159 * Sync to the fence
d38ceaf9
AD
160 */
161int amdgpu_sync_resv(struct amdgpu_device *adev,
162 struct amdgpu_sync *sync,
163 struct reservation_object *resv,
164 void *owner)
165{
166 struct reservation_object_list *flist;
167 struct fence *f;
423a9480 168 void *fence_owner;
d38ceaf9
AD
169 unsigned i;
170 int r = 0;
171
4b095304
JZ
172 if (resv == NULL)
173 return -EINVAL;
174
d38ceaf9
AD
175 /* always sync to the exclusive fence */
176 f = reservation_object_get_excl(resv);
91e1a520 177 r = amdgpu_sync_fence(adev, sync, f);
d38ceaf9
AD
178
179 flist = reservation_object_get_list(resv);
180 if (!flist || r)
181 return r;
182
183 for (i = 0; i < flist->shared_count; ++i) {
184 f = rcu_dereference_protected(flist->shared[i],
185 reservation_object_held(resv));
423a9480 186 if (amdgpu_sync_same_dev(adev, f)) {
1d3897e0
CK
187 /* VM updates are only interesting
188 * for other VM updates and moves.
189 */
423a9480 190 fence_owner = amdgpu_sync_get_owner(f);
7a91d6cb
CK
191 if ((owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
192 (fence_owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
1d3897e0 193 ((owner == AMDGPU_FENCE_OWNER_VM) !=
423a9480 194 (fence_owner == AMDGPU_FENCE_OWNER_VM)))
91e1a520
CK
195 continue;
196
1d3897e0
CK
197 /* Ignore fence from the same owner as
198 * long as it isn't undefined.
199 */
200 if (owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
423a9480 201 fence_owner == owner)
1d3897e0
CK
202 continue;
203 }
204
91e1a520
CK
205 r = amdgpu_sync_fence(adev, sync, f);
206 if (r)
207 break;
d38ceaf9
AD
208 }
209 return r;
210}
211
e61235db
CK
212struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
213{
214 struct amdgpu_sync_entry *e;
215 struct hlist_node *tmp;
216 struct fence *f;
217 int i;
218
219 hash_for_each_safe(sync->fences, i, tmp, e, node) {
220
221 f = e->fence;
222
223 hash_del(&e->node);
224 kfree(e);
225
226 if (!fence_is_signaled(f))
227 return f;
228
229 fence_put(f);
230 }
231 return NULL;
232}
233
f91b3a69
CK
234int amdgpu_sync_wait(struct amdgpu_sync *sync)
235{
236 struct amdgpu_sync_entry *e;
237 struct hlist_node *tmp;
238 int i, r;
239
240 hash_for_each_safe(sync->fences, i, tmp, e, node) {
241 r = fence_wait(e->fence, false);
242 if (r)
243 return r;
244
245 hash_del(&e->node);
246 fence_put(e->fence);
247 kfree(e);
248 }
3daea9e3 249
3daea9e3 250 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
16545c32 251 struct fence *fence = sync->sync_to[i];
3daea9e3
CK
252 if (!fence)
253 continue;
254
16545c32 255 r = fence_wait(fence, false);
3daea9e3
CK
256 if (r)
257 return r;
258 }
259
f91b3a69
CK
260 return 0;
261}
262
d38ceaf9
AD
263/**
264 * amdgpu_sync_free - free the sync object
265 *
266 * @adev: amdgpu_device pointer
267 * @sync: sync object to use
268 * @fence: fence to use for the free
269 *
2f4b9400 270 * Free the sync object.
d38ceaf9
AD
271 */
272void amdgpu_sync_free(struct amdgpu_device *adev,
273 struct amdgpu_sync *sync,
4ce9891e 274 struct fence *fence)
d38ceaf9 275{
f91b3a69
CK
276 struct amdgpu_sync_entry *e;
277 struct hlist_node *tmp;
d38ceaf9
AD
278 unsigned i;
279
f91b3a69
CK
280 hash_for_each_safe(sync->fences, i, tmp, e, node) {
281 hash_del(&e->node);
282 fence_put(e->fence);
283 kfree(e);
284 }
285
d38ceaf9 286 for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
16545c32 287 fence_put(sync->sync_to[i]);
d38ceaf9 288
3c62338c 289 fence_put(sync->last_vm_update);
d38ceaf9 290}
This page took 0.073218 seconds and 5 git commands to generate.