* FAILED: patch "[PATCH] drm/xe: Wait on external BO kernel fences in exec IOCTL" failed to apply to 6.12-stable tree
@ 2026-07-29 11:09 gregkh
2026-08-01 23:43 ` [PATCH 6.12.y 1/2] drm/exec: Remove the index parameter from drm_exec_for_each_locked_obj[_reverse] Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: gregkh @ 2026-07-29 11:09 UTC (permalink / raw)
To: matthew.brost, matthew.auld, thomas.hellstrom; +Cc: stable
The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x af80e2bfde9312c76b60cf9274248dce0410b30d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026072911-surplus-properly-117b@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From af80e2bfde9312c76b60cf9274248dce0410b30d Mon Sep 17 00:00:00 2001
From: Matthew Brost <matthew.brost@intel.com>
Date: Thu, 2 Jul 2026 14:58:05 -0700
Subject: [PATCH] drm/xe: Wait on external BO kernel fences in exec IOCTL
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Before arming a user job, xe_exec_ioctl() only added the VM's
dma-resv KERNEL slot as a dependency. That slot covers rebinds and
the kernel operations of the VM's private BOs, but not external BOs
(bo->vm == NULL), which carry their kernel operations (evictions,
moves, ...) in their own dma-resv KERNEL slot.
The DMA_RESV_USAGE_KERNEL slot is the cross-driver contract for
memory management operations that must complete before the BO or its
backing store may be used: any accessor is required to wait on the
KERNEL fences before touching the resv. By skipping the external BOs'
KERNEL slots, the exec path violated that contract and could schedule
a user job while a kernel operation on an external BO mapped by the VM
was still in flight, racing against it and potentially reading or
writing memory that was being moved.
Replace the VM-only dependency with an iteration over every object
locked by the exec, adding each object's KERNEL slot as a job
dependency. This covers the VM resv (rebinds and private BOs) as well
as every external BO, mirroring the drm_gpuvm_resv_add_fence() call
that later publishes the job fence to the same set of objects.
Long-running mode continues to skip this, as before.
Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Cc: stable@vger.kernel.org
Assisted-by: GitHub_Copilot:claude-opus-4.8
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patch.msgid.link/20260702215805.4011228-1-matthew.brost@intel.com
(cherry picked from commit a6b842acf3ddd1efc53a56de9260cfa718fb35e7)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index e05dabfcd43c..d5293bc33a67 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -292,13 +292,23 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
goto err_exec;
}
- /* Wait behind rebinds */
+ /*
+ * Wait behind rebinds and any kernel operations (evictions, defrag
+ * moves, ...) on the VM and all external BOs. The VM's private BOs
+ * carry their kernel ops in the VM dma-resv KERNEL slot, while each
+ * external BO carries them in its own dma-resv KERNEL slot; both are
+ * covered by iterating every object locked by the exec, mirroring the
+ * drm_gpuvm_resv_add_fence() below.
+ */
if (!xe_vm_in_lr_mode(vm)) {
- err = xe_sched_job_add_deps(job,
- xe_vm_resv(vm),
- DMA_RESV_USAGE_KERNEL);
- if (err)
- goto err_put_job;
+ struct drm_gem_object *obj;
+
+ drm_exec_for_each_locked_object(exec, obj) {
+ err = xe_sched_job_add_deps(job, obj->resv,
+ DMA_RESV_USAGE_KERNEL);
+ if (err)
+ goto err_put_job;
+ }
}
for (i = 0; i < num_syncs && !err; i++)
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 6.12.y 1/2] drm/exec: Remove the index parameter from drm_exec_for_each_locked_obj[_reverse]
2026-07-29 11:09 FAILED: patch "[PATCH] drm/xe: Wait on external BO kernel fences in exec IOCTL" failed to apply to 6.12-stable tree gregkh
@ 2026-08-01 23:43 ` Sasha Levin
2026-08-01 23:43 ` [PATCH 6.12.y 2/2] drm/xe: Wait on external BO kernel fences in exec IOCTL Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-08-01 23:43 UTC (permalink / raw)
To: stable; +Cc: Thomas Hellström, Christian König, Sasha Levin
From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
[ Upstream commit ce44b78512e9102aea54ff6b6e521d6c8de9f31c ]
Nobody makes any use of it. Possible internal future users can
instead use the _index variable. External users shouldn't use
it since the array it's pointing into is internal drm_exec state.
v2:
- Use a unique id for the loop variable (Christian)
Assisted-by: GitHub Copilot:claude-sonnet-4.6
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Link: https://patch.msgid.link/20260520101616.41284-2-thomas.hellstrom@linux.intel.com
Stable-dep-of: af80e2bfde93 ("drm/xe: Wait on external BO kernel fences in exec IOCTL")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 9 +++------
drivers/gpu/drm/drm_exec.c | 6 ++----
drivers/gpu/drm/drm_gpuvm.c | 3 +--
drivers/gpu/drm/xe/xe_vm.c | 3 +--
include/drm/drm_exec.h | 20 ++++++++++++--------
5 files changed, 19 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index e018a807e4e3..eb94e7891c2a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -843,7 +843,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_bo_list_entry *e;
struct drm_gem_object *obj;
- unsigned long index;
unsigned int i;
int r;
@@ -964,7 +963,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
goto out_free_user_pages;
}
- drm_exec_for_each_locked_object(&p->exec, index, obj) {
+ drm_exec_for_each_locked_object(&p->exec, obj) {
r = amdgpu_cs_bo_validate(p, gem_to_amdgpu_bo(obj));
if (unlikely(r))
goto out_free_user_pages;
@@ -1202,7 +1201,6 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
struct drm_gpu_scheduler *sched;
struct drm_gem_object *obj;
struct dma_fence *fence;
- unsigned long index;
unsigned int i;
int r;
@@ -1213,7 +1211,7 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
return r;
}
- drm_exec_for_each_locked_object(&p->exec, index, obj) {
+ drm_exec_for_each_locked_object(&p->exec, obj) {
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
struct dma_resv *resv = bo->tbo.base.resv;
@@ -1281,7 +1279,6 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_bo_list_entry *e;
struct drm_gem_object *gobj;
- unsigned long index;
unsigned int i;
uint64_t seq;
int r;
@@ -1332,7 +1329,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
}
p->fence = dma_fence_get(&leader->base.s_fence->finished);
- drm_exec_for_each_locked_object(&p->exec, index, gobj) {
+ drm_exec_for_each_locked_object(&p->exec, gobj) {
ttm_bo_move_to_lru_tail_unlocked(&gem_to_amdgpu_bo(gobj)->tbo);
diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c
index 18e366cc4993..6c1351cd7f15 100644
--- a/drivers/gpu/drm/drm_exec.c
+++ b/drivers/gpu/drm/drm_exec.c
@@ -22,7 +22,6 @@
*
* struct drm_gem_object *obj;
* struct drm_exec exec;
- * unsigned long index;
* int ret;
*
* drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
@@ -38,7 +37,7 @@
* goto error;
* }
*
- * drm_exec_for_each_locked_object(&exec, index, obj) {
+ * drm_exec_for_each_locked_object(&exec, obj) {
* dma_resv_add_fence(obj->resv, fence, DMA_RESV_USAGE_READ);
* ...
* }
@@ -54,9 +53,8 @@
static void drm_exec_unlock_all(struct drm_exec *exec)
{
struct drm_gem_object *obj;
- unsigned long index;
- drm_exec_for_each_locked_object_reverse(exec, index, obj) {
+ drm_exec_for_each_locked_object_reverse(exec, obj) {
dma_resv_unlock(obj->resv);
drm_gem_object_put(obj);
}
diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c
index 2515cff33485..338a21a58ec5 100644
--- a/drivers/gpu/drm/drm_gpuvm.c
+++ b/drivers/gpu/drm/drm_gpuvm.c
@@ -1451,9 +1451,8 @@ drm_gpuvm_resv_add_fence(struct drm_gpuvm *gpuvm,
enum dma_resv_usage extobj_usage)
{
struct drm_gem_object *obj;
- unsigned long index;
- drm_exec_for_each_locked_object(exec, index, obj) {
+ drm_exec_for_each_locked_object(exec, obj) {
dma_resv_assert_held(obj->resv);
dma_resv_add_fence(obj->resv, fence,
drm_gpuvm_is_extobj(gpuvm, obj) ?
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 7ce6a9d4e5c1..deb4d0314db3 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -418,7 +418,6 @@ int xe_vm_validate_rebind(struct xe_vm *vm, struct drm_exec *exec,
unsigned int num_fences)
{
struct drm_gem_object *obj;
- unsigned long index;
int ret;
do {
@@ -431,7 +430,7 @@ int xe_vm_validate_rebind(struct xe_vm *vm, struct drm_exec *exec,
return ret;
} while (!list_empty(&vm->gpuvm.evict.list));
- drm_exec_for_each_locked_object(exec, index, obj) {
+ drm_exec_for_each_locked_object(exec, obj) {
ret = dma_resv_reserve_fences(obj->resv, num_fences);
if (ret)
return ret;
diff --git a/include/drm/drm_exec.h b/include/drm/drm_exec.h
index aa786b828a0a..dee6ebdbe416 100644
--- a/include/drm/drm_exec.h
+++ b/include/drm/drm_exec.h
@@ -65,31 +65,35 @@ drm_exec_obj(struct drm_exec *exec, unsigned long index)
return index < exec->num_objects ? exec->objects[index] : NULL;
}
+/* Helper for drm_exec_for_each_locked_object(). Internal use only. */
+#define __drm_exec_for_each_locked_object(exec, obj, __index) \
+ for (unsigned long __index = 0; ((obj) = drm_exec_obj(exec, __index)); ++__index)
/**
* drm_exec_for_each_locked_object - iterate over all the locked objects
* @exec: drm_exec object
- * @index: unsigned long index for the iteration
* @obj: the current GEM object
*
* Iterate over all the locked GEM objects inside the drm_exec object.
*/
-#define drm_exec_for_each_locked_object(exec, index, obj) \
- for ((index) = 0; ((obj) = drm_exec_obj(exec, index)); ++(index))
+#define drm_exec_for_each_locked_object(exec, obj) \
+ __drm_exec_for_each_locked_object(exec, obj, __UNIQUE_ID(drm_exec))
+/* Helper for drm_exec_for_each_locked_object_reverse(). Internal use only. */
+#define __drm_exec_for_each_locked_object_reverse(exec, obj, __index) \
+ for (unsigned long __index = (exec)->num_objects - 1; \
+ ((obj) = drm_exec_obj(exec, __index)); --__index)
/**
* drm_exec_for_each_locked_object_reverse - iterate over all the locked
* objects in reverse locking order
* @exec: drm_exec object
- * @index: unsigned long index for the iteration
* @obj: the current GEM object
*
* Iterate over all the locked GEM objects inside the drm_exec object in
- * reverse locking order. Note that @index may go below zero and wrap,
+ * reverse locking order. Note that the internal index may wrap around,
* but that will be caught by drm_exec_obj(), returning a NULL object.
*/
-#define drm_exec_for_each_locked_object_reverse(exec, index, obj) \
- for ((index) = (exec)->num_objects - 1; \
- ((obj) = drm_exec_obj(exec, index)); --(index))
+#define drm_exec_for_each_locked_object_reverse(exec, obj) \
+ __drm_exec_for_each_locked_object_reverse(exec, obj, __UNIQUE_ID(drm_exec))
/**
* drm_exec_until_all_locked - loop until all GEM objects are locked
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 6.12.y 2/2] drm/xe: Wait on external BO kernel fences in exec IOCTL
2026-08-01 23:43 ` [PATCH 6.12.y 1/2] drm/exec: Remove the index parameter from drm_exec_for_each_locked_obj[_reverse] Sasha Levin
@ 2026-08-01 23:43 ` Sasha Levin
0 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-08-01 23:43 UTC (permalink / raw)
To: stable; +Cc: Matthew Brost, Matthew Auld, Thomas Hellström, Sasha Levin
From: Matthew Brost <matthew.brost@intel.com>
[ Upstream commit af80e2bfde9312c76b60cf9274248dce0410b30d ]
Before arming a user job, xe_exec_ioctl() only added the VM's
dma-resv KERNEL slot as a dependency. That slot covers rebinds and
the kernel operations of the VM's private BOs, but not external BOs
(bo->vm == NULL), which carry their kernel operations (evictions,
moves, ...) in their own dma-resv KERNEL slot.
The DMA_RESV_USAGE_KERNEL slot is the cross-driver contract for
memory management operations that must complete before the BO or its
backing store may be used: any accessor is required to wait on the
KERNEL fences before touching the resv. By skipping the external BOs'
KERNEL slots, the exec path violated that contract and could schedule
a user job while a kernel operation on an external BO mapped by the VM
was still in flight, racing against it and potentially reading or
writing memory that was being moved.
Replace the VM-only dependency with an iteration over every object
locked by the exec, adding each object's KERNEL slot as a job
dependency. This covers the VM resv (rebinds and private BOs) as well
as every external BO, mirroring the drm_gpuvm_resv_add_fence() call
that later publishes the job fence to the same set of objects.
Long-running mode continues to skip this, as before.
Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Cc: stable@vger.kernel.org
Assisted-by: GitHub_Copilot:claude-opus-4.8
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patch.msgid.link/20260702215805.4011228-1-matthew.brost@intel.com
(cherry picked from commit a6b842acf3ddd1efc53a56de9260cfa718fb35e7)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/xe_exec.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index 886d03ccf744..04a88c16d835 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -270,13 +270,23 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
goto err_exec;
}
- /* Wait behind rebinds */
+ /*
+ * Wait behind rebinds and any kernel operations (evictions, defrag
+ * moves, ...) on the VM and all external BOs. The VM's private BOs
+ * carry their kernel ops in the VM dma-resv KERNEL slot, while each
+ * external BO carries them in its own dma-resv KERNEL slot; both are
+ * covered by iterating every object locked by the exec, mirroring the
+ * drm_gpuvm_resv_add_fence() below.
+ */
if (!xe_vm_in_lr_mode(vm)) {
- err = xe_sched_job_add_deps(job,
- xe_vm_resv(vm),
- DMA_RESV_USAGE_KERNEL);
- if (err)
- goto err_put_job;
+ struct drm_gem_object *obj;
+
+ drm_exec_for_each_locked_object(exec, obj) {
+ err = xe_sched_job_add_deps(job, obj->resv,
+ DMA_RESV_USAGE_KERNEL);
+ if (err)
+ goto err_put_job;
+ }
}
for (i = 0; i < num_syncs && !err; i++)
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-01 23:43 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 11:09 FAILED: patch "[PATCH] drm/xe: Wait on external BO kernel fences in exec IOCTL" failed to apply to 6.12-stable tree gregkh
2026-08-01 23:43 ` [PATCH 6.12.y 1/2] drm/exec: Remove the index parameter from drm_exec_for_each_locked_obj[_reverse] Sasha Levin
2026-08-01 23:43 ` [PATCH 6.12.y 2/2] drm/xe: Wait on external BO kernel fences in exec IOCTL Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.