diff --git a/src/intel/vulkan/xe/anv_queue.c b/src/intel/vulkan/xe/anv_queue.c index ac043a40758..fc6a6dc8bf7 100644 --- a/src/intel/vulkan/xe/anv_queue.c +++ b/src/intel/vulkan/xe/anv_queue.c @@ -145,12 +145,71 @@ anv_xe_create_engine(struct anv_device *device, return result; } +/* + * Wait for all previous DRM_IOCTL_XE_EXEC calls over the + * drm_xe_exec_queue to complete. + **/ +static void +anv_xe_wait_exec_queue_idle(struct anv_device *device, uint32_t exec_queue_id) +{ + struct drm_syncobj_create syncobj_create = {}; + struct drm_xe_sync xe_sync = { + .type = DRM_XE_SYNC_TYPE_SYNCOBJ, + .flags = DRM_XE_SYNC_FLAG_SIGNAL, + }; + struct drm_xe_exec exec = { + .exec_queue_id = exec_queue_id, + .num_syncs = 1, + .syncs = (uintptr_t)&xe_sync, + .num_batch_buffer = 0, + }; + struct drm_syncobj_destroy syncobj_destroy = {}; + struct drm_syncobj_wait syncobj_wait = { + .count_handles = 1, + .timeout_nsec = INT64_MAX, + }; + int fd = device->fd; + int ret; + + ret = intel_ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &syncobj_create); + assert(ret == 0); + if (ret) + return; + + xe_sync.handle = syncobj_create.handle; + /* Using the special exec.num_batch_buffer == 0 handling to get syncobj + * signaled when the last DRM_IOCTL_XE_EXEC is completed. + */ + ret = intel_ioctl(fd, DRM_IOCTL_XE_EXEC, &exec); + if (ret) { + /* exec_queue could have been banned, that is why it is being destroyed + * so no assert() here + */ + goto error_exec; + } + + syncobj_wait.handles = (uintptr_t)&syncobj_create.handle; + ret = intel_ioctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &syncobj_wait); + assert(ret == 0); + +error_exec: + syncobj_destroy.handle = syncobj_create.handle; + ret = intel_ioctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &syncobj_destroy); + assert(ret == 0); +} + static void destroy_engine(struct anv_device *device, uint32_t exec_queue_id) { struct drm_xe_exec_queue_destroy destroy = { .exec_queue_id = exec_queue_id, }; + + /* Application could submit a workload and before it is done, destroy the + * queue causing job timeouts in Xe KMD as it don't have permanent + * exec queues. + */ + anv_xe_wait_exec_queue_idle(device, exec_queue_id); intel_ioctl(device->fd, DRM_IOCTL_XE_EXEC_QUEUE_DESTROY, &destroy); }