anv: Wait for Xe exec queue to be idle before destroying it

Paulo reported that Vulkan is also affected by the drop of permanent
exec queues in Xe KMD, Iris already have this handling.

So here using the special DRM_IOCTL_XE_EXEC with num_batch_buffer == 0
to get a syncobj signaled when the last DRM_IOCTL_XE_EXEC is completed.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30156>
This commit is contained in:
José Roberto de Souza
2024-07-12 07:36:47 -07:00
committed by Marge Bot
parent 6cd4372460
commit 945564e498

View File

@@ -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);
}