diff options
author | Mark Brown <broonie@kernel.org> | 2015-10-12 13:09:27 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-10-12 13:09:27 -0400 |
commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | |
parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (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.c | 195 |
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 | ||
35 | struct 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 | ||
61 | static 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 | |||
73 | static 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 | */ |
63 | void amdgpu_sync_fence(struct amdgpu_sync *sync, | 91 | int 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)); | 145 | static 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 | ||
217 | struct 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 | |||
239 | int 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 | */ |
221 | void amdgpu_sync_free(struct amdgpu_device *adev, | 342 | void 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 | } |