Driver Changes:

- Fix missing  synchronization on unbind (Balasubramani Vivekanandan)
  - Fix device shutdown when doing FLR (Jouni Högander)
  - Fix user fence signaling order (Matthew Brost)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE6rM8lpABPHM5FqyDm6KlpjDL6lMFAmkOCr8ACgkQm6KlpjDL
 6lMEfxAAjjzVskX6riDg9s03Ko1yacMjPT/HWai4KByN6RL1Iyxh0OZjkenDYheQ
 BnX/Kv0PgO8tfQsY3KXsej8m+4A/JsN0Hh4u3sbDpYLIDvVDCHZEg9pgiBcGEG4O
 79pZaNMtAZ5BYaCHxbzVqvrZHLoeHA4ncMhQBUG3TOSWYrVK5BJRFgZ7bIIAwKgj
 7RXnPEpim+7X1dXmHRc5MNsT3F6MRGWyPocppcJTYF0JjOknOPJzw5la3r2tX2n7
 Bp4Q8Pt2RjLUyo8WycvZ/+4TS9FiRWG1zvFQ2ATdir2EIC+DbUxtgTlS1xcHui7W
 /9T4Fjy8NB09BVJzPP+YjqQGmxACsm+rpq6PGi1UfZy2VuaoE0XL4/P2QDUca9iC
 S4e5Z0jGgZnzuUeuhF2KO6GSQxuoB6sIEtMLCow6T7Rhe2CF7WpttpagZjjLDo3r
 d2v2mPV8Pcimd/ff3nxLaHEFqFiqU9+voG8/wNSF1GMi0LiMy9seyHc5ZlJkSHbH
 IJUDvT/3U/oRrB/1C+jbuPjMjaK3aBANBqp0uUutpQ8wsbawjFlaK5td2O3rb7ti
 9mLUq0NH/aRRgPMHa7KpDMYCtZiq766YMySwg1TFiKDJXfUEyepQUYMwr0qM8sQY
 OMvInchAMYpupDLntxsW0P1TYO1ebFHsQd586l5DNd6OynycnmA=
 =lRRA
 -----END PGP SIGNATURE-----

Merge tag 'drm-xe-fixes-2025-11-07' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes

Driver Changes:
 - Fix missing  synchronization on unbind (Balasubramani Vivekanandan)
 - Fix device shutdown when doing FLR (Jouni Högander)
 - Fix user fence signaling order (Matthew Brost)

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://patch.msgid.link/mvfyflloncy76a7nmkatpj6f2afddavwsibz3y4u4wo6gznro5@rdulkuh5wvje
This commit is contained in:
Dave Airlie 2025-11-08 07:39:11 +10:00
commit d439acbbfb
11 changed files with 96 additions and 25 deletions

View File

@ -988,7 +988,6 @@ void xe_device_shutdown(struct xe_device *xe)
drm_dbg(&xe->drm, "Shutting down device\n");
if (xe_driver_flr_disabled(xe)) {
xe_display_pm_shutdown(xe);
xe_irq_suspend(xe);
@ -997,7 +996,8 @@ void xe_device_shutdown(struct xe_device *xe)
xe_gt_shutdown(gt);
xe_display_pm_shutdown_late(xe);
} else {
if (!xe_driver_flr_disabled(xe)) {
/* BOOM! */
__xe_driver_flr(xe);
}

View File

@ -165,7 +165,8 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) {
err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs],
&syncs_user[num_syncs], SYNC_PARSE_FLAG_EXEC |
&syncs_user[num_syncs], NULL, 0,
SYNC_PARSE_FLAG_EXEC |
(xe_vm_in_lr_mode(vm) ?
SYNC_PARSE_FLAG_LR_MODE : 0));
if (err)

View File

@ -10,6 +10,7 @@
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_syncobj.h>
#include <uapi/drm/xe_drm.h>
#include "xe_dep_scheduler.h"
@ -324,6 +325,16 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
}
xe_vm_put(migrate_vm);
if (!IS_ERR(q)) {
int err = drm_syncobj_create(&q->ufence_syncobj,
DRM_SYNCOBJ_CREATE_SIGNALED,
NULL);
if (err) {
xe_exec_queue_put(q);
return ERR_PTR(err);
}
}
return q;
}
ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO);
@ -333,6 +344,9 @@ void xe_exec_queue_destroy(struct kref *ref)
struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount);
struct xe_exec_queue *eq, *next;
if (q->ufence_syncobj)
drm_syncobj_put(q->ufence_syncobj);
if (xe_exec_queue_uses_pxp(q))
xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);

View File

@ -15,6 +15,7 @@
#include "xe_hw_fence_types.h"
#include "xe_lrc_types.h"
struct drm_syncobj;
struct xe_execlist_exec_queue;
struct xe_gt;
struct xe_guc_exec_queue;
@ -155,6 +156,12 @@ struct xe_exec_queue {
struct list_head link;
} pxp;
/** @ufence_syncobj: User fence syncobj */
struct drm_syncobj *ufence_syncobj;
/** @ufence_timeline_value: User fence timeline value */
u64 ufence_timeline_value;
/** @ops: submission backend exec queue operations */
const struct xe_exec_queue_ops *ops;

View File

@ -200,6 +200,9 @@ static void guc_ct_fini(struct drm_device *drm, void *arg)
{
struct xe_guc_ct *ct = arg;
#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
cancel_work_sync(&ct->dead.worker);
#endif
ct_exit_safe_mode(ct);
destroy_workqueue(ct->g2h_wq);
xa_destroy(&ct->fence_lookup);

View File

@ -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>
@ -1389,7 +1390,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;
@ -1409,7 +1412,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, &param->syncs[num_syncs],
&param->syncs_user[num_syncs], 0);
&param->syncs_user[num_syncs],
stream->ufence_syncobj,
++stream->ufence_timeline_value, 0);
if (ret)
goto err_syncs;
@ -1539,7 +1544,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, &param);
err = xe_oa_parse_syncs(stream->oa, stream, &param);
if (err)
goto err_config_put;
@ -1635,6 +1640,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);
}
@ -1826,6 +1832,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;
@ -1836,17 +1843,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(&param->syncs[param->num_syncs]);
kfree(param->syncs);
goto err_free;
}
if (!param->disabled) {
ret = xe_oa_enable_locked(stream);
if (ret)
@ -1870,6 +1891,8 @@ static int xe_oa_stream_open_ioctl_locked(struct xe_oa *oa,
xe_oa_stream_destroy(stream);
err_free:
kfree(stream);
err_syncobj:
drm_syncobj_put(ufence_syncobj);
exit:
return ret;
}
@ -2083,22 +2106,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, &param);
if (ret)
goto err_exec_q;
mutex_lock(&param.hwe->gt->oa.gt_lock);
ret = xe_oa_stream_open_ioctl_locked(oa, &param);
mutex_unlock(&param.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(&param.syncs[param.num_syncs]);
kfree(param.syncs);
err_exec_q:
if (param.exec_q)
xe_exec_queue_put(param.exec_q);

View File

@ -15,6 +15,8 @@
#include "regs/xe_reg_defs.h"
#include "xe_hw_engine_types.h"
struct drm_syncobj;
#define DEFAULT_XE_OA_BUFFER_SIZE SZ_16M
enum xe_oa_report_header {
@ -248,6 +250,12 @@ struct xe_oa_stream {
/** @xef: xe_file with which the stream was opened */
struct xe_file *xef;
/** @ufence_syncobj: User fence syncobj */
struct drm_syncobj *ufence_syncobj;
/** @ufence_timeline_value: User fence timeline value */
u64 ufence_timeline_value;
/** @last_fence: fence to use in stream destroy when needed */
struct dma_fence *last_fence;

View File

@ -113,6 +113,8 @@ static void user_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
struct xe_sync_entry *sync,
struct drm_xe_sync __user *sync_user,
struct drm_syncobj *ufence_syncobj,
u64 ufence_timeline_value,
unsigned int flags)
{
struct drm_xe_sync sync_in;
@ -192,10 +194,15 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
if (exec) {
sync->addr = sync_in.addr;
} else {
sync->ufence_timeline_value = ufence_timeline_value;
sync->ufence = user_fence_create(xe, sync_in.addr,
sync_in.timeline_value);
if (XE_IOCTL_DBG(xe, IS_ERR(sync->ufence)))
return PTR_ERR(sync->ufence);
sync->ufence_chain_fence = dma_fence_chain_alloc();
if (!sync->ufence_chain_fence)
return -ENOMEM;
sync->ufence_syncobj = ufence_syncobj;
}
break;
@ -239,7 +246,12 @@ void xe_sync_entry_signal(struct xe_sync_entry *sync, struct dma_fence *fence)
} else if (sync->ufence) {
int err;
dma_fence_get(fence);
drm_syncobj_add_point(sync->ufence_syncobj,
sync->ufence_chain_fence,
fence, sync->ufence_timeline_value);
sync->ufence_chain_fence = NULL;
fence = drm_syncobj_fence_get(sync->ufence_syncobj);
user_fence_get(sync->ufence);
err = dma_fence_add_callback(fence, &sync->ufence->cb,
user_fence_cb);
@ -259,7 +271,8 @@ void xe_sync_entry_cleanup(struct xe_sync_entry *sync)
drm_syncobj_put(sync->syncobj);
dma_fence_put(sync->fence);
dma_fence_chain_free(sync->chain_fence);
if (sync->ufence)
dma_fence_chain_free(sync->ufence_chain_fence);
if (!IS_ERR_OR_NULL(sync->ufence))
user_fence_put(sync->ufence);
}

View File

@ -8,6 +8,7 @@
#include "xe_sync_types.h"
struct drm_syncobj;
struct xe_device;
struct xe_exec_queue;
struct xe_file;
@ -21,6 +22,8 @@ struct xe_vm;
int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
struct xe_sync_entry *sync,
struct drm_xe_sync __user *sync_user,
struct drm_syncobj *ufence_syncobj,
u64 ufence_timeline_value,
unsigned int flags);
int xe_sync_entry_add_deps(struct xe_sync_entry *sync,
struct xe_sched_job *job);

View File

@ -18,9 +18,12 @@ struct xe_sync_entry {
struct drm_syncobj *syncobj;
struct dma_fence *fence;
struct dma_fence_chain *chain_fence;
struct dma_fence_chain *ufence_chain_fence;
struct drm_syncobj *ufence_syncobj;
struct xe_user_fence *ufence;
u64 addr;
u64 timeline_value;
u64 ufence_timeline_value;
u32 type;
u32 flags;
};

View File

@ -3606,8 +3606,12 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
syncs_user = u64_to_user_ptr(args->syncs);
for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) {
struct xe_exec_queue *__q = q ?: vm->q[0];
err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs],
&syncs_user[num_syncs],
__q->ufence_syncobj,
++__q->ufence_timeline_value,
(xe_vm_in_lr_mode(vm) ?
SYNC_PARSE_FLAG_LR_MODE : 0) |
(!args->num_binds ?