aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2015-10-12 13:09:27 -0400
committerMark Brown <broonie@kernel.org>2015-10-12 13:09:27 -0400
commit79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch)
tree5e0fa7156acb75ba603022bc807df8f2fedb97a8 /drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
parent721b51fcf91898299d96f4b72cb9434cda29dce6 (diff)
parent8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff)
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c195
1 files changed, 162 insertions, 33 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index 21accbdd0a1a..068aeaff7183 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -32,6 +32,11 @@
32#include "amdgpu.h" 32#include "amdgpu.h"
33#include "amdgpu_trace.h" 33#include "amdgpu_trace.h"
34 34
35struct amdgpu_sync_entry {
36 struct hlist_node node;
37 struct fence *fence;
38};
39
35/** 40/**
36 * amdgpu_sync_create - zero init sync object 41 * amdgpu_sync_create - zero init sync object
37 * 42 *
@@ -49,36 +54,104 @@ void amdgpu_sync_create(struct amdgpu_sync *sync)
49 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) 54 for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
50 sync->sync_to[i] = NULL; 55 sync->sync_to[i] = NULL;
51 56
57 hash_init(sync->fences);
52 sync->last_vm_update = NULL; 58 sync->last_vm_update = NULL;
53} 59}
54 60
61static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f)
62{
63 struct amdgpu_fence *a_fence = to_amdgpu_fence(f);
64 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
65
66 if (a_fence)
67 return a_fence->ring->adev == adev;
68 if (s_fence)
69 return (struct amdgpu_device *)s_fence->scheduler->priv == adev;
70 return false;
71}
72
73static bool amdgpu_sync_test_owner(struct fence *f, void *owner)
74{
75 struct amdgpu_fence *a_fence = to_amdgpu_fence(f);
76 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
77 if (s_fence)
78 return s_fence->owner == owner;
79 if (a_fence)
80 return a_fence->owner == owner;
81 return false;
82}
83
55/** 84/**
56 * amdgpu_sync_fence - use the semaphore to sync to a fence 85 * amdgpu_sync_fence - remember to sync to this fence
57 * 86 *
58 * @sync: sync object to add fence to 87 * @sync: sync object to add fence to
59 * @fence: fence to sync to 88 * @fence: fence to sync to
60 * 89 *
61 * Sync to the fence using the semaphore objects
62 */ 90 */
63void amdgpu_sync_fence(struct amdgpu_sync *sync, 91int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
64 struct amdgpu_fence *fence) 92 struct fence *f)
65{ 93{
94 struct amdgpu_sync_entry *e;
95 struct amdgpu_fence *fence;
66 struct amdgpu_fence *other; 96 struct amdgpu_fence *other;
97 struct fence *tmp, *later;
67 98
68 if (!fence) 99 if (!f)
69 return; 100 return 0;
101
102 if (amdgpu_sync_same_dev(adev, f) &&
103 amdgpu_sync_test_owner(f, AMDGPU_FENCE_OWNER_VM)) {
104 if (sync->last_vm_update) {
105 tmp = sync->last_vm_update;
106 BUG_ON(f->context != tmp->context);
107 later = (f->seqno - tmp->seqno <= INT_MAX) ? f : tmp;
108 sync->last_vm_update = fence_get(later);
109 fence_put(tmp);
110 } else
111 sync->last_vm_update = fence_get(f);
112 }
113
114 fence = to_amdgpu_fence(f);
115 if (!fence || fence->ring->adev != adev) {
116 hash_for_each_possible(sync->fences, e, node, f->context) {
117 struct fence *new;
118 if (unlikely(e->fence->context != f->context))
119 continue;
120 new = fence_get(fence_later(e->fence, f));
121 if (new) {
122 fence_put(e->fence);
123 e->fence = new;
124 }
125 return 0;
126 }
127
128 e = kmalloc(sizeof(struct amdgpu_sync_entry), GFP_KERNEL);
129 if (!e)
130 return -ENOMEM;
131
132 hash_add(sync->fences, &e->node, f->context);
133 e->fence = fence_get(f);
134 return 0;
135 }
70 136
71 other = sync->sync_to[fence->ring->idx]; 137 other = sync->sync_to[fence->ring->idx];
72 sync->sync_to[fence->ring->idx] = amdgpu_fence_ref( 138 sync->sync_to[fence->ring->idx] = amdgpu_fence_ref(
73 amdgpu_fence_later(fence, other)); 139 amdgpu_fence_later(fence, other));
74 amdgpu_fence_unref(&other); 140 amdgpu_fence_unref(&other);
75 141
76 if (fence->owner == AMDGPU_FENCE_OWNER_VM) { 142 return 0;
77 other = sync->last_vm_update; 143}
78 sync->last_vm_update = amdgpu_fence_ref( 144
79 amdgpu_fence_later(fence, other)); 145static void *amdgpu_sync_get_owner(struct fence *f)
80 amdgpu_fence_unref(&other); 146{
81 } 147 struct amdgpu_fence *a_fence = to_amdgpu_fence(f);
148 struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
149
150 if (s_fence)
151 return s_fence->owner;
152 else if (a_fence)
153 return a_fence->owner;
154 return AMDGPU_FENCE_OWNER_UNDEFINED;
82} 155}
83 156
84/** 157/**
@@ -97,7 +170,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
97{ 170{
98 struct reservation_object_list *flist; 171 struct reservation_object_list *flist;
99 struct fence *f; 172 struct fence *f;
100 struct amdgpu_fence *fence; 173 void *fence_owner;
101 unsigned i; 174 unsigned i;
102 int r = 0; 175 int r = 0;
103 176
@@ -106,11 +179,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
106 179
107 /* always sync to the exclusive fence */ 180 /* always sync to the exclusive fence */
108 f = reservation_object_get_excl(resv); 181 f = reservation_object_get_excl(resv);
109 fence = f ? to_amdgpu_fence(f) : NULL; 182 r = amdgpu_sync_fence(adev, sync, f);
110 if (fence && fence->ring->adev == adev)
111 amdgpu_sync_fence(sync, fence);
112 else if (f)
113 r = fence_wait(f, true);
114 183
115 flist = reservation_object_get_list(resv); 184 flist = reservation_object_get_list(resv);
116 if (!flist || r) 185 if (!flist || r)
@@ -119,20 +188,72 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
119 for (i = 0; i < flist->shared_count; ++i) { 188 for (i = 0; i < flist->shared_count; ++i) {
120 f = rcu_dereference_protected(flist->shared[i], 189 f = rcu_dereference_protected(flist->shared[i],
121 reservation_object_held(resv)); 190 reservation_object_held(resv));
122 fence = f ? to_amdgpu_fence(f) : NULL; 191 if (amdgpu_sync_same_dev(adev, f)) {
123 if (fence && fence->ring->adev == adev) { 192 /* VM updates are only interesting
124 if (fence->owner != owner || 193 * for other VM updates and moves.
125 fence->owner == AMDGPU_FENCE_OWNER_UNDEFINED) 194 */
126 amdgpu_sync_fence(sync, fence); 195 fence_owner = amdgpu_sync_get_owner(f);
127 } else if (f) { 196 if ((owner != AMDGPU_FENCE_OWNER_MOVE) &&
128 r = fence_wait(f, true); 197 (fence_owner != AMDGPU_FENCE_OWNER_MOVE) &&
129 if (r) 198 ((owner == AMDGPU_FENCE_OWNER_VM) !=
130 break; 199 (fence_owner == AMDGPU_FENCE_OWNER_VM)))
200 continue;
201
202 /* Ignore fence from the same owner as
203 * long as it isn't undefined.
204 */
205 if (owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
206 fence_owner == owner)
207 continue;
131 } 208 }
209
210 r = amdgpu_sync_fence(adev, sync, f);
211 if (r)
212 break;
132 } 213 }
133 return r; 214 return r;
134} 215}
135 216
217struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
218{
219 struct amdgpu_sync_entry *e;
220 struct hlist_node *tmp;
221 struct fence *f;
222 int i;
223
224 hash_for_each_safe(sync->fences, i, tmp, e, node) {
225
226 f = e->fence;
227
228 hash_del(&e->node);
229 kfree(e);
230
231 if (!fence_is_signaled(f))
232 return f;
233
234 fence_put(f);
235 }
236 return NULL;
237}
238
239int amdgpu_sync_wait(struct amdgpu_sync *sync)
240{
241 struct amdgpu_sync_entry *e;
242 struct hlist_node *tmp;
243 int i, r;
244
245 hash_for_each_safe(sync->fences, i, tmp, e, node) {
246 r = fence_wait(e->fence, false);
247 if (r)
248 return r;
249
250 hash_del(&e->node);
251 fence_put(e->fence);
252 kfree(e);
253 }
254 return 0;
255}
256
136/** 257/**
137 * amdgpu_sync_rings - sync ring to all registered fences 258 * amdgpu_sync_rings - sync ring to all registered fences
138 * 259 *
@@ -164,9 +285,9 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
164 return -EINVAL; 285 return -EINVAL;
165 } 286 }
166 287
167 if (count >= AMDGPU_NUM_SYNCS) { 288 if (amdgpu_enable_scheduler || (count >= AMDGPU_NUM_SYNCS)) {
168 /* not enough room, wait manually */ 289 /* not enough room, wait manually */
169 r = amdgpu_fence_wait(fence, false); 290 r = fence_wait(&fence->base, false);
170 if (r) 291 if (r)
171 return r; 292 return r;
172 continue; 293 continue;
@@ -186,7 +307,7 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
186 if (!amdgpu_semaphore_emit_signal(other, semaphore)) { 307 if (!amdgpu_semaphore_emit_signal(other, semaphore)) {
187 /* signaling wasn't successful wait manually */ 308 /* signaling wasn't successful wait manually */
188 amdgpu_ring_undo(other); 309 amdgpu_ring_undo(other);
189 r = amdgpu_fence_wait(fence, false); 310 r = fence_wait(&fence->base, false);
190 if (r) 311 if (r)
191 return r; 312 return r;
192 continue; 313 continue;
@@ -196,7 +317,7 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
196 if (!amdgpu_semaphore_emit_wait(ring, semaphore)) { 317 if (!amdgpu_semaphore_emit_wait(ring, semaphore)) {
197 /* waiting wasn't successful wait manually */ 318 /* waiting wasn't successful wait manually */
198 amdgpu_ring_undo(other); 319 amdgpu_ring_undo(other);
199 r = amdgpu_fence_wait(fence, false); 320 r = fence_wait(&fence->base, false);
200 if (r) 321 if (r)
201 return r; 322 return r;
202 continue; 323 continue;
@@ -220,15 +341,23 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
220 */ 341 */
221void amdgpu_sync_free(struct amdgpu_device *adev, 342void amdgpu_sync_free(struct amdgpu_device *adev,
222 struct amdgpu_sync *sync, 343 struct amdgpu_sync *sync,
223 struct amdgpu_fence *fence) 344 struct fence *fence)
224{ 345{
346 struct amdgpu_sync_entry *e;
347 struct hlist_node *tmp;
225 unsigned i; 348 unsigned i;
226 349
350 hash_for_each_safe(sync->fences, i, tmp, e, node) {
351 hash_del(&e->node);
352 fence_put(e->fence);
353 kfree(e);
354 }
355
227 for (i = 0; i < AMDGPU_NUM_SYNCS; ++i) 356 for (i = 0; i < AMDGPU_NUM_SYNCS; ++i)
228 amdgpu_semaphore_free(adev, &sync->semaphores[i], fence); 357 amdgpu_semaphore_free(adev, &sync->semaphores[i], fence);
229 358
230 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) 359 for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
231 amdgpu_fence_unref(&sync->sync_to[i]); 360 amdgpu_fence_unref(&sync->sync_to[i]);
232 361
233 amdgpu_fence_unref(&sync->last_vm_update); 362 fence_put(sync->last_vm_update);
234} 363}