Commit ad1a58a4 authored by Christian König's avatar Christian König Committed by Alex Deucher

drm/radeon: track VM update fences separately

Note for each fence if it's a VM page table update or not. This allows
us to determine the last VM update in a sync object and so to figure
out if we need to flush the TLB or not.
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 587cdda8
...@@ -360,14 +360,15 @@ struct radeon_fence_driver { ...@@ -360,14 +360,15 @@ struct radeon_fence_driver {
}; };
struct radeon_fence { struct radeon_fence {
struct fence base; struct fence base;
struct radeon_device *rdev; struct radeon_device *rdev;
uint64_t seq; uint64_t seq;
/* RB, DMA, etc. */ /* RB, DMA, etc. */
unsigned ring; unsigned ring;
bool is_vm_update;
wait_queue_t fence_wake; wait_queue_t fence_wake;
}; };
int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
...@@ -594,6 +595,7 @@ void radeon_semaphore_free(struct radeon_device *rdev, ...@@ -594,6 +595,7 @@ void radeon_semaphore_free(struct radeon_device *rdev,
struct radeon_sync { struct radeon_sync {
struct radeon_semaphore *semaphores[RADEON_NUM_SYNCS]; struct radeon_semaphore *semaphores[RADEON_NUM_SYNCS];
struct radeon_fence *sync_to[RADEON_NUM_RINGS]; struct radeon_fence *sync_to[RADEON_NUM_RINGS];
struct radeon_fence *last_vm_update;
}; };
void radeon_sync_create(struct radeon_sync *sync); void radeon_sync_create(struct radeon_sync *sync);
...@@ -926,8 +928,8 @@ struct radeon_vm { ...@@ -926,8 +928,8 @@ struct radeon_vm {
struct mutex mutex; struct mutex mutex;
/* last fence for cs using this vm */ /* last fence for cs using this vm */
struct radeon_fence *fence; struct radeon_fence *fence;
/* last flush or NULL if we still need to flush */ /* last flushed PD/PT update */
struct radeon_fence *last_flush; struct radeon_fence *flushed_updates;
/* last use of vmid */ /* last use of vmid */
struct radeon_fence *last_id_use; struct radeon_fence *last_id_use;
}; };
...@@ -2975,7 +2977,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, ...@@ -2975,7 +2977,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
struct radeon_vm *vm, int ring); struct radeon_vm *vm, int ring);
void radeon_vm_flush(struct radeon_device *rdev, void radeon_vm_flush(struct radeon_device *rdev,
struct radeon_vm *vm, struct radeon_vm *vm,
int ring); int ring, struct radeon_fence *fence);
void radeon_vm_fence(struct radeon_device *rdev, void radeon_vm_fence(struct radeon_device *rdev,
struct radeon_vm *vm, struct radeon_vm *vm,
struct radeon_fence *fence); struct radeon_fence *fence);
......
...@@ -140,6 +140,7 @@ int radeon_fence_emit(struct radeon_device *rdev, ...@@ -140,6 +140,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
(*fence)->rdev = rdev; (*fence)->rdev = rdev;
(*fence)->seq = seq; (*fence)->seq = seq;
(*fence)->ring = ring; (*fence)->ring = ring;
(*fence)->is_vm_update = false;
fence_init(&(*fence)->base, &radeon_fence_ops, fence_init(&(*fence)->base, &radeon_fence_ops,
&rdev->fence_queue.lock, rdev->fence_context + ring, seq); &rdev->fence_queue.lock, rdev->fence_context + ring, seq);
radeon_fence_ring_emit(rdev, ring, *fence); radeon_fence_ring_emit(rdev, ring, *fence);
......
...@@ -154,7 +154,8 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, ...@@ -154,7 +154,8 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
} }
if (ib->vm) if (ib->vm)
radeon_vm_flush(rdev, ib->vm, ib->ring); radeon_vm_flush(rdev, ib->vm, ib->ring,
ib->sync.last_vm_update);
if (const_ib) { if (const_ib) {
radeon_ring_ib_execute(rdev, const_ib->ring, const_ib); radeon_ring_ib_execute(rdev, const_ib->ring, const_ib);
......
...@@ -48,6 +48,8 @@ void radeon_sync_create(struct radeon_sync *sync) ...@@ -48,6 +48,8 @@ void radeon_sync_create(struct radeon_sync *sync)
for (i = 0; i < RADEON_NUM_RINGS; ++i) for (i = 0; i < RADEON_NUM_RINGS; ++i)
sync->sync_to[i] = NULL; sync->sync_to[i] = NULL;
sync->last_vm_update = NULL;
} }
/** /**
...@@ -68,6 +70,11 @@ void radeon_sync_fence(struct radeon_sync *sync, ...@@ -68,6 +70,11 @@ void radeon_sync_fence(struct radeon_sync *sync,
other = sync->sync_to[fence->ring]; other = sync->sync_to[fence->ring];
sync->sync_to[fence->ring] = radeon_fence_later(fence, other); sync->sync_to[fence->ring] = radeon_fence_later(fence, other);
if (fence->is_vm_update) {
other = sync->last_vm_update;
sync->last_vm_update = radeon_fence_later(fence, other);
}
} }
/** /**
......
...@@ -190,7 +190,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, ...@@ -190,7 +190,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
return NULL; return NULL;
/* we definately need to flush */ /* we definately need to flush */
radeon_fence_unref(&vm->last_flush); vm->pd_gpu_addr = ~0ll;
/* skip over VMID 0, since it is the system VM */ /* skip over VMID 0, since it is the system VM */
for (i = 1; i < rdev->vm_manager.nvm; ++i) { for (i = 1; i < rdev->vm_manager.nvm; ++i) {
...@@ -228,6 +228,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, ...@@ -228,6 +228,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
* @rdev: radeon_device pointer * @rdev: radeon_device pointer
* @vm: vm we want to flush * @vm: vm we want to flush
* @ring: ring to use for flush * @ring: ring to use for flush
* @updates: last vm update that is waited for
* *
* Flush the vm (cayman+). * Flush the vm (cayman+).
* *
...@@ -235,13 +236,16 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, ...@@ -235,13 +236,16 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
*/ */
void radeon_vm_flush(struct radeon_device *rdev, void radeon_vm_flush(struct radeon_device *rdev,
struct radeon_vm *vm, struct radeon_vm *vm,
int ring) int ring, struct radeon_fence *updates)
{ {
uint64_t pd_addr = radeon_bo_gpu_offset(vm->page_directory); uint64_t pd_addr = radeon_bo_gpu_offset(vm->page_directory);
/* if we can't remember our last VM flush then flush now! */ if (pd_addr != vm->pd_gpu_addr || !vm->flushed_updates ||
if (!vm->last_flush || pd_addr != vm->pd_gpu_addr) { radeon_fence_is_earlier(vm->flushed_updates, updates)) {
trace_radeon_vm_flush(pd_addr, ring, vm->id); trace_radeon_vm_flush(pd_addr, ring, vm->id);
radeon_fence_unref(&vm->flushed_updates);
vm->flushed_updates = radeon_fence_ref(updates);
vm->pd_gpu_addr = pd_addr; vm->pd_gpu_addr = pd_addr;
radeon_ring_vm_flush(rdev, &rdev->ring[ring], radeon_ring_vm_flush(rdev, &rdev->ring[ring],
vm->id, vm->pd_gpu_addr); vm->id, vm->pd_gpu_addr);
...@@ -272,10 +276,6 @@ void radeon_vm_fence(struct radeon_device *rdev, ...@@ -272,10 +276,6 @@ void radeon_vm_fence(struct radeon_device *rdev,
radeon_fence_unref(&vm->last_id_use); radeon_fence_unref(&vm->last_id_use);
vm->last_id_use = radeon_fence_ref(fence); vm->last_id_use = radeon_fence_ref(fence);
/* we just flushed the VM, remember that */
if (!vm->last_flush)
vm->last_flush = radeon_fence_ref(fence);
} }
/** /**
...@@ -418,6 +418,7 @@ static int radeon_vm_clear_bo(struct radeon_device *rdev, ...@@ -418,6 +418,7 @@ static int radeon_vm_clear_bo(struct radeon_device *rdev,
if (r) if (r)
goto error_free; goto error_free;
ib.fence->is_vm_update = true;
radeon_bo_fence(bo, ib.fence, false); radeon_bo_fence(bo, ib.fence, false);
error_free: error_free:
...@@ -697,10 +698,10 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev, ...@@ -697,10 +698,10 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
radeon_ib_free(rdev, &ib); radeon_ib_free(rdev, &ib);
return r; return r;
} }
ib.fence->is_vm_update = true;
radeon_bo_fence(pd, ib.fence, false); radeon_bo_fence(pd, ib.fence, false);
radeon_fence_unref(&vm->fence); radeon_fence_unref(&vm->fence);
vm->fence = radeon_fence_ref(ib.fence); vm->fence = radeon_fence_ref(ib.fence);
radeon_fence_unref(&vm->last_flush);
} }
radeon_ib_free(rdev, &ib); radeon_ib_free(rdev, &ib);
...@@ -989,11 +990,11 @@ int radeon_vm_bo_update(struct radeon_device *rdev, ...@@ -989,11 +990,11 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
radeon_ib_free(rdev, &ib); radeon_ib_free(rdev, &ib);
return r; return r;
} }
ib.fence->is_vm_update = true;
radeon_vm_fence_pts(vm, bo_va->it.start, bo_va->it.last + 1, ib.fence); radeon_vm_fence_pts(vm, bo_va->it.start, bo_va->it.last + 1, ib.fence);
radeon_fence_unref(&vm->fence); radeon_fence_unref(&vm->fence);
vm->fence = radeon_fence_ref(ib.fence); vm->fence = radeon_fence_ref(ib.fence);
radeon_ib_free(rdev, &ib); radeon_ib_free(rdev, &ib);
radeon_fence_unref(&vm->last_flush);
return 0; return 0;
} }
...@@ -1124,7 +1125,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) ...@@ -1124,7 +1125,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
vm->id = 0; vm->id = 0;
vm->ib_bo_va = NULL; vm->ib_bo_va = NULL;
vm->fence = NULL; vm->fence = NULL;
vm->last_flush = NULL; vm->flushed_updates = NULL;
vm->last_id_use = NULL; vm->last_id_use = NULL;
mutex_init(&vm->mutex); mutex_init(&vm->mutex);
vm->va = RB_ROOT; vm->va = RB_ROOT;
...@@ -1196,7 +1197,7 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) ...@@ -1196,7 +1197,7 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
radeon_bo_unref(&vm->page_directory); radeon_bo_unref(&vm->page_directory);
radeon_fence_unref(&vm->fence); radeon_fence_unref(&vm->fence);
radeon_fence_unref(&vm->last_flush); radeon_fence_unref(&vm->flushed_updates);
radeon_fence_unref(&vm->last_id_use); radeon_fence_unref(&vm->last_id_use);
mutex_destroy(&vm->mutex); mutex_destroy(&vm->mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment