Skip to content

Commit 0be6873

Browse files
ChristianKoenigAMDheftig
authored andcommitted
drm/amdgpu: avoid memory allocation in the critical code path v3
When we run out of VMIDs we need to wait for some to become available. Previously we were using a dma_fence_array for that, but this means that we have to allocate memory. Instead just wait for the first not signaled fence from the least recently used VMID to signal. That is not as efficient since we end up in this function multiple times again, but allocating memory can easily fail or deadlock if we have to wait for memory to become available. v2: remove now unused VM manager fields v3: fix dma_fence reference Signed-off-by: Christian König <christian.koenig@amd.com> Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4258 Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cherry-picked-for: https://gitlab.archlinux.org/archlinux/packaging/packages/linux/-/issues/164
1 parent ce2ae46 commit 0be6873

File tree

3 files changed

+14
-49
lines changed

3 files changed

+14
-49
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c

Lines changed: 14 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -201,58 +201,34 @@ static int amdgpu_vmid_grab_idle(struct amdgpu_ring *ring,
201201
struct amdgpu_device *adev = ring->adev;
202202
unsigned vmhub = ring->vm_hub;
203203
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
204-
struct dma_fence **fences;
205-
unsigned i;
206204

205+
/* If anybody is waiting for a VMID let everybody wait for fairness */
207206
if (!dma_fence_is_signaled(ring->vmid_wait)) {
208207
*fence = dma_fence_get(ring->vmid_wait);
209208
return 0;
210209
}
211210

212-
fences = kmalloc_array(id_mgr->num_ids, sizeof(void *), GFP_NOWAIT);
213-
if (!fences)
214-
return -ENOMEM;
215-
216211
/* Check if we have an idle VMID */
217-
i = 0;
218-
list_for_each_entry((*idle), &id_mgr->ids_lru, list) {
212+
list_for_each_entry_reverse((*idle), &id_mgr->ids_lru, list) {
219213
/* Don't use per engine and per process VMID at the same time */
220214
struct amdgpu_ring *r = adev->vm_manager.concurrent_flush ?
221215
NULL : ring;
222216

223-
fences[i] = amdgpu_sync_peek_fence(&(*idle)->active, r);
224-
if (!fences[i])
225-
break;
226-
++i;
217+
*fence = amdgpu_sync_peek_fence(&(*idle)->active, r);
218+
if (!(*fence))
219+
return 0;
227220
}
228221

229-
/* If we can't find a idle VMID to use, wait till one becomes available */
230-
if (&(*idle)->list == &id_mgr->ids_lru) {
231-
u64 fence_context = adev->vm_manager.fence_context + ring->idx;
232-
unsigned seqno = ++adev->vm_manager.seqno[ring->idx];
233-
struct dma_fence_array *array;
234-
unsigned j;
235-
236-
*idle = NULL;
237-
for (j = 0; j < i; ++j)
238-
dma_fence_get(fences[j]);
239-
240-
array = dma_fence_array_create(i, fences, fence_context,
241-
seqno, true);
242-
if (!array) {
243-
for (j = 0; j < i; ++j)
244-
dma_fence_put(fences[j]);
245-
kfree(fences);
246-
return -ENOMEM;
247-
}
248-
249-
*fence = dma_fence_get(&array->base);
250-
dma_fence_put(ring->vmid_wait);
251-
ring->vmid_wait = &array->base;
252-
return 0;
253-
}
254-
kfree(fences);
222+
/*
223+
* If we can't find a idle VMID to use, wait on a fence from the least
224+
* recently used in the hope that it will be available soon.
225+
*/
226+
*idle = NULL;
227+
dma_fence_put(ring->vmid_wait);
228+
ring->vmid_wait = dma_fence_get(*fence);
255229

230+
/* This is the reference we return */
231+
dma_fence_get(*fence);
256232
return 0;
257233
}
258234

drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2828,8 +2828,6 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
28282828
*/
28292829
void amdgpu_vm_manager_init(struct amdgpu_device *adev)
28302830
{
2831-
unsigned i;
2832-
28332831
/* Concurrent flushes are only possible starting with Vega10 and
28342832
* are broken on Navi10 and Navi14.
28352833
*/
@@ -2838,11 +2836,6 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
28382836
adev->asic_type == CHIP_NAVI14);
28392837
amdgpu_vmid_mgr_init(adev);
28402838

2841-
adev->vm_manager.fence_context =
2842-
dma_fence_context_alloc(AMDGPU_MAX_RINGS);
2843-
for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
2844-
adev->vm_manager.seqno[i] = 0;
2845-
28462839
spin_lock_init(&adev->vm_manager.prt_lock);
28472840
atomic_set(&adev->vm_manager.num_prt_users, 0);
28482841

drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,10 +453,6 @@ struct amdgpu_vm_manager {
453453
unsigned int first_kfd_vmid;
454454
bool concurrent_flush;
455455

456-
/* Handling of VM fences */
457-
u64 fence_context;
458-
unsigned seqno[AMDGPU_MAX_RINGS];
459-
460456
uint64_t max_pfn;
461457
uint32_t num_level;
462458
uint32_t block_size;

0 commit comments

Comments
 (0)