mirror of https://github.com/torvalds/linux.git
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:
commit
d439acbbfb
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, ¶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;
|
||||
|
||||
|
|
@ -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, ¶m);
|
||||
err = xe_oa_parse_syncs(stream->oa, stream, ¶m);
|
||||
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(¶m->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, ¶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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 ?
|
||||
|
|
|
|||
Loading…
Reference in New Issue