diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 412 |
1 files changed, 283 insertions, 129 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c index 16884a0b677b..a1c78f90eadf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | |||
@@ -40,6 +40,12 @@ | |||
40 | */ | 40 | */ |
41 | static DEFINE_IDA(amdgpu_pasid_ida); | 41 | static DEFINE_IDA(amdgpu_pasid_ida); |
42 | 42 | ||
43 | /* Helper to free pasid from a fence callback */ | ||
44 | struct amdgpu_pasid_cb { | ||
45 | struct dma_fence_cb cb; | ||
46 | unsigned int pasid; | ||
47 | }; | ||
48 | |||
43 | /** | 49 | /** |
44 | * amdgpu_pasid_alloc - Allocate a PASID | 50 | * amdgpu_pasid_alloc - Allocate a PASID |
45 | * @bits: Maximum width of the PASID in bits, must be at least 1 | 51 | * @bits: Maximum width of the PASID in bits, must be at least 1 |
@@ -63,6 +69,9 @@ int amdgpu_pasid_alloc(unsigned int bits) | |||
63 | break; | 69 | break; |
64 | } | 70 | } |
65 | 71 | ||
72 | if (pasid >= 0) | ||
73 | trace_amdgpu_pasid_allocated(pasid); | ||
74 | |||
66 | return pasid; | 75 | return pasid; |
67 | } | 76 | } |
68 | 77 | ||
@@ -72,9 +81,86 @@ int amdgpu_pasid_alloc(unsigned int bits) | |||
72 | */ | 81 | */ |
73 | void amdgpu_pasid_free(unsigned int pasid) | 82 | void amdgpu_pasid_free(unsigned int pasid) |
74 | { | 83 | { |
84 | trace_amdgpu_pasid_freed(pasid); | ||
75 | ida_simple_remove(&amdgpu_pasid_ida, pasid); | 85 | ida_simple_remove(&amdgpu_pasid_ida, pasid); |
76 | } | 86 | } |
77 | 87 | ||
88 | static void amdgpu_pasid_free_cb(struct dma_fence *fence, | ||
89 | struct dma_fence_cb *_cb) | ||
90 | { | ||
91 | struct amdgpu_pasid_cb *cb = | ||
92 | container_of(_cb, struct amdgpu_pasid_cb, cb); | ||
93 | |||
94 | amdgpu_pasid_free(cb->pasid); | ||
95 | dma_fence_put(fence); | ||
96 | kfree(cb); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * amdgpu_pasid_free_delayed - free pasid when fences signal | ||
101 | * | ||
102 | * @resv: reservation object with the fences to wait for | ||
103 | * @pasid: pasid to free | ||
104 | * | ||
105 | * Free the pasid only after all the fences in resv are signaled. | ||
106 | */ | ||
107 | void amdgpu_pasid_free_delayed(struct reservation_object *resv, | ||
108 | unsigned int pasid) | ||
109 | { | ||
110 | struct dma_fence *fence, **fences; | ||
111 | struct amdgpu_pasid_cb *cb; | ||
112 | unsigned count; | ||
113 | int r; | ||
114 | |||
115 | r = reservation_object_get_fences_rcu(resv, NULL, &count, &fences); | ||
116 | if (r) | ||
117 | goto fallback; | ||
118 | |||
119 | if (count == 0) { | ||
120 | amdgpu_pasid_free(pasid); | ||
121 | return; | ||
122 | } | ||
123 | |||
124 | if (count == 1) { | ||
125 | fence = fences[0]; | ||
126 | kfree(fences); | ||
127 | } else { | ||
128 | uint64_t context = dma_fence_context_alloc(1); | ||
129 | struct dma_fence_array *array; | ||
130 | |||
131 | array = dma_fence_array_create(count, fences, context, | ||
132 | 1, false); | ||
133 | if (!array) { | ||
134 | kfree(fences); | ||
135 | goto fallback; | ||
136 | } | ||
137 | fence = &array->base; | ||
138 | } | ||
139 | |||
140 | cb = kmalloc(sizeof(*cb), GFP_KERNEL); | ||
141 | if (!cb) { | ||
142 | /* Last resort when we are OOM */ | ||
143 | dma_fence_wait(fence, false); | ||
144 | dma_fence_put(fence); | ||
145 | amdgpu_pasid_free(pasid); | ||
146 | } else { | ||
147 | cb->pasid = pasid; | ||
148 | if (dma_fence_add_callback(fence, &cb->cb, | ||
149 | amdgpu_pasid_free_cb)) | ||
150 | amdgpu_pasid_free_cb(fence, &cb->cb); | ||
151 | } | ||
152 | |||
153 | return; | ||
154 | |||
155 | fallback: | ||
156 | /* Not enough memory for the delayed delete, as last resort | ||
157 | * block for all the fences to complete. | ||
158 | */ | ||
159 | reservation_object_wait_timeout_rcu(resv, true, false, | ||
160 | MAX_SCHEDULE_TIMEOUT); | ||
161 | amdgpu_pasid_free(pasid); | ||
162 | } | ||
163 | |||
78 | /* | 164 | /* |
79 | * VMID manager | 165 | * VMID manager |
80 | * | 166 | * |
@@ -96,164 +182,185 @@ bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev, | |||
96 | atomic_read(&adev->gpu_reset_counter); | 182 | atomic_read(&adev->gpu_reset_counter); |
97 | } | 183 | } |
98 | 184 | ||
99 | /* idr_mgr->lock must be held */ | ||
100 | static int amdgpu_vmid_grab_reserved_locked(struct amdgpu_vm *vm, | ||
101 | struct amdgpu_ring *ring, | ||
102 | struct amdgpu_sync *sync, | ||
103 | struct dma_fence *fence, | ||
104 | struct amdgpu_job *job) | ||
105 | { | ||
106 | struct amdgpu_device *adev = ring->adev; | ||
107 | unsigned vmhub = ring->funcs->vmhub; | ||
108 | uint64_t fence_context = adev->fence_context + ring->idx; | ||
109 | struct amdgpu_vmid *id = vm->reserved_vmid[vmhub]; | ||
110 | struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; | ||
111 | struct dma_fence *updates = sync->last_vm_update; | ||
112 | int r = 0; | ||
113 | struct dma_fence *flushed, *tmp; | ||
114 | bool needs_flush = vm->use_cpu_for_update; | ||
115 | |||
116 | flushed = id->flushed_updates; | ||
117 | if ((amdgpu_vmid_had_gpu_reset(adev, id)) || | ||
118 | (atomic64_read(&id->owner) != vm->entity.fence_context) || | ||
119 | (job->vm_pd_addr != id->pd_gpu_addr) || | ||
120 | (updates && (!flushed || updates->context != flushed->context || | ||
121 | dma_fence_is_later(updates, flushed))) || | ||
122 | (!id->last_flush || (id->last_flush->context != fence_context && | ||
123 | !dma_fence_is_signaled(id->last_flush)))) { | ||
124 | needs_flush = true; | ||
125 | /* to prevent one context starved by another context */ | ||
126 | id->pd_gpu_addr = 0; | ||
127 | tmp = amdgpu_sync_peek_fence(&id->active, ring); | ||
128 | if (tmp) { | ||
129 | r = amdgpu_sync_fence(adev, sync, tmp, false); | ||
130 | return r; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /* Good we can use this VMID. Remember this submission as | ||
135 | * user of the VMID. | ||
136 | */ | ||
137 | r = amdgpu_sync_fence(ring->adev, &id->active, fence, false); | ||
138 | if (r) | ||
139 | goto out; | ||
140 | |||
141 | if (updates && (!flushed || updates->context != flushed->context || | ||
142 | dma_fence_is_later(updates, flushed))) { | ||
143 | dma_fence_put(id->flushed_updates); | ||
144 | id->flushed_updates = dma_fence_get(updates); | ||
145 | } | ||
146 | id->pd_gpu_addr = job->vm_pd_addr; | ||
147 | atomic64_set(&id->owner, vm->entity.fence_context); | ||
148 | job->vm_needs_flush = needs_flush; | ||
149 | if (needs_flush) { | ||
150 | dma_fence_put(id->last_flush); | ||
151 | id->last_flush = NULL; | ||
152 | } | ||
153 | job->vmid = id - id_mgr->ids; | ||
154 | trace_amdgpu_vm_grab_id(vm, ring, job); | ||
155 | out: | ||
156 | return r; | ||
157 | } | ||
158 | |||
159 | /** | 185 | /** |
160 | * amdgpu_vm_grab_id - allocate the next free VMID | 186 | * amdgpu_vm_grab_idle - grab idle VMID |
161 | * | 187 | * |
162 | * @vm: vm to allocate id for | 188 | * @vm: vm to allocate id for |
163 | * @ring: ring we want to submit job to | 189 | * @ring: ring we want to submit job to |
164 | * @sync: sync object where we add dependencies | 190 | * @sync: sync object where we add dependencies |
165 | * @fence: fence protecting ID from reuse | 191 | * @idle: resulting idle VMID |
166 | * | 192 | * |
167 | * Allocate an id for the vm, adding fences to the sync obj as necessary. | 193 | * Try to find an idle VMID, if none is idle add a fence to wait to the sync |
194 | * object. Returns -ENOMEM when we are out of memory. | ||
168 | */ | 195 | */ |
169 | int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring, | 196 | static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm, |
170 | struct amdgpu_sync *sync, struct dma_fence *fence, | 197 | struct amdgpu_ring *ring, |
171 | struct amdgpu_job *job) | 198 | struct amdgpu_sync *sync, |
199 | struct amdgpu_vmid **idle) | ||
172 | { | 200 | { |
173 | struct amdgpu_device *adev = ring->adev; | 201 | struct amdgpu_device *adev = ring->adev; |
174 | unsigned vmhub = ring->funcs->vmhub; | 202 | unsigned vmhub = ring->funcs->vmhub; |
175 | struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; | 203 | struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; |
176 | uint64_t fence_context = adev->fence_context + ring->idx; | ||
177 | struct dma_fence *updates = sync->last_vm_update; | ||
178 | struct amdgpu_vmid *id, *idle; | ||
179 | struct dma_fence **fences; | 204 | struct dma_fence **fences; |
180 | unsigned i; | 205 | unsigned i; |
181 | int r = 0; | 206 | int r; |
207 | |||
208 | if (ring->vmid_wait && !dma_fence_is_signaled(ring->vmid_wait)) | ||
209 | return amdgpu_sync_fence(adev, sync, ring->vmid_wait, false); | ||
182 | 210 | ||
183 | mutex_lock(&id_mgr->lock); | ||
184 | if (vm->reserved_vmid[vmhub]) { | ||
185 | r = amdgpu_vmid_grab_reserved_locked(vm, ring, sync, fence, job); | ||
186 | mutex_unlock(&id_mgr->lock); | ||
187 | return r; | ||
188 | } | ||
189 | fences = kmalloc_array(sizeof(void *), id_mgr->num_ids, GFP_KERNEL); | 211 | fences = kmalloc_array(sizeof(void *), id_mgr->num_ids, GFP_KERNEL); |
190 | if (!fences) { | 212 | if (!fences) |
191 | mutex_unlock(&id_mgr->lock); | ||
192 | return -ENOMEM; | 213 | return -ENOMEM; |
193 | } | 214 | |
194 | /* Check if we have an idle VMID */ | 215 | /* Check if we have an idle VMID */ |
195 | i = 0; | 216 | i = 0; |
196 | list_for_each_entry(idle, &id_mgr->ids_lru, list) { | 217 | list_for_each_entry((*idle), &id_mgr->ids_lru, list) { |
197 | fences[i] = amdgpu_sync_peek_fence(&idle->active, ring); | 218 | fences[i] = amdgpu_sync_peek_fence(&(*idle)->active, ring); |
198 | if (!fences[i]) | 219 | if (!fences[i]) |
199 | break; | 220 | break; |
200 | ++i; | 221 | ++i; |
201 | } | 222 | } |
202 | 223 | ||
203 | /* If we can't find a idle VMID to use, wait till one becomes available */ | 224 | /* If we can't find a idle VMID to use, wait till one becomes available */ |
204 | if (&idle->list == &id_mgr->ids_lru) { | 225 | if (&(*idle)->list == &id_mgr->ids_lru) { |
205 | u64 fence_context = adev->vm_manager.fence_context + ring->idx; | 226 | u64 fence_context = adev->vm_manager.fence_context + ring->idx; |
206 | unsigned seqno = ++adev->vm_manager.seqno[ring->idx]; | 227 | unsigned seqno = ++adev->vm_manager.seqno[ring->idx]; |
207 | struct dma_fence_array *array; | 228 | struct dma_fence_array *array; |
208 | unsigned j; | 229 | unsigned j; |
209 | 230 | ||
231 | *idle = NULL; | ||
210 | for (j = 0; j < i; ++j) | 232 | for (j = 0; j < i; ++j) |
211 | dma_fence_get(fences[j]); | 233 | dma_fence_get(fences[j]); |
212 | 234 | ||
213 | array = dma_fence_array_create(i, fences, fence_context, | 235 | array = dma_fence_array_create(i, fences, fence_context, |
214 | seqno, true); | 236 | seqno, true); |
215 | if (!array) { | 237 | if (!array) { |
216 | for (j = 0; j < i; ++j) | 238 | for (j = 0; j < i; ++j) |
217 | dma_fence_put(fences[j]); | 239 | dma_fence_put(fences[j]); |
218 | kfree(fences); | 240 | kfree(fences); |
219 | r = -ENOMEM; | 241 | return -ENOMEM; |
220 | goto error; | ||
221 | } | 242 | } |
222 | 243 | ||
244 | r = amdgpu_sync_fence(adev, sync, &array->base, false); | ||
245 | dma_fence_put(ring->vmid_wait); | ||
246 | ring->vmid_wait = &array->base; | ||
247 | return r; | ||
248 | } | ||
249 | kfree(fences); | ||
223 | 250 | ||
224 | r = amdgpu_sync_fence(ring->adev, sync, &array->base, false); | 251 | return 0; |
225 | dma_fence_put(&array->base); | 252 | } |
226 | if (r) | ||
227 | goto error; | ||
228 | 253 | ||
229 | mutex_unlock(&id_mgr->lock); | 254 | /** |
230 | return 0; | 255 | * amdgpu_vm_grab_reserved - try to assign reserved VMID |
256 | * | ||
257 | * @vm: vm to allocate id for | ||
258 | * @ring: ring we want to submit job to | ||
259 | * @sync: sync object where we add dependencies | ||
260 | * @fence: fence protecting ID from reuse | ||
261 | * @job: job who wants to use the VMID | ||
262 | * | ||
263 | * Try to assign a reserved VMID. | ||
264 | */ | ||
265 | static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm, | ||
266 | struct amdgpu_ring *ring, | ||
267 | struct amdgpu_sync *sync, | ||
268 | struct dma_fence *fence, | ||
269 | struct amdgpu_job *job, | ||
270 | struct amdgpu_vmid **id) | ||
271 | { | ||
272 | struct amdgpu_device *adev = ring->adev; | ||
273 | unsigned vmhub = ring->funcs->vmhub; | ||
274 | uint64_t fence_context = adev->fence_context + ring->idx; | ||
275 | struct dma_fence *updates = sync->last_vm_update; | ||
276 | bool needs_flush = vm->use_cpu_for_update; | ||
277 | int r = 0; | ||
278 | |||
279 | *id = vm->reserved_vmid[vmhub]; | ||
280 | if (updates && (*id)->flushed_updates && | ||
281 | updates->context == (*id)->flushed_updates->context && | ||
282 | !dma_fence_is_later(updates, (*id)->flushed_updates)) | ||
283 | updates = NULL; | ||
284 | |||
285 | if ((*id)->owner != vm->entity.fence_context || | ||
286 | job->vm_pd_addr != (*id)->pd_gpu_addr || | ||
287 | updates || !(*id)->last_flush || | ||
288 | ((*id)->last_flush->context != fence_context && | ||
289 | !dma_fence_is_signaled((*id)->last_flush))) { | ||
290 | struct dma_fence *tmp; | ||
231 | 291 | ||
292 | /* to prevent one context starved by another context */ | ||
293 | (*id)->pd_gpu_addr = 0; | ||
294 | tmp = amdgpu_sync_peek_fence(&(*id)->active, ring); | ||
295 | if (tmp) { | ||
296 | *id = NULL; | ||
297 | r = amdgpu_sync_fence(adev, sync, tmp, false); | ||
298 | return r; | ||
299 | } | ||
300 | needs_flush = true; | ||
232 | } | 301 | } |
233 | kfree(fences); | 302 | |
303 | /* Good we can use this VMID. Remember this submission as | ||
304 | * user of the VMID. | ||
305 | */ | ||
306 | r = amdgpu_sync_fence(ring->adev, &(*id)->active, fence, false); | ||
307 | if (r) | ||
308 | return r; | ||
309 | |||
310 | if (updates) { | ||
311 | dma_fence_put((*id)->flushed_updates); | ||
312 | (*id)->flushed_updates = dma_fence_get(updates); | ||
313 | } | ||
314 | job->vm_needs_flush = needs_flush; | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | /** | ||
319 | * amdgpu_vm_grab_used - try to reuse a VMID | ||
320 | * | ||
321 | * @vm: vm to allocate id for | ||
322 | * @ring: ring we want to submit job to | ||
323 | * @sync: sync object where we add dependencies | ||
324 | * @fence: fence protecting ID from reuse | ||
325 | * @job: job who wants to use the VMID | ||
326 | * @id: resulting VMID | ||
327 | * | ||
328 | * Try to reuse a VMID for this submission. | ||
329 | */ | ||
330 | static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm, | ||
331 | struct amdgpu_ring *ring, | ||
332 | struct amdgpu_sync *sync, | ||
333 | struct dma_fence *fence, | ||
334 | struct amdgpu_job *job, | ||
335 | struct amdgpu_vmid **id) | ||
336 | { | ||
337 | struct amdgpu_device *adev = ring->adev; | ||
338 | unsigned vmhub = ring->funcs->vmhub; | ||
339 | struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; | ||
340 | uint64_t fence_context = adev->fence_context + ring->idx; | ||
341 | struct dma_fence *updates = sync->last_vm_update; | ||
342 | int r; | ||
234 | 343 | ||
235 | job->vm_needs_flush = vm->use_cpu_for_update; | 344 | job->vm_needs_flush = vm->use_cpu_for_update; |
345 | |||
236 | /* Check if we can use a VMID already assigned to this VM */ | 346 | /* Check if we can use a VMID already assigned to this VM */ |
237 | list_for_each_entry_reverse(id, &id_mgr->ids_lru, list) { | 347 | list_for_each_entry_reverse((*id), &id_mgr->ids_lru, list) { |
238 | struct dma_fence *flushed; | ||
239 | bool needs_flush = vm->use_cpu_for_update; | 348 | bool needs_flush = vm->use_cpu_for_update; |
349 | struct dma_fence *flushed; | ||
240 | 350 | ||
241 | /* Check all the prerequisites to using this VMID */ | 351 | /* Check all the prerequisites to using this VMID */ |
242 | if (amdgpu_vmid_had_gpu_reset(adev, id)) | 352 | if ((*id)->owner != vm->entity.fence_context) |
243 | continue; | ||
244 | |||
245 | if (atomic64_read(&id->owner) != vm->entity.fence_context) | ||
246 | continue; | 353 | continue; |
247 | 354 | ||
248 | if (job->vm_pd_addr != id->pd_gpu_addr) | 355 | if ((*id)->pd_gpu_addr != job->vm_pd_addr) |
249 | continue; | 356 | continue; |
250 | 357 | ||
251 | if (!id->last_flush || | 358 | if (!(*id)->last_flush || |
252 | (id->last_flush->context != fence_context && | 359 | ((*id)->last_flush->context != fence_context && |
253 | !dma_fence_is_signaled(id->last_flush))) | 360 | !dma_fence_is_signaled((*id)->last_flush))) |
254 | needs_flush = true; | 361 | needs_flush = true; |
255 | 362 | ||
256 | flushed = id->flushed_updates; | 363 | flushed = (*id)->flushed_updates; |
257 | if (updates && (!flushed || dma_fence_is_later(updates, flushed))) | 364 | if (updates && (!flushed || dma_fence_is_later(updates, flushed))) |
258 | needs_flush = true; | 365 | needs_flush = true; |
259 | 366 | ||
@@ -261,47 +368,91 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring, | |||
261 | if (adev->asic_type < CHIP_VEGA10 && needs_flush) | 368 | if (adev->asic_type < CHIP_VEGA10 && needs_flush) |
262 | continue; | 369 | continue; |
263 | 370 | ||
264 | /* Good we can use this VMID. Remember this submission as | 371 | /* Good, we can use this VMID. Remember this submission as |
265 | * user of the VMID. | 372 | * user of the VMID. |
266 | */ | 373 | */ |
267 | r = amdgpu_sync_fence(ring->adev, &id->active, fence, false); | 374 | r = amdgpu_sync_fence(ring->adev, &(*id)->active, fence, false); |
268 | if (r) | 375 | if (r) |
269 | goto error; | 376 | return r; |
270 | 377 | ||
271 | if (updates && (!flushed || dma_fence_is_later(updates, flushed))) { | 378 | if (updates && (!flushed || dma_fence_is_later(updates, flushed))) { |
272 | dma_fence_put(id->flushed_updates); | 379 | dma_fence_put((*id)->flushed_updates); |
273 | id->flushed_updates = dma_fence_get(updates); | 380 | (*id)->flushed_updates = dma_fence_get(updates); |
274 | } | 381 | } |
275 | 382 | ||
276 | if (needs_flush) | 383 | job->vm_needs_flush |= needs_flush; |
277 | goto needs_flush; | 384 | return 0; |
278 | else | 385 | } |
279 | goto no_flush_needed; | ||
280 | 386 | ||
281 | }; | 387 | *id = NULL; |
388 | return 0; | ||
389 | } | ||
282 | 390 | ||
283 | /* Still no ID to use? Then use the idle one found earlier */ | 391 | /** |
284 | id = idle; | 392 | * amdgpu_vm_grab_id - allocate the next free VMID |
393 | * | ||
394 | * @vm: vm to allocate id for | ||
395 | * @ring: ring we want to submit job to | ||
396 | * @sync: sync object where we add dependencies | ||
397 | * @fence: fence protecting ID from reuse | ||
398 | * @job: job who wants to use the VMID | ||
399 | * | ||
400 | * Allocate an id for the vm, adding fences to the sync obj as necessary. | ||
401 | */ | ||
402 | int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring, | ||
403 | struct amdgpu_sync *sync, struct dma_fence *fence, | ||
404 | struct amdgpu_job *job) | ||
405 | { | ||
406 | struct amdgpu_device *adev = ring->adev; | ||
407 | unsigned vmhub = ring->funcs->vmhub; | ||
408 | struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; | ||
409 | struct amdgpu_vmid *idle = NULL; | ||
410 | struct amdgpu_vmid *id = NULL; | ||
411 | int r = 0; | ||
285 | 412 | ||
286 | /* Remember this submission as user of the VMID */ | 413 | mutex_lock(&id_mgr->lock); |
287 | r = amdgpu_sync_fence(ring->adev, &id->active, fence, false); | 414 | r = amdgpu_vmid_grab_idle(vm, ring, sync, &idle); |
288 | if (r) | 415 | if (r || !idle) |
289 | goto error; | 416 | goto error; |
290 | 417 | ||
291 | id->pd_gpu_addr = job->vm_pd_addr; | 418 | if (vm->reserved_vmid[vmhub]) { |
292 | dma_fence_put(id->flushed_updates); | 419 | r = amdgpu_vmid_grab_reserved(vm, ring, sync, fence, job, &id); |
293 | id->flushed_updates = dma_fence_get(updates); | 420 | if (r || !id) |
294 | atomic64_set(&id->owner, vm->entity.fence_context); | 421 | goto error; |
422 | } else { | ||
423 | r = amdgpu_vmid_grab_used(vm, ring, sync, fence, job, &id); | ||
424 | if (r) | ||
425 | goto error; | ||
295 | 426 | ||
296 | needs_flush: | 427 | if (!id) { |
297 | job->vm_needs_flush = true; | 428 | struct dma_fence *updates = sync->last_vm_update; |
298 | dma_fence_put(id->last_flush); | ||
299 | id->last_flush = NULL; | ||
300 | 429 | ||
301 | no_flush_needed: | 430 | /* Still no ID to use? Then use the idle one found earlier */ |
302 | list_move_tail(&id->list, &id_mgr->ids_lru); | 431 | id = idle; |
303 | 432 | ||
433 | /* Remember this submission as user of the VMID */ | ||
434 | r = amdgpu_sync_fence(ring->adev, &id->active, | ||
435 | fence, false); | ||
436 | if (r) | ||
437 | goto error; | ||
438 | |||
439 | dma_fence_put(id->flushed_updates); | ||
440 | id->flushed_updates = dma_fence_get(updates); | ||
441 | job->vm_needs_flush = true; | ||
442 | } | ||
443 | |||
444 | list_move_tail(&id->list, &id_mgr->ids_lru); | ||
445 | } | ||
446 | |||
447 | id->pd_gpu_addr = job->vm_pd_addr; | ||
448 | id->owner = vm->entity.fence_context; | ||
449 | |||
450 | if (job->vm_needs_flush) { | ||
451 | dma_fence_put(id->last_flush); | ||
452 | id->last_flush = NULL; | ||
453 | } | ||
304 | job->vmid = id - id_mgr->ids; | 454 | job->vmid = id - id_mgr->ids; |
455 | job->pasid = vm->pasid; | ||
305 | trace_amdgpu_vm_grab_id(vm, ring, job); | 456 | trace_amdgpu_vm_grab_id(vm, ring, job); |
306 | 457 | ||
307 | error: | 458 | error: |
@@ -370,13 +521,15 @@ void amdgpu_vmid_reset(struct amdgpu_device *adev, unsigned vmhub, | |||
370 | struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; | 521 | struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; |
371 | struct amdgpu_vmid *id = &id_mgr->ids[vmid]; | 522 | struct amdgpu_vmid *id = &id_mgr->ids[vmid]; |
372 | 523 | ||
373 | atomic64_set(&id->owner, 0); | 524 | mutex_lock(&id_mgr->lock); |
525 | id->owner = 0; | ||
374 | id->gds_base = 0; | 526 | id->gds_base = 0; |
375 | id->gds_size = 0; | 527 | id->gds_size = 0; |
376 | id->gws_base = 0; | 528 | id->gws_base = 0; |
377 | id->gws_size = 0; | 529 | id->gws_size = 0; |
378 | id->oa_base = 0; | 530 | id->oa_base = 0; |
379 | id->oa_size = 0; | 531 | id->oa_size = 0; |
532 | mutex_unlock(&id_mgr->lock); | ||
380 | } | 533 | } |
381 | 534 | ||
382 | /** | 535 | /** |
@@ -454,6 +607,7 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev) | |||
454 | amdgpu_sync_free(&id->active); | 607 | amdgpu_sync_free(&id->active); |
455 | dma_fence_put(id->flushed_updates); | 608 | dma_fence_put(id->flushed_updates); |
456 | dma_fence_put(id->last_flush); | 609 | dma_fence_put(id->last_flush); |
610 | dma_fence_put(id->pasid_mapping); | ||
457 | } | 611 | } |
458 | } | 612 | } |
459 | } | 613 | } |