mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
drm/xe: Enforce correct user fence signaling order using
Prevent application hangs caused by out-of-order fence signaling when
user fences are attached. Use drm_syncobj (via dma-fence-chain) to
guarantee that each user fence signals in order, regardless of the
signaling order of the attached fences. Ensure user fence writebacks to
user space occur in the correct sequence.
v7:
- Skip drm_syncbj create of error (CI)
Fixes: dd08ebf6c3 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Link: https://patch.msgid.link/20251031234050.3043507-2-matthew.brost@intel.com
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_syncobj.h>
|
||||
#include <uapi/drm/xe_drm.h>
|
||||
|
||||
#include <generated/xe_wa_oob.h>
|
||||
@@ -1390,7 +1391,9 @@ static int xe_oa_user_extensions(struct xe_oa *oa, enum xe_oa_user_extn_from fro
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param)
|
||||
static int xe_oa_parse_syncs(struct xe_oa *oa,
|
||||
struct xe_oa_stream *stream,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
int ret, num_syncs, num_ufence = 0;
|
||||
|
||||
@@ -1410,7 +1413,9 @@ static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param)
|
||||
|
||||
for (num_syncs = 0; num_syncs < param->num_syncs; num_syncs++) {
|
||||
ret = xe_sync_entry_parse(oa->xe, param->xef, ¶m->syncs[num_syncs],
|
||||
¶m->syncs_user[num_syncs], 0);
|
||||
¶m->syncs_user[num_syncs],
|
||||
stream->ufence_syncobj,
|
||||
++stream->ufence_timeline_value, 0);
|
||||
if (ret)
|
||||
goto err_syncs;
|
||||
|
||||
@@ -1540,7 +1545,7 @@ static long xe_oa_config_locked(struct xe_oa_stream *stream, u64 arg)
|
||||
return -ENODEV;
|
||||
|
||||
param.xef = stream->xef;
|
||||
err = xe_oa_parse_syncs(stream->oa, ¶m);
|
||||
err = xe_oa_parse_syncs(stream->oa, stream, ¶m);
|
||||
if (err)
|
||||
goto err_config_put;
|
||||
|
||||
@@ -1636,6 +1641,7 @@ static void xe_oa_destroy_locked(struct xe_oa_stream *stream)
|
||||
if (stream->exec_q)
|
||||
xe_exec_queue_put(stream->exec_q);
|
||||
|
||||
drm_syncobj_put(stream->ufence_syncobj);
|
||||
kfree(stream);
|
||||
}
|
||||
|
||||
@@ -1827,6 +1833,7 @@ static int xe_oa_stream_open_ioctl_locked(struct xe_oa *oa,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
struct xe_oa_stream *stream;
|
||||
struct drm_syncobj *ufence_syncobj;
|
||||
int stream_fd;
|
||||
int ret;
|
||||
|
||||
@@ -1837,17 +1844,31 @@ static int xe_oa_stream_open_ioctl_locked(struct xe_oa *oa,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = drm_syncobj_create(&ufence_syncobj, DRM_SYNCOBJ_CREATE_SIGNALED,
|
||||
NULL);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
|
||||
if (!stream) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
goto err_syncobj;
|
||||
}
|
||||
|
||||
stream->ufence_syncobj = ufence_syncobj;
|
||||
stream->oa = oa;
|
||||
ret = xe_oa_stream_init(stream, param);
|
||||
|
||||
ret = xe_oa_parse_syncs(oa, stream, param);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
ret = xe_oa_stream_init(stream, param);
|
||||
if (ret) {
|
||||
while (param->num_syncs--)
|
||||
xe_sync_entry_cleanup(¶m->syncs[param->num_syncs]);
|
||||
kfree(param->syncs);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (!param->disabled) {
|
||||
ret = xe_oa_enable_locked(stream);
|
||||
if (ret)
|
||||
@@ -1871,6 +1892,8 @@ err_destroy:
|
||||
xe_oa_stream_destroy(stream);
|
||||
err_free:
|
||||
kfree(stream);
|
||||
err_syncobj:
|
||||
drm_syncobj_put(ufence_syncobj);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
@@ -2084,22 +2107,14 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
|
||||
goto err_exec_q;
|
||||
}
|
||||
|
||||
ret = xe_oa_parse_syncs(oa, ¶m);
|
||||
if (ret)
|
||||
goto err_exec_q;
|
||||
|
||||
mutex_lock(¶m.hwe->gt->oa.gt_lock);
|
||||
ret = xe_oa_stream_open_ioctl_locked(oa, ¶m);
|
||||
mutex_unlock(¶m.hwe->gt->oa.gt_lock);
|
||||
if (ret < 0)
|
||||
goto err_sync_cleanup;
|
||||
goto err_exec_q;
|
||||
|
||||
return ret;
|
||||
|
||||
err_sync_cleanup:
|
||||
while (param.num_syncs--)
|
||||
xe_sync_entry_cleanup(¶m.syncs[param.num_syncs]);
|
||||
kfree(param.syncs);
|
||||
err_exec_q:
|
||||
if (param.exec_q)
|
||||
xe_exec_queue_put(param.exec_q);
|
||||
|
||||
Reference in New Issue
Block a user