2 * Copyright 2017 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #include "amdgpu_ids.h"
25 #include <linux/idr.h>
26 #include <linux/dma-fence-array.h>
30 #include "amdgpu_trace.h"
35 * PASIDs are global address space identifiers that can be shared
36 * between the GPU, an IOMMU and the driver. VMs on different devices
37 * may use the same PASID if they share the same address
38 * space. Therefore PASIDs are allocated using a global IDA. VMs are
39 * looked up from the PASID per amdgpu_device.
41 static DEFINE_IDA(amdgpu_pasid_ida
);
43 /* Helper to free pasid from a fence callback */
44 struct amdgpu_pasid_cb
{
45 struct dma_fence_cb cb
;
50 * amdgpu_pasid_alloc - Allocate a PASID
51 * @bits: Maximum width of the PASID in bits, must be at least 1
53 * Allocates a PASID of the given width while keeping smaller PASIDs
54 * available if possible.
56 * Returns a positive integer on success. Returns %-EINVAL if bits==0.
57 * Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on
58 * memory allocation failure.
60 int amdgpu_pasid_alloc(unsigned int bits
)
64 for (bits
= min(bits
, 31U); bits
> 0; bits
--) {
65 pasid
= ida_simple_get(&amdgpu_pasid_ida
,
66 1U << (bits
- 1), 1U << bits
,
73 trace_amdgpu_pasid_allocated(pasid
);
79 * amdgpu_pasid_free - Free a PASID
80 * @pasid: PASID to free
82 void amdgpu_pasid_free(unsigned int pasid
)
84 trace_amdgpu_pasid_freed(pasid
);
85 ida_simple_remove(&amdgpu_pasid_ida
, pasid
);
88 static void amdgpu_pasid_free_cb(struct dma_fence
*fence
,
89 struct dma_fence_cb
*_cb
)
91 struct amdgpu_pasid_cb
*cb
=
92 container_of(_cb
, struct amdgpu_pasid_cb
, cb
);
94 amdgpu_pasid_free(cb
->pasid
);
100 * amdgpu_pasid_free_delayed - free pasid when fences signal
102 * @resv: reservation object with the fences to wait for
103 * @pasid: pasid to free
105 * Free the pasid only after all the fences in resv are signaled.
107 void amdgpu_pasid_free_delayed(struct reservation_object
*resv
,
110 struct dma_fence
*fence
, **fences
;
111 struct amdgpu_pasid_cb
*cb
;
115 r
= reservation_object_get_fences_rcu(resv
, NULL
, &count
, &fences
);
120 amdgpu_pasid_free(pasid
);
128 uint64_t context
= dma_fence_context_alloc(1);
129 struct dma_fence_array
*array
;
131 array
= dma_fence_array_create(count
, fences
, context
,
137 fence
= &array
->base
;
140 cb
= kmalloc(sizeof(*cb
), GFP_KERNEL
);
142 /* Last resort when we are OOM */
143 dma_fence_wait(fence
, false);
144 dma_fence_put(fence
);
145 amdgpu_pasid_free(pasid
);
148 if (dma_fence_add_callback(fence
, &cb
->cb
,
149 amdgpu_pasid_free_cb
))
150 amdgpu_pasid_free_cb(fence
, &cb
->cb
);
156 /* Not enough memory for the delayed delete, as last resort
157 * block for all the fences to complete.
159 reservation_object_wait_timeout_rcu(resv
, true, false,
160 MAX_SCHEDULE_TIMEOUT
);
161 amdgpu_pasid_free(pasid
);
167 * VMIDs are a per VMHUB identifier for page tables handling.
171 * amdgpu_vmid_had_gpu_reset - check if reset occured since last use
173 * @adev: amdgpu_device pointer
174 * @id: VMID structure
176 * Check if GPU reset occured since last use of the VMID.
178 bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device
*adev
,
179 struct amdgpu_vmid
*id
)
181 return id
->current_gpu_reset_count
!=
182 atomic_read(&adev
->gpu_reset_counter
);
186 * amdgpu_vm_grab_idle - grab idle VMID
188 * @vm: vm to allocate id for
189 * @ring: ring we want to submit job to
190 * @sync: sync object where we add dependencies
191 * @idle: resulting idle VMID
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.
196 static int amdgpu_vmid_grab_idle(struct amdgpu_vm
*vm
,
197 struct amdgpu_ring
*ring
,
198 struct amdgpu_sync
*sync
,
199 struct amdgpu_vmid
**idle
)
201 struct amdgpu_device
*adev
= ring
->adev
;
202 unsigned vmhub
= ring
->funcs
->vmhub
;
203 struct amdgpu_vmid_mgr
*id_mgr
= &adev
->vm_manager
.id_mgr
[vmhub
];
204 struct dma_fence
**fences
;
208 if (ring
->vmid_wait
&& !dma_fence_is_signaled(ring
->vmid_wait
))
209 return amdgpu_sync_fence(adev
, sync
, ring
->vmid_wait
, false);
211 fences
= kmalloc_array(sizeof(void *), id_mgr
->num_ids
, GFP_KERNEL
);
215 /* Check if we have an idle VMID */
217 list_for_each_entry((*idle
), &id_mgr
->ids_lru
, list
) {
218 fences
[i
] = amdgpu_sync_peek_fence(&(*idle
)->active
, ring
);
224 /* If we can't find a idle VMID to use, wait till one becomes available */
225 if (&(*idle
)->list
== &id_mgr
->ids_lru
) {
226 u64 fence_context
= adev
->vm_manager
.fence_context
+ ring
->idx
;
227 unsigned seqno
= ++adev
->vm_manager
.seqno
[ring
->idx
];
228 struct dma_fence_array
*array
;
232 for (j
= 0; j
< i
; ++j
)
233 dma_fence_get(fences
[j
]);
235 array
= dma_fence_array_create(i
, fences
, fence_context
,
238 for (j
= 0; j
< i
; ++j
)
239 dma_fence_put(fences
[j
]);
244 r
= amdgpu_sync_fence(adev
, sync
, &array
->base
, false);
245 dma_fence_put(ring
->vmid_wait
);
246 ring
->vmid_wait
= &array
->base
;
255 * amdgpu_vm_grab_reserved - try to assign reserved VMID
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
263 * Try to assign a reserved VMID.
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
)
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
;
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
))
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
;
292 /* to prevent one context starved by another context */
293 (*id
)->pd_gpu_addr
= 0;
294 tmp
= amdgpu_sync_peek_fence(&(*id
)->active
, ring
);
297 r
= amdgpu_sync_fence(adev
, sync
, tmp
, false);
303 /* Good we can use this VMID. Remember this submission as
306 r
= amdgpu_sync_fence(ring
->adev
, &(*id
)->active
, fence
, false);
311 dma_fence_put((*id
)->flushed_updates
);
312 (*id
)->flushed_updates
= dma_fence_get(updates
);
314 job
->vm_needs_flush
= needs_flush
;
319 * amdgpu_vm_grab_used - try to reuse a VMID
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
328 * Try to reuse a VMID for this submission.
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
)
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
;
344 job
->vm_needs_flush
= vm
->use_cpu_for_update
;
346 /* Check if we can use a VMID already assigned to this VM */
347 list_for_each_entry_reverse((*id
), &id_mgr
->ids_lru
, list
) {
348 bool needs_flush
= vm
->use_cpu_for_update
;
349 struct dma_fence
*flushed
;
351 /* Check all the prerequisites to using this VMID */
352 if ((*id
)->owner
!= vm
->entity
.fence_context
)
355 if ((*id
)->pd_gpu_addr
!= job
->vm_pd_addr
)
358 if (!(*id
)->last_flush
||
359 ((*id
)->last_flush
->context
!= fence_context
&&
360 !dma_fence_is_signaled((*id
)->last_flush
)))
363 flushed
= (*id
)->flushed_updates
;
364 if (updates
&& (!flushed
|| dma_fence_is_later(updates
, flushed
)))
367 /* Concurrent flushes are only possible starting with Vega10 */
368 if (adev
->asic_type
< CHIP_VEGA10
&& needs_flush
)
371 /* Good, we can use this VMID. Remember this submission as
374 r
= amdgpu_sync_fence(ring
->adev
, &(*id
)->active
, fence
, false);
378 if (updates
&& (!flushed
|| dma_fence_is_later(updates
, flushed
))) {
379 dma_fence_put((*id
)->flushed_updates
);
380 (*id
)->flushed_updates
= dma_fence_get(updates
);
383 job
->vm_needs_flush
|= needs_flush
;
392 * amdgpu_vm_grab_id - allocate the next free VMID
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
400 * Allocate an id for the vm, adding fences to the sync obj as necessary.
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
)
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
;
413 mutex_lock(&id_mgr
->lock
);
414 r
= amdgpu_vmid_grab_idle(vm
, ring
, sync
, &idle
);
418 if (vm
->reserved_vmid
[vmhub
]) {
419 r
= amdgpu_vmid_grab_reserved(vm
, ring
, sync
, fence
, job
, &id
);
423 r
= amdgpu_vmid_grab_used(vm
, ring
, sync
, fence
, job
, &id
);
428 struct dma_fence
*updates
= sync
->last_vm_update
;
430 /* Still no ID to use? Then use the idle one found earlier */
433 /* Remember this submission as user of the VMID */
434 r
= amdgpu_sync_fence(ring
->adev
, &id
->active
,
439 dma_fence_put(id
->flushed_updates
);
440 id
->flushed_updates
= dma_fence_get(updates
);
441 job
->vm_needs_flush
= true;
444 list_move_tail(&id
->list
, &id_mgr
->ids_lru
);
447 id
->pd_gpu_addr
= job
->vm_pd_addr
;
448 id
->owner
= vm
->entity
.fence_context
;
450 if (job
->vm_needs_flush
) {
451 dma_fence_put(id
->last_flush
);
452 id
->last_flush
= NULL
;
454 job
->vmid
= id
- id_mgr
->ids
;
455 job
->pasid
= vm
->pasid
;
456 trace_amdgpu_vm_grab_id(vm
, ring
, job
);
459 mutex_unlock(&id_mgr
->lock
);
463 int amdgpu_vmid_alloc_reserved(struct amdgpu_device
*adev
,
464 struct amdgpu_vm
*vm
,
467 struct amdgpu_vmid_mgr
*id_mgr
;
468 struct amdgpu_vmid
*idle
;
471 id_mgr
= &adev
->vm_manager
.id_mgr
[vmhub
];
472 mutex_lock(&id_mgr
->lock
);
473 if (vm
->reserved_vmid
[vmhub
])
475 if (atomic_inc_return(&id_mgr
->reserved_vmid_num
) >
476 AMDGPU_VM_MAX_RESERVED_VMID
) {
477 DRM_ERROR("Over limitation of reserved vmid\n");
478 atomic_dec(&id_mgr
->reserved_vmid_num
);
482 /* Select the first entry VMID */
483 idle
= list_first_entry(&id_mgr
->ids_lru
, struct amdgpu_vmid
, list
);
484 list_del_init(&idle
->list
);
485 vm
->reserved_vmid
[vmhub
] = idle
;
486 mutex_unlock(&id_mgr
->lock
);
490 mutex_unlock(&id_mgr
->lock
);
494 void amdgpu_vmid_free_reserved(struct amdgpu_device
*adev
,
495 struct amdgpu_vm
*vm
,
498 struct amdgpu_vmid_mgr
*id_mgr
= &adev
->vm_manager
.id_mgr
[vmhub
];
500 mutex_lock(&id_mgr
->lock
);
501 if (vm
->reserved_vmid
[vmhub
]) {
502 list_add(&vm
->reserved_vmid
[vmhub
]->list
,
504 vm
->reserved_vmid
[vmhub
] = NULL
;
505 atomic_dec(&id_mgr
->reserved_vmid_num
);
507 mutex_unlock(&id_mgr
->lock
);
511 * amdgpu_vmid_reset - reset VMID to zero
513 * @adev: amdgpu device structure
514 * @vmid: vmid number to use
516 * Reset saved GDW, GWS and OA to force switch on next flush.
518 void amdgpu_vmid_reset(struct amdgpu_device
*adev
, unsigned vmhub
,
521 struct amdgpu_vmid_mgr
*id_mgr
= &adev
->vm_manager
.id_mgr
[vmhub
];
522 struct amdgpu_vmid
*id
= &id_mgr
->ids
[vmid
];
524 mutex_lock(&id_mgr
->lock
);
532 mutex_unlock(&id_mgr
->lock
);
536 * amdgpu_vmid_reset_all - reset VMID to zero
538 * @adev: amdgpu device structure
540 * Reset VMID to force flush on next use
542 void amdgpu_vmid_reset_all(struct amdgpu_device
*adev
)
546 for (i
= 0; i
< AMDGPU_MAX_VMHUBS
; ++i
) {
547 struct amdgpu_vmid_mgr
*id_mgr
=
548 &adev
->vm_manager
.id_mgr
[i
];
550 for (j
= 1; j
< id_mgr
->num_ids
; ++j
)
551 amdgpu_vmid_reset(adev
, i
, j
);
556 * amdgpu_vmid_mgr_init - init the VMID manager
558 * @adev: amdgpu_device pointer
560 * Initialize the VM manager structures
562 void amdgpu_vmid_mgr_init(struct amdgpu_device
*adev
)
566 for (i
= 0; i
< AMDGPU_MAX_VMHUBS
; ++i
) {
567 struct amdgpu_vmid_mgr
*id_mgr
=
568 &adev
->vm_manager
.id_mgr
[i
];
570 mutex_init(&id_mgr
->lock
);
571 INIT_LIST_HEAD(&id_mgr
->ids_lru
);
572 atomic_set(&id_mgr
->reserved_vmid_num
, 0);
574 /* skip over VMID 0, since it is the system VM */
575 for (j
= 1; j
< id_mgr
->num_ids
; ++j
) {
576 amdgpu_vmid_reset(adev
, i
, j
);
577 amdgpu_sync_create(&id_mgr
->ids
[j
].active
);
578 list_add_tail(&id_mgr
->ids
[j
].list
, &id_mgr
->ids_lru
);
584 * amdgpu_vmid_mgr_fini - cleanup VM manager
586 * @adev: amdgpu_device pointer
588 * Cleanup the VM manager and free resources.
590 void amdgpu_vmid_mgr_fini(struct amdgpu_device
*adev
)
594 for (i
= 0; i
< AMDGPU_MAX_VMHUBS
; ++i
) {
595 struct amdgpu_vmid_mgr
*id_mgr
=
596 &adev
->vm_manager
.id_mgr
[i
];
598 mutex_destroy(&id_mgr
->lock
);
599 for (j
= 0; j
< AMDGPU_NUM_VMID
; ++j
) {
600 struct amdgpu_vmid
*id
= &id_mgr
->ids
[j
];
602 amdgpu_sync_free(&id
->active
);
603 dma_fence_put(id
->flushed_updates
);
604 dma_fence_put(id
->last_flush
);
605 dma_fence_put(id
->pasid_mapping
);