[Intel-xe] [PATCH 3/6] drm/xe: Remove async worker and rework sync binds
Thomas Hellström
thomas.hellstrom at linux.intel.com
Thu Sep 21 09:09:53 UTC 2023
On Thu, 2023-09-14 at 13:40 -0700, Matthew Brost wrote:
> Async worker is gone. All jobs and memory allocations done in IOCTL
> to
> align with dma fencing rules.
>
> Async vs. sync now means when do bind operations complete relative to
> the IOCTL. Async completes when out-syncs signal while sync completes
> when the IOCTL returns. In-syncs and out-syncs are only allowed in
> async
> mode.
>
> If memory allocations fail in the job creation step the VM is killed.
> This is temporary, eventually a proper unwind will be done and VM
> will
> be usable.
>
> Signed-off-by: Matthew Brost <mattthew.brost at intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom at linux.intel.com>
> ---
> drivers/gpu/drm/xe/xe_exec.c | 43 --
> drivers/gpu/drm/xe/xe_exec_queue.c | 7 +-
> drivers/gpu/drm/xe/xe_exec_queue_types.h | 2 +
> drivers/gpu/drm/xe/xe_sync.c | 14 +-
> drivers/gpu/drm/xe/xe_sync.h | 2 +-
> drivers/gpu/drm/xe/xe_vm.c | 536 +++++----------------
> --
> drivers/gpu/drm/xe/xe_vm.h | 2 -
> drivers/gpu/drm/xe/xe_vm_types.h | 31 +-
> include/uapi/drm/xe_drm.h | 33 +-
> 9 files changed, 127 insertions(+), 543 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_exec.c
> b/drivers/gpu/drm/xe/xe_exec.c
> index 7d0381d41b32..28e84a0bbeb0 100644
> --- a/drivers/gpu/drm/xe/xe_exec.c
> +++ b/drivers/gpu/drm/xe/xe_exec.c
> @@ -196,27 +196,6 @@ int xe_exec_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
> }
> }
>
> - /*
> - * We can't install a job into the VM dma-resv shared slot
> before an
> - * async VM bind passed in as a fence without the risk of
> deadlocking as
> - * the bind can trigger an eviction which in turn depends on
> anything in
> - * the VM dma-resv shared slots. Not an ideal solution, but
> we wait for
> - * all dependent async VM binds to start (install correct
> fences into
> - * dma-resv slots) before moving forward.
> - */
> - if (!xe_vm_no_dma_fences(vm) &&
> - vm->flags & XE_VM_FLAG_ASYNC_BIND_OPS) {
> - for (i = 0; i < args->num_syncs; i++) {
> - struct dma_fence *fence = syncs[i].fence;
> -
> - if (fence) {
> - err =
> xe_vm_async_fence_wait_start(fence);
> - if (err)
> - goto err_syncs;
> - }
> - }
> - }
> -
> retry:
> if (!xe_vm_no_dma_fences(vm) &&
> xe_vm_userptr_check_repin(vm)) {
> err = down_write_killable(&vm->lock);
> @@ -229,28 +208,6 @@ int xe_exec_ioctl(struct drm_device *dev, void
> *data, struct drm_file *file)
> if (err)
> goto err_syncs;
>
> - /* We don't allow execs while the VM is in error state */
> - if (vm->async_ops.error) {
> - err = vm->async_ops.error;
> - goto err_unlock_list;
> - }
> -
> - /*
> - * Extreme corner where we exit a VM error state with a
> munmap style VM
> - * unbind inflight which requires a rebind. In this case the
> rebind
> - * needs to install some fences into the dma-resv slots. The
> worker to
> - * do this queued, let that worker make progress by dropping
> vm->lock,
> - * flushing the worker and retrying the exec.
> - */
> - if (vm->async_ops.munmap_rebind_inflight) {
> - if (write_locked)
> - up_write(&vm->lock);
> - else
> - up_read(&vm->lock);
> - flush_work(&vm->async_ops.work);
> - goto retry;
> - }
> -
> if (write_locked) {
> err = xe_vm_userptr_pin(vm);
> downgrade_write(&vm->lock);
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c
> b/drivers/gpu/drm/xe/xe_exec_queue.c
> index 6725157d8c1d..e950c9ef9d40 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue.c
> +++ b/drivers/gpu/drm/xe/xe_exec_queue.c
> @@ -661,7 +661,10 @@ int xe_exec_queue_create_ioctl(struct drm_device
> *dev, void *data,
> if (XE_IOCTL_DBG(xe, eci[0].gt_id >= xe->info.gt_count))
> return -EINVAL;
>
> - if (eci[0].engine_class == DRM_XE_ENGINE_CLASS_VM_BIND) {
> + if (eci[0].engine_class >= DRM_XE_ENGINE_CLASS_VM_BIND_ASYNC)
> {
> + bool sync = eci[0].engine_class ==
> + DRM_XE_ENGINE_CLASS_VM_BIND_SYNC;
> +
> for_each_gt(gt, xe, id) {
> struct xe_exec_queue *new;
>
> @@ -687,6 +690,8 @@ int xe_exec_queue_create_ioctl(struct drm_device
> *dev, void *data,
> args->width, hwe,
>
> EXEC_QUEUE_FLAG_PERSISTENT |
> EXEC_QUEUE_FLAG_VM
> |
> + (sync ? 0 :
> +
> EXEC_QUEUE_FLAG_VM_ASYNC) |
> (id ?
>
> EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD :
> 0));
> diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> index 347d28442701..b828d8a60adf 100644
> --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
> +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
> @@ -66,6 +66,8 @@ struct xe_exec_queue {
> #define EXEC_QUEUE_FLAG_VM BIT(5)
> /* child of VM queue for multi-tile VM jobs */
> #define EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD BIT(6)
> +/* VM jobs for this queue are asynchronous */
> +#define EXEC_QUEUE_FLAG_VM_ASYNC BIT(7)
>
> /**
> * @flags: flags for this exec queue, should statically setup
> aside from ban
> diff --git a/drivers/gpu/drm/xe/xe_sync.c
> b/drivers/gpu/drm/xe/xe_sync.c
> index 9fcd7802ba30..73ef259aa387 100644
> --- a/drivers/gpu/drm/xe/xe_sync.c
> +++ b/drivers/gpu/drm/xe/xe_sync.c
> @@ -18,7 +18,6 @@
> #include "xe_sched_job_types.h"
>
> #define SYNC_FLAGS_TYPE_MASK 0x3
> -#define SYNC_FLAGS_FENCE_INSTALLED 0x10000
>
> struct user_fence {
> struct xe_device *xe;
> @@ -223,12 +222,11 @@ int xe_sync_entry_add_deps(struct xe_sync_entry
> *sync, struct xe_sched_job *job)
> return 0;
> }
>
> -bool xe_sync_entry_signal(struct xe_sync_entry *sync, struct
> xe_sched_job *job,
> +void xe_sync_entry_signal(struct xe_sync_entry *sync, struct
> xe_sched_job *job,
> struct dma_fence *fence)
> {
> - if (!(sync->flags & DRM_XE_SYNC_SIGNAL) ||
> - sync->flags & SYNC_FLAGS_FENCE_INSTALLED)
> - return false;
> + if (!(sync->flags & DRM_XE_SYNC_SIGNAL))
> + return;
>
> if (sync->chain_fence) {
> drm_syncobj_add_point(sync->syncobj, sync-
> >chain_fence,
> @@ -260,12 +258,6 @@ bool xe_sync_entry_signal(struct xe_sync_entry
> *sync, struct xe_sched_job *job,
> job->user_fence.addr = sync->addr;
> job->user_fence.value = sync->timeline_value;
> }
> -
> - /* TODO: external BO? */
> -
> - sync->flags |= SYNC_FLAGS_FENCE_INSTALLED;
> -
> - return true;
> }
>
> void xe_sync_entry_cleanup(struct xe_sync_entry *sync)
> diff --git a/drivers/gpu/drm/xe/xe_sync.h
> b/drivers/gpu/drm/xe/xe_sync.h
> index 4cbcf7a19911..30958ddc4cdc 100644
> --- a/drivers/gpu/drm/xe/xe_sync.h
> +++ b/drivers/gpu/drm/xe/xe_sync.h
> @@ -19,7 +19,7 @@ int xe_sync_entry_parse(struct xe_device *xe,
> struct xe_file *xef,
> int xe_sync_entry_wait(struct xe_sync_entry *sync);
> int xe_sync_entry_add_deps(struct xe_sync_entry *sync,
> struct xe_sched_job *job);
> -bool xe_sync_entry_signal(struct xe_sync_entry *sync,
> +void xe_sync_entry_signal(struct xe_sync_entry *sync,
> struct xe_sched_job *job,
> struct dma_fence *fence);
> void xe_sync_entry_cleanup(struct xe_sync_entry *sync);
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index ea1f089549b1..f9dc9bf6b36b 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -565,7 +565,7 @@ static void preempt_rebind_work_func(struct
> work_struct *w)
> unsigned int fence_count = 0;
> LIST_HEAD(preempt_fences);
> ktime_t end = 0;
> - int err;
> + int err = 0;
> long wait;
> int __maybe_unused tries = 0;
>
> @@ -581,22 +581,6 @@ static void preempt_rebind_work_func(struct
> work_struct *w)
> }
>
> retry:
> - if (vm->async_ops.error)
> - goto out_unlock_outer;
> -
> - /*
> - * Extreme corner where we exit a VM error state with a
> munmap style VM
> - * unbind inflight which requires a rebind. In this case the
> rebind
> - * needs to install some fences into the dma-resv slots. The
> worker to
> - * do this queued, let that worker make progress by dropping
> vm->lock
> - * and trying this again.
> - */
> - if (vm->async_ops.munmap_rebind_inflight) {
> - up_write(&vm->lock);
> - flush_work(&vm->async_ops.work);
> - goto retry;
> - }
> -
> if (xe_vm_userptr_check_repin(vm)) {
> err = xe_vm_userptr_pin(vm);
> if (err)
> @@ -1190,7 +1174,6 @@ static struct drm_gpuva_fn_ops gpuva_ops = {
> .op_alloc = xe_vm_op_alloc,
> };
>
> -static void xe_vma_op_work_func(struct work_struct *w);
> static void vm_destroy_work_func(struct work_struct *w);
>
> struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
> @@ -1224,10 +1207,6 @@ struct xe_vm *xe_vm_create(struct xe_device
> *xe, u32 flags)
> INIT_LIST_HEAD(&vm->notifier.rebind_list);
> spin_lock_init(&vm->notifier.list_lock);
>
> - INIT_LIST_HEAD(&vm->async_ops.pending);
> - INIT_WORK(&vm->async_ops.work, xe_vma_op_work_func);
> - spin_lock_init(&vm->async_ops.lock);
> -
> INIT_WORK(&vm->destroy_work, vm_destroy_work_func);
>
> INIT_LIST_HEAD(&vm->preempt.exec_queues);
> @@ -1281,11 +1260,6 @@ struct xe_vm *xe_vm_create(struct xe_device
> *xe, u32 flags)
> vm->batch_invalidate_tlb = false;
> }
>
> - if (flags & XE_VM_FLAG_ASYNC_BIND_OPS) {
> - vm->async_ops.fence.context =
> dma_fence_context_alloc(1);
> - vm->flags |= XE_VM_FLAG_ASYNC_BIND_OPS;
> - }
> -
> /* Fill pt_root after allocating scratch tables */
> for_each_tile(tile, xe, id) {
> if (!vm->pt_root[id])
> @@ -1301,6 +1275,9 @@ struct xe_vm *xe_vm_create(struct xe_device
> *xe, u32 flags)
> struct xe_gt *gt = tile->primary_gt;
> struct xe_vm *migrate_vm;
> struct xe_exec_queue *q;
> + u32 create_flags = EXEC_QUEUE_FLAG_VM |
> + ((flags & XE_VM_FLAG_ASYNC_DEFAULT) ?
> + EXEC_QUEUE_FLAG_VM_ASYNC : 0);
>
> if (!vm->pt_root[id])
> continue;
> @@ -1308,7 +1285,7 @@ struct xe_vm *xe_vm_create(struct xe_device
> *xe, u32 flags)
> migrate_vm = xe_migrate_get_vm(tile-
> >migrate);
> q = xe_exec_queue_create_class(xe, gt,
> migrate_vm,
>
> XE_ENGINE_CLASS_COPY,
> -
> EXEC_QUEUE_FLAG_VM);
> + create_flags);
> xe_vm_put(migrate_vm);
> if (IS_ERR(q)) {
> xe_vm_close_and_put(vm);
> @@ -1363,12 +1340,6 @@ struct xe_vm *xe_vm_create(struct xe_device
> *xe, u32 flags)
> return ERR_PTR(err);
> }
>
> -static void flush_async_ops(struct xe_vm *vm)
> -{
> - queue_work(system_unbound_wq, &vm->async_ops.work);
> - flush_work(&vm->async_ops.work);
> -}
> -
> static void xe_vm_close(struct xe_vm *vm)
> {
> down_write(&vm->lock);
> @@ -1388,7 +1359,6 @@ void xe_vm_close_and_put(struct xe_vm *vm)
> xe_assert(xe, !vm->preempt.num_exec_queues);
>
> xe_vm_close(vm);
> - flush_async_ops(vm);
> if (xe_vm_in_compute_mode(vm))
> flush_work(&vm->preempt.rebind_work);
>
> @@ -1608,10 +1578,8 @@ xe_vm_unbind_vma(struct xe_vma *vma, struct
> xe_exec_queue *q,
>
> err_fences:
> if (fences) {
> - while (cur_fence) {
> - /* FIXME: Rewind the previous binds? */
> + while (cur_fence)
> dma_fence_put(fences[--cur_fence]);
> - }
> kfree(fences);
> }
>
> @@ -1685,100 +1653,24 @@ xe_vm_bind_vma(struct xe_vma *vma, struct
> xe_exec_queue *q,
>
> err_fences:
> if (fences) {
> - while (cur_fence) {
> - /* FIXME: Rewind the previous binds? */
> + while (cur_fence)
> dma_fence_put(fences[--cur_fence]);
> - }
> kfree(fences);
> }
>
> return ERR_PTR(err);
> }
>
> -struct async_op_fence {
> - struct dma_fence fence;
> - struct dma_fence *wait_fence;
> - struct dma_fence_cb cb;
> - struct xe_vm *vm;
> - wait_queue_head_t wq;
> - bool started;
> -};
> -
> -static const char *async_op_fence_get_driver_name(struct dma_fence
> *dma_fence)
> -{
> - return "xe";
> -}
> -
> -static const char *
> -async_op_fence_get_timeline_name(struct dma_fence *dma_fence)
> -{
> - return "async_op_fence";
> -}
> -
> -static const struct dma_fence_ops async_op_fence_ops = {
> - .get_driver_name = async_op_fence_get_driver_name,
> - .get_timeline_name = async_op_fence_get_timeline_name,
> -};
> -
> -static void async_op_fence_cb(struct dma_fence *fence, struct
> dma_fence_cb *cb)
> -{
> - struct async_op_fence *afence =
> - container_of(cb, struct async_op_fence, cb);
> -
> - afence->fence.error = afence->wait_fence->error;
> - dma_fence_signal(&afence->fence);
> - xe_vm_put(afence->vm);
> - dma_fence_put(afence->wait_fence);
> - dma_fence_put(&afence->fence);
> -}
> -
> -static void add_async_op_fence_cb(struct xe_vm *vm,
> - struct dma_fence *fence,
> - struct async_op_fence *afence)
> +static bool xe_vm_sync_mode(struct xe_vm *vm, struct xe_exec_queue
> *q)
> {
> - int ret;
> -
> - if (!xe_vm_no_dma_fences(vm)) {
> - afence->started = true;
> - smp_wmb();
> - wake_up_all(&afence->wq);
> - }
> -
> - afence->wait_fence = dma_fence_get(fence);
> - afence->vm = xe_vm_get(vm);
> - dma_fence_get(&afence->fence);
> - ret = dma_fence_add_callback(fence, &afence->cb,
> async_op_fence_cb);
> - if (ret == -ENOENT) {
> - afence->fence.error = afence->wait_fence->error;
> - dma_fence_signal(&afence->fence);
> - }
> - if (ret) {
> - xe_vm_put(vm);
> - dma_fence_put(afence->wait_fence);
> - dma_fence_put(&afence->fence);
> - }
> - XE_WARN_ON(ret && ret != -ENOENT);
> -}
> -
> -int xe_vm_async_fence_wait_start(struct dma_fence *fence)
> -{
> - if (fence->ops == &async_op_fence_ops) {
> - struct async_op_fence *afence =
> - container_of(fence, struct async_op_fence,
> fence);
> -
> - xe_assert(afence->vm->xe,
> !xe_vm_no_dma_fences(afence->vm));
> -
> - smp_rmb();
> - return wait_event_interruptible(afence->wq, afence-
> >started);
> - }
> -
> - return 0;
> + return q ? !(q->flags & EXEC_QUEUE_FLAG_VM_ASYNC) :
> + !(vm->flags & XE_VM_FLAG_ASYNC_DEFAULT);
> }
>
> static int __xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma,
> struct xe_exec_queue *q, struct xe_sync_entry
> *syncs,
> - u32 num_syncs, struct async_op_fence *afence,
> - bool immediate, bool first_op, bool last_op)
> + u32 num_syncs, bool immediate, bool first_op,
> + bool last_op)
> {
> struct dma_fence *fence;
>
> @@ -1800,17 +1692,18 @@ static int __xe_vm_bind(struct xe_vm *vm,
> struct xe_vma *vma,
> xe_sync_entry_signal(&syncs[i], NULL,
> fence);
> }
> }
> - if (afence)
> - add_async_op_fence_cb(vm, fence, afence);
>
> + if (last_op && xe_vm_sync_mode(vm, q))
> + dma_fence_wait(fence, true);
> dma_fence_put(fence);
> +
> return 0;
> }
>
> static int xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct
> xe_exec_queue *q,
> struct xe_bo *bo, struct xe_sync_entry *syncs,
> - u32 num_syncs, struct async_op_fence *afence,
> - bool immediate, bool first_op, bool last_op)
> + u32 num_syncs, bool immediate, bool first_op,
> + bool last_op)
> {
> int err;
>
> @@ -1823,14 +1716,13 @@ static int xe_vm_bind(struct xe_vm *vm,
> struct xe_vma *vma, struct xe_exec_queue
> return err;
> }
>
> - return __xe_vm_bind(vm, vma, q, syncs, num_syncs, afence,
> immediate,
> - first_op, last_op);
> + return __xe_vm_bind(vm, vma, q, syncs, num_syncs, immediate,
> first_op,
> + last_op);
> }
>
> static int xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma,
> struct xe_exec_queue *q, struct xe_sync_entry
> *syncs,
> - u32 num_syncs, struct async_op_fence *afence,
> - bool first_op, bool last_op)
> + u32 num_syncs, bool first_op, bool last_op)
> {
> struct dma_fence *fence;
>
> @@ -1840,10 +1732,10 @@ static int xe_vm_unbind(struct xe_vm *vm,
> struct xe_vma *vma,
> fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op,
> last_op);
> if (IS_ERR(fence))
> return PTR_ERR(fence);
> - if (afence)
> - add_async_op_fence_cb(vm, fence, afence);
>
> xe_vma_destroy(vma, fence);
> + if (last_op && xe_vm_sync_mode(vm, q))
> + dma_fence_wait(fence, true);
> dma_fence_put(fence);
>
> return 0;
> @@ -1851,7 +1743,7 @@ static int xe_vm_unbind(struct xe_vm *vm,
> struct xe_vma *vma,
>
> #define ALL_DRM_XE_VM_CREATE_FLAGS (DRM_XE_VM_CREATE_SCRATCH_PAGE |
> \
> DRM_XE_VM_CREATE_COMPUTE_MODE | \
> - DRM_XE_VM_CREATE_ASYNC_BIND_OPS |
> \
> + DRM_XE_VM_CREATE_ASYNC_DEFAULT |
> \
> DRM_XE_VM_CREATE_FAULT_MODE)
>
> int xe_vm_create_ioctl(struct drm_device *dev, void *data,
> @@ -1897,12 +1789,15 @@ int xe_vm_create_ioctl(struct drm_device
> *dev, void *data,
> xe_device_in_fault_mode(xe)))
> return -EINVAL;
>
> + if (XE_IOCTL_DBG(xe, args->extensions))
> + return -EINVAL;
> +
> if (args->flags & DRM_XE_VM_CREATE_SCRATCH_PAGE)
> flags |= XE_VM_FLAG_SCRATCH_PAGE;
> if (args->flags & DRM_XE_VM_CREATE_COMPUTE_MODE)
> flags |= XE_VM_FLAG_COMPUTE_MODE;
> - if (args->flags & DRM_XE_VM_CREATE_ASYNC_BIND_OPS)
> - flags |= XE_VM_FLAG_ASYNC_BIND_OPS;
> + if (args->flags & DRM_XE_VM_CREATE_ASYNC_DEFAULT)
> + flags |= XE_VM_FLAG_ASYNC_DEFAULT;
> if (args->flags & DRM_XE_VM_CREATE_FAULT_MODE)
> flags |= XE_VM_FLAG_FAULT_MODE;
>
> @@ -1979,8 +1874,7 @@ static const u32 region_to_mem_type[] = {
> static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
> struct xe_exec_queue *q, u32 region,
> struct xe_sync_entry *syncs, u32 num_syncs,
> - struct async_op_fence *afence, bool
> first_op,
> - bool last_op)
> + bool first_op, bool last_op)
> {
> int err;
>
> @@ -1994,7 +1888,7 @@ static int xe_vm_prefetch(struct xe_vm *vm,
> struct xe_vma *vma,
>
> if (vma->tile_mask != (vma->tile_present & ~vma-
> >usm.tile_invalidated)) {
> return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs,
> num_syncs,
> - afence, true, first_op, last_op);
> + true, first_op, last_op);
> } else {
> int i;
>
> @@ -2004,8 +1898,7 @@ static int xe_vm_prefetch(struct xe_vm *vm,
> struct xe_vma *vma,
> xe_sync_entry_signal(&syncs[i], NULL,
>
> dma_fence_get_stub());
> }
> - if (afence)
> - dma_fence_signal(&afence->fence);
> +
> return 0;
> }
> }
> @@ -2021,51 +1914,6 @@ struct ttm_buffer_object *xe_vm_ttm_bo(struct
> xe_vm *vm)
> return &vm->pt_root[idx]->bo->ttm;
> }
>
> -static void vm_set_async_error(struct xe_vm *vm, int err)
> -{
> - lockdep_assert_held(&vm->lock);
> - vm->async_ops.error = err;
> -}
> -
> -static int vm_bind_ioctl_lookup_vma(struct xe_vm *vm, struct xe_bo
> *bo,
> - u64 addr, u64 range, u32 op)
> -{
> - struct xe_device *xe = vm->xe;
> - struct xe_vma *vma;
> - bool async = !!(op & XE_VM_BIND_FLAG_ASYNC);
> -
> - lockdep_assert_held(&vm->lock);
> -
> - switch (VM_BIND_OP(op)) {
> - case XE_VM_BIND_OP_MAP:
> - case XE_VM_BIND_OP_MAP_USERPTR:
> - vma = xe_vm_find_overlapping_vma(vm, addr, range);
> - if (XE_IOCTL_DBG(xe, vma && !async))
> - return -EBUSY;
> - break;
> - case XE_VM_BIND_OP_UNMAP:
> - case XE_VM_BIND_OP_PREFETCH:
> - vma = xe_vm_find_overlapping_vma(vm, addr, range);
> - if (XE_IOCTL_DBG(xe, !vma))
> - /* Not an actual error, IOCTL cleans up
> returns and 0 */
> - return -ENODATA;
> - if (XE_IOCTL_DBG(xe, (xe_vma_start(vma) != addr ||
> - xe_vma_end(vma) != addr +
> range) && !async))
> - return -EINVAL;
> - break;
> - case XE_VM_BIND_OP_UNMAP_ALL:
> - if (XE_IOCTL_DBG(xe, list_empty(&bo-
> >ttm.base.gpuva.list)))
> - /* Not an actual error, IOCTL cleans up
> returns and 0 */
> - return -ENODATA;
> - break;
> - default:
> - drm_warn(&xe->drm, "NOT POSSIBLE");
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> static void prep_vma_destroy(struct xe_vm *vm, struct xe_vma *vma,
> bool post_commit)
> {
> @@ -2353,37 +2201,15 @@ static int vm_bind_ioctl_ops_parse(struct
> xe_vm *vm, struct xe_exec_queue *q,
> bool async)
> {
> struct xe_vma_op *last_op = NULL;
> - struct async_op_fence *fence = NULL;
> struct drm_gpuva_op *__op;
> int err = 0;
>
> lockdep_assert_held_write(&vm->lock);
>
> - if (last && num_syncs && async) {
> - u64 seqno;
> -
> - fence = kmalloc(sizeof(*fence), GFP_KERNEL);
> - if (!fence)
> - return -ENOMEM;
> -
> - seqno = q ? ++q->bind.fence_seqno : ++vm-
> >async_ops.fence.seqno;
> - dma_fence_init(&fence->fence, &async_op_fence_ops,
> - &vm->async_ops.lock, q ? q-
> >bind.fence_ctx :
> - vm->async_ops.fence.context, seqno);
> -
> - if (!xe_vm_no_dma_fences(vm)) {
> - fence->vm = vm;
> - fence->started = false;
> - init_waitqueue_head(&fence->wq);
> - }
> - }
> -
> drm_gpuva_for_each_op(__op, ops) {
> struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
> bool first = list_empty(ops_list);
>
> - xe_assert(vm->xe, first || async);
> -
> INIT_LIST_HEAD(&op->link);
> list_add_tail(&op->link, ops_list);
>
> @@ -2403,10 +2229,8 @@ static int vm_bind_ioctl_ops_parse(struct
> xe_vm *vm, struct xe_exec_queue *q,
> vma = new_vma(vm, &op->base.map,
> op->tile_mask, op-
> >map.read_only,
> op->map.is_null);
> - if (IS_ERR(vma)) {
> - err = PTR_ERR(vma);
> - goto free_fence;
> - }
> + if (IS_ERR(vma))
> + return PTR_ERR(vma);
>
> op->map.vma = vma;
> break;
> @@ -2431,10 +2255,8 @@ static int vm_bind_ioctl_ops_parse(struct
> xe_vm *vm, struct xe_exec_queue *q,
> vma = new_vma(vm, op-
> >base.remap.prev,
> op->tile_mask,
> read_only,
> is_null);
> - if (IS_ERR(vma)) {
> - err = PTR_ERR(vma);
> - goto free_fence;
> - }
> + if (IS_ERR(vma))
> + return PTR_ERR(vma);
>
> op->remap.prev = vma;
>
> @@ -2467,10 +2289,8 @@ static int vm_bind_ioctl_ops_parse(struct
> xe_vm *vm, struct xe_exec_queue *q,
> vma = new_vma(vm, op-
> >base.remap.next,
> op->tile_mask,
> read_only,
> is_null);
> - if (IS_ERR(vma)) {
> - err = PTR_ERR(vma);
> - goto free_fence;
> - }
> + if (IS_ERR(vma))
> + return PTR_ERR(vma);
>
> op->remap.next = vma;
>
> @@ -2502,27 +2322,23 @@ static int vm_bind_ioctl_ops_parse(struct
> xe_vm *vm, struct xe_exec_queue *q,
>
> err = xe_vma_op_commit(vm, op);
> if (err)
> - goto free_fence;
> + return err;
> }
>
> /* FIXME: Unhandled corner case */
> XE_WARN_ON(!last_op && last && !list_empty(ops_list));
>
> if (!last_op)
> - goto free_fence;
> + return 0;
> +
> last_op->ops = ops;
> if (last) {
> last_op->flags |= XE_VMA_OP_LAST;
> last_op->num_syncs = num_syncs;
> last_op->syncs = syncs;
> - last_op->fence = fence;
> }
>
> return 0;
> -
> -free_fence:
> - kfree(fence);
> - return err;
> }
>
> static int op_execute(struct drm_exec *exec, struct xe_vm *vm,
> @@ -2542,7 +2358,7 @@ static int op_execute(struct drm_exec *exec,
> struct xe_vm *vm,
> switch (op->base.op) {
> case DRM_GPUVA_OP_MAP:
> err = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma),
> - op->syncs, op->num_syncs, op->fence,
> + op->syncs, op->num_syncs,
> op->map.immediate ||
> !xe_vm_in_fault_mode(vm),
> op->flags & XE_VMA_OP_FIRST,
> op->flags & XE_VMA_OP_LAST);
> @@ -2553,16 +2369,13 @@ static int op_execute(struct drm_exec *exec,
> struct xe_vm *vm,
> bool next = !!op->remap.next;
>
> if (!op->remap.unmap_done) {
> - if (prev || next) {
> - vm->async_ops.munmap_rebind_inflight
> = true;
> + if (prev || next)
> vma->gpuva.flags |=
> XE_VMA_FIRST_REBIND;
> - }
> err = xe_vm_unbind(vm, vma, op->q, op->syncs,
> op->num_syncs,
> - !prev && !next ? op->fence
> : NULL,
> op->flags &
> XE_VMA_OP_FIRST,
> - op->flags & XE_VMA_OP_LAST
> && !prev &&
> - !next);
> + op->flags & XE_VMA_OP_LAST
> &&
> + !prev && !next);
> if (err)
> break;
> op->remap.unmap_done = true;
> @@ -2572,8 +2385,7 @@ static int op_execute(struct drm_exec *exec,
> struct xe_vm *vm,
> op->remap.prev->gpuva.flags |=
> XE_VMA_LAST_REBIND;
> err = xe_vm_bind(vm, op->remap.prev, op->q,
> xe_vma_bo(op->remap.prev),
> op->syncs,
> - op->num_syncs,
> - !next ? op->fence : NULL,
> true, false,
> + op->num_syncs, true, false,
> op->flags & XE_VMA_OP_LAST
> && !next);
> op->remap.prev->gpuva.flags &=
> ~XE_VMA_LAST_REBIND;
> if (err)
> @@ -2586,26 +2398,24 @@ static int op_execute(struct drm_exec *exec,
> struct xe_vm *vm,
> err = xe_vm_bind(vm, op->remap.next, op->q,
> xe_vma_bo(op->remap.next),
> op->syncs, op->num_syncs,
> - op->fence, true, false,
> + true, false,
> op->flags & XE_VMA_OP_LAST);
> op->remap.next->gpuva.flags &=
> ~XE_VMA_LAST_REBIND;
> if (err)
> break;
> op->remap.next = NULL;
> }
> - vm->async_ops.munmap_rebind_inflight = false;
>
> break;
> }
> case DRM_GPUVA_OP_UNMAP:
> err = xe_vm_unbind(vm, vma, op->q, op->syncs,
> - op->num_syncs, op->fence,
> - op->flags & XE_VMA_OP_FIRST,
> + op->num_syncs, op->flags &
> XE_VMA_OP_FIRST,
> op->flags & XE_VMA_OP_LAST);
> break;
> case DRM_GPUVA_OP_PREFETCH:
> err = xe_vm_prefetch(vm, vma, op->q, op-
> >prefetch.region,
> - op->syncs, op->num_syncs, op-
> >fence,
> + op->syncs, op->num_syncs,
> op->flags & XE_VMA_OP_FIRST,
> op->flags & XE_VMA_OP_LAST);
> break;
> @@ -2704,14 +2514,9 @@ static void xe_vma_op_cleanup(struct xe_vm
> *vm, struct xe_vma_op *op)
> kfree(op->syncs);
> if (op->q)
> xe_exec_queue_put(op->q);
> - if (op->fence)
> - dma_fence_put(&op->fence->fence);
> }
> - if (!list_empty(&op->link)) {
> - spin_lock_irq(&vm->async_ops.lock);
> + if (!list_empty(&op->link))
> list_del(&op->link);
> - spin_unlock_irq(&vm->async_ops.lock);
> - }
> if (op->ops)
> drm_gpuva_ops_free(&vm->mgr, op->ops);
> if (last)
> @@ -2773,130 +2578,6 @@ static void xe_vma_op_unwind(struct xe_vm
> *vm, struct xe_vma_op *op,
> }
> }
>
> -static struct xe_vma_op *next_vma_op(struct xe_vm *vm)
> -{
> - return list_first_entry_or_null(&vm->async_ops.pending,
> - struct xe_vma_op, link);
> -}
> -
> -static void xe_vma_op_work_func(struct work_struct *w)
> -{
> - struct xe_vm *vm = container_of(w, struct xe_vm,
> async_ops.work);
> -
> - for (;;) {
> - struct xe_vma_op *op;
> - int err;
> -
> - if (vm->async_ops.error && !xe_vm_is_closed(vm))
> - break;
> -
> - spin_lock_irq(&vm->async_ops.lock);
> - op = next_vma_op(vm);
> - spin_unlock_irq(&vm->async_ops.lock);
> -
> - if (!op)
> - break;
> -
> - if (!xe_vm_is_closed(vm)) {
> - down_write(&vm->lock);
> - err = xe_vma_op_execute(vm, op);
> - if (err) {
> - drm_warn(&vm->xe->drm,
> - "Async VM op(%d) failed with
> %d",
> - op->base.op, err);
> - vm_set_async_error(vm, err);
> - up_write(&vm->lock);
> -
> - break;
> - }
> - up_write(&vm->lock);
> - } else {
> - struct xe_vma *vma;
> -
> - switch (op->base.op) {
> - case DRM_GPUVA_OP_REMAP:
> - vma = gpuva_to_vma(op-
> >base.remap.unmap->va);
> - trace_xe_vma_flush(vma);
> -
> - down_write(&vm->lock);
> - xe_vma_destroy_unlocked(vma);
> - up_write(&vm->lock);
> - break;
> - case DRM_GPUVA_OP_UNMAP:
> - vma = gpuva_to_vma(op-
> >base.unmap.va);
> - trace_xe_vma_flush(vma);
> -
> - down_write(&vm->lock);
> - xe_vma_destroy_unlocked(vma);
> - up_write(&vm->lock);
> - break;
> - default:
> - /* Nothing to do */
> - break;
> - }
> -
> - if (op->fence &&
> !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
> - &op->fence-
> >fence.flags)) {
> - if (!xe_vm_no_dma_fences(vm)) {
> - op->fence->started = true;
> - wake_up_all(&op->fence->wq);
> - }
> - dma_fence_signal(&op->fence->fence);
> - }
> - }
> -
> - xe_vma_op_cleanup(vm, op);
> - }
> -}
> -
> -static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> - struct list_head *ops_list, bool
> async)
> -{
> - struct xe_vma_op *op, *last_op, *next;
> - int err;
> -
> - lockdep_assert_held_write(&vm->lock);
> -
> - list_for_each_entry(op, ops_list, link)
> - last_op = op;
> -
> - if (!async) {
> - err = xe_vma_op_execute(vm, last_op);
> - if (err)
> - goto unwind;
> - xe_vma_op_cleanup(vm, last_op);
> - } else {
> - int i;
> - bool installed = false;
> -
> - for (i = 0; i < last_op->num_syncs; i++)
> - installed |= xe_sync_entry_signal(&last_op-
> >syncs[i],
> - NULL,
> - &last_op-
> >fence->fence);
> - if (!installed && last_op->fence)
> - dma_fence_signal(&last_op->fence->fence);
> -
> - spin_lock_irq(&vm->async_ops.lock);
> - list_splice_tail(ops_list, &vm->async_ops.pending);
> - spin_unlock_irq(&vm->async_ops.lock);
> -
> - if (!vm->async_ops.error)
> - queue_work(system_unbound_wq, &vm-
> >async_ops.work);
> - }
> -
> - return 0;
> -
> -unwind:
> - list_for_each_entry_reverse(op, ops_list, link)
> - xe_vma_op_unwind(vm, op, op->flags &
> XE_VMA_OP_COMMITTED,
> - op->flags &
> XE_VMA_OP_PREV_COMMITTED,
> - op->flags &
> XE_VMA_OP_NEXT_COMMITTED);
> - list_for_each_entry_safe(op, next, ops_list, link)
> - xe_vma_op_cleanup(vm, op);
> -
> - return err;
> -}
> -
> static void vm_bind_ioctl_ops_unwind(struct xe_vm *vm,
> struct drm_gpuva_ops **ops,
> int num_ops_list)
> @@ -2923,6 +2604,31 @@ static void vm_bind_ioctl_ops_unwind(struct
> xe_vm *vm,
> }
> }
>
> +static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
> + struct list_head *ops_list)
> +{
> + struct xe_vma_op *op, *next;
> + int err;
> +
> + lockdep_assert_held_write(&vm->lock);
> +
> + list_for_each_entry_safe(op, next, ops_list, link) {
> + err = xe_vma_op_execute(vm, op);
> + if (err) {
> + drm_warn(&vm->xe->drm, "VM op(%d) failed with
> %d",
> + op->base.op, err);
> + /*
> + * FIXME: Killing VM rather than proper error
> handling
> + */
> + xe_vm_kill(vm);
> + return -ENOSPC;
> + }
> + xe_vma_op_cleanup(vm, op);
> + }
> +
> + return 0;
> +}
> +
> #ifdef TEST_VM_ASYNC_OPS_ERROR
> #define SUPPORTED_FLAGS \
> (FORCE_ASYNC_OP_ERROR | XE_VM_BIND_FLAG_ASYNC | \
> @@ -2931,7 +2637,8 @@ static void vm_bind_ioctl_ops_unwind(struct
> xe_vm *vm,
> #else
> #define SUPPORTED_FLAGS \
> (XE_VM_BIND_FLAG_ASYNC | XE_VM_BIND_FLAG_READONLY | \
> - XE_VM_BIND_FLAG_IMMEDIATE | XE_VM_BIND_FLAG_NULL | 0xffff)
> + XE_VM_BIND_FLAG_IMMEDIATE | XE_VM_BIND_FLAG_NULL | \
> + 0xffff)
> #endif
> #define XE_64K_PAGE_MASK 0xffffull
>
> @@ -2981,22 +2688,12 @@ static int vm_bind_ioctl_check_args(struct
> xe_device *xe,
>
> if (i == 0) {
> *async = !!(op & XE_VM_BIND_FLAG_ASYNC);
> - } else if (XE_IOCTL_DBG(xe, !*async) ||
> - XE_IOCTL_DBG(xe, !(op &
> XE_VM_BIND_FLAG_ASYNC)) ||
> - XE_IOCTL_DBG(xe, VM_BIND_OP(op) ==
> - XE_VM_BIND_OP_RESTART)) {
> - err = -EINVAL;
> - goto free_bind_ops;
> - }
> -
> - if (XE_IOCTL_DBG(xe, !*async &&
> - VM_BIND_OP(op) ==
> XE_VM_BIND_OP_UNMAP_ALL)) {
> - err = -EINVAL;
> - goto free_bind_ops;
> - }
> -
> - if (XE_IOCTL_DBG(xe, !*async &&
> - VM_BIND_OP(op) ==
> XE_VM_BIND_OP_PREFETCH)) {
> + if (XE_IOCTL_DBG(xe, !*async && args-
> >num_syncs)) {
> + err = -EINVAL;
> + goto free_bind_ops;
> + }
> + } else if (XE_IOCTL_DBG(xe, *async !=
> + !!(op &
> XE_VM_BIND_FLAG_ASYNC))) {
> err = -EINVAL;
> goto free_bind_ops;
> }
> @@ -3034,8 +2731,7 @@ static int vm_bind_ioctl_check_args(struct
> xe_device *xe,
> if (XE_IOCTL_DBG(xe, obj_offset & ~PAGE_MASK) ||
> XE_IOCTL_DBG(xe, addr & ~PAGE_MASK) ||
> XE_IOCTL_DBG(xe, range & ~PAGE_MASK) ||
> - XE_IOCTL_DBG(xe, !range && VM_BIND_OP(op) !=
> - XE_VM_BIND_OP_RESTART &&
> + XE_IOCTL_DBG(xe, !range &&
> VM_BIND_OP(op) !=
> XE_VM_BIND_OP_UNMAP_ALL)) {
> err = -EINVAL;
> goto free_bind_ops;
> @@ -3083,6 +2779,12 @@ int xe_vm_bind_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file)
> err = -EINVAL;
> goto put_exec_queue;
> }
> +
> + if (XE_IOCTL_DBG(xe, async !=
> + !!(q->flags &
> EXEC_QUEUE_FLAG_VM_ASYNC))) {
> + err = -EINVAL;
> + goto put_exec_queue;
> + }
> }
>
> vm = xe_vm_lookup(xef, args->vm_id);
> @@ -3091,6 +2793,14 @@ int xe_vm_bind_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file)
> goto put_exec_queue;
> }
>
> + if (!args->exec_queue_id) {
> + if (XE_IOCTL_DBG(xe, async !=
> + !!(vm->flags &
> XE_VM_FLAG_ASYNC_DEFAULT))) {
> + err = -EINVAL;
> + goto put_vm;
> + }
> + }
> +
> err = down_write_killable(&vm->lock);
> if (err)
> goto put_vm;
> @@ -3100,34 +2810,6 @@ int xe_vm_bind_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file)
> goto release_vm_lock;
> }
>
> - if (VM_BIND_OP(bind_ops[0].op) == XE_VM_BIND_OP_RESTART) {
> - if (XE_IOCTL_DBG(xe, !(vm->flags &
> XE_VM_FLAG_ASYNC_BIND_OPS)))
> - err = -EOPNOTSUPP;
> - if (XE_IOCTL_DBG(xe, !err && args->num_syncs))
> - err = EINVAL;
> - if (XE_IOCTL_DBG(xe, !err && !vm->async_ops.error))
> - err = -EPROTO;
> -
> - if (!err) {
> - trace_xe_vm_restart(vm);
> - vm_set_async_error(vm, 0);
> -
> - queue_work(system_unbound_wq, &vm-
> >async_ops.work);
> -
> - /* Rebinds may have been blocked, give worker
> a kick */
> - if (xe_vm_in_compute_mode(vm))
> - xe_vm_queue_rebind_worker(vm);
> - }
> -
> - goto release_vm_lock;
> - }
> -
> - if (XE_IOCTL_DBG(xe, !vm->async_ops.error &&
> - async != !!(vm->flags &
> XE_VM_FLAG_ASYNC_BIND_OPS))) {
> - err = -EOPNOTSUPP;
> - goto release_vm_lock;
> - }
> -
> for (i = 0; i < args->num_binds; ++i) {
> u64 range = bind_ops[i].range;
> u64 addr = bind_ops[i].addr;
> @@ -3213,17 +2895,6 @@ int xe_vm_bind_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file)
> goto free_syncs;
> }
>
> - /* Do some error checking first to make the unwind easier */
> - for (i = 0; i < args->num_binds; ++i) {
> - u64 range = bind_ops[i].range;
> - u64 addr = bind_ops[i].addr;
> - u32 op = bind_ops[i].op;
> -
> - err = vm_bind_ioctl_lookup_vma(vm, bos[i], addr,
> range, op);
> - if (err)
> - goto free_syncs;
> - }
> -
> for (i = 0; i < args->num_binds; ++i) {
> u64 range = bind_ops[i].range;
> u64 addr = bind_ops[i].addr;
> @@ -3255,10 +2926,19 @@ int xe_vm_bind_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file)
> goto unwind_ops;
> }
>
> - err = vm_bind_ioctl_ops_execute(vm, &ops_list, async);
> + xe_vm_get(vm);
> + if (q)
> + xe_exec_queue_get(q);
> +
> + err = vm_bind_ioctl_ops_execute(vm, &ops_list);
> +
> up_write(&vm->lock);
>
> - for (i = 0; i < args->num_binds; ++i)
> + if (q)
> + xe_exec_queue_put(q);
> + xe_vm_put(vm);
> +
> + for (i = 0; bos && i < args->num_binds; ++i)
> xe_bo_put(bos[i]);
>
> kfree(bos);
> diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
> index f966ed39b711..384ec6ea8318 100644
> --- a/drivers/gpu/drm/xe/xe_vm.h
> +++ b/drivers/gpu/drm/xe/xe_vm.h
> @@ -179,8 +179,6 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm,
> bool rebind_worker);
>
> int xe_vm_invalidate_vma(struct xe_vma *vma);
>
> -int xe_vm_async_fence_wait_start(struct dma_fence *fence);
> -
> extern struct ttm_device_funcs xe_ttm_funcs;
>
> struct ttm_buffer_object *xe_vm_ttm_bo(struct xe_vm *vm);
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index 3dc3da1386cb..917b7a16c3a7 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -17,7 +17,6 @@
> #include "xe_pt_types.h"
> #include "xe_range_fence.h"
>
> -struct async_op_fence;
> struct xe_bo;
> struct xe_sync_entry;
> struct xe_vm;
> @@ -163,7 +162,7 @@ struct xe_vm {
> */
> #define XE_VM_FLAG_64K BIT(0)
> #define XE_VM_FLAG_COMPUTE_MODE BIT(1)
> -#define XE_VM_FLAG_ASYNC_BIND_OPS BIT(2)
> +#define XE_VM_FLAG_ASYNC_DEFAULT BIT(2)
> #define XE_VM_FLAG_MIGRATION BIT(3)
> #define XE_VM_FLAG_SCRATCH_PAGE BIT(4)
> #define XE_VM_FLAG_FAULT_MODE BIT(5)
> @@ -214,30 +213,6 @@ struct xe_vm {
> struct list_head list;
> } extobj;
>
> - /** @async_ops: async VM operations (bind / unbinds) */
> - struct {
> - /** @list: list of pending async VM ops */
> - struct list_head pending;
> - /** @work: worker to execute async VM ops */
> - struct work_struct work;
> - /** @lock: protects list of pending async VM ops and
> fences */
> - spinlock_t lock;
> - /** @fence: fence state */
> - struct {
> - /** @context: context of async fence */
> - u64 context;
> - /** @seqno: seqno of async fence */
> - u32 seqno;
> - } fence;
> - /** @error: error state for async VM ops */
> - int error;
> - /**
> - * @munmap_rebind_inflight: an munmap style VM bind
> is in the
> - * middle of a set of ops which requires a rebind at
> the end.
> - */
> - bool munmap_rebind_inflight;
> - } async_ops;
> -
> /** @userptr: user pointer state */
> struct {
> /**
> @@ -397,10 +372,6 @@ struct xe_vma_op {
> u32 num_syncs;
> /** @link: async operation link */
> struct list_head link;
> - /**
> - * @fence: async operation fence, signaled on last operation
> complete
> - */
> - struct async_op_fence *fence;
> /** @tile_mask: gt mask for this operation */
> u8 tile_mask;
> /** @flags: operation flags */
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index d0259865717a..baa104d502ce 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -486,7 +486,7 @@ struct drm_xe_vm_create {
>
> #define DRM_XE_VM_CREATE_SCRATCH_PAGE (0x1 << 0)
> #define DRM_XE_VM_CREATE_COMPUTE_MODE (0x1 << 1)
> -#define DRM_XE_VM_CREATE_ASYNC_BIND_OPS (0x1 << 2)
> +#define DRM_XE_VM_CREATE_ASYNC_DEFAULT (0x1 << 2)
> #define DRM_XE_VM_CREATE_FAULT_MODE (0x1 << 3)
> /** @flags: Flags */
> __u32 flags;
> @@ -546,32 +546,10 @@ struct drm_xe_vm_bind_op {
> #define XE_VM_BIND_OP_MAP 0x0
> #define XE_VM_BIND_OP_UNMAP 0x1
> #define XE_VM_BIND_OP_MAP_USERPTR 0x2
> -#define XE_VM_BIND_OP_RESTART 0x3
> -#define XE_VM_BIND_OP_UNMAP_ALL 0x4
> -#define XE_VM_BIND_OP_PREFETCH 0x5
> +#define XE_VM_BIND_OP_UNMAP_ALL 0x3
> +#define XE_VM_BIND_OP_PREFETCH 0x4
>
> #define XE_VM_BIND_FLAG_READONLY (0x1 << 16)
> - /*
> - * A bind ops completions are always async, hence the support
> for out
> - * sync. This flag indicates the allocation of the memory for
> new page
> - * tables and the job to program the pages tables is
> asynchronous
> - * relative to the IOCTL. That part of a bind operation can
> fail under
> - * memory pressure, the job in practice can't fail unless the
> system is
> - * totally shot.
> - *
> - * If this flag is clear and the IOCTL doesn't return an
> error, in
> - * practice the bind op is good and will complete.
> - *
> - * If this flag is set and doesn't return an error, the bind
> op can
> - * still fail and recovery is needed. It should free memory
> - * via non-async unbinds, and then restart all queued async
> binds op via
> - * XE_VM_BIND_OP_RESTART. Or alternatively the user should
> destroy the
> - * VM.
> - *
> - * This flag is only allowed when
> DRM_XE_VM_CREATE_ASYNC_BIND_OPS is
> - * configured in the VM and must be set if the VM is
> configured with
> - * DRM_XE_VM_CREATE_ASYNC_BIND_OPS and not in an error state.
> - */
> #define XE_VM_BIND_FLAG_ASYNC (0x1 << 17)
> /*
> * Valid on a faulting VM only, do the MAP operation
> immediately rather
> @@ -700,10 +678,11 @@ struct drm_xe_engine_class_instance {
> #define DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE 3
> #define DRM_XE_ENGINE_CLASS_COMPUTE 4
> /*
> - * Kernel only class (not actual hardware engine class). Used
> for
> + * Kernel only classes (not actual hardware engine class).
> Used for
> * creating ordered queues of VM bind operations.
> */
> -#define DRM_XE_ENGINE_CLASS_VM_BIND 5
> +#define DRM_XE_ENGINE_CLASS_VM_BIND_ASYNC 5
> +#define DRM_XE_ENGINE_CLASS_VM_BIND_SYNC 6
> __u16 engine_class;
>
> __u16 engine_instance;
More information about the Intel-xe
mailing list