From: Jiwoo Kim <arpe1618@gmail.com>
To: Rob Clark <robin.clark@oss.qualcomm.com>,
Dmitry Baryshkov <lumag@kernel.org>
Cc: Akhil P Oommen <akhilpo@oss.qualcomm.com>,
Konrad Dybcio <konradybcio@kernel.org>,
Antonino Maniscalco <antomani103@gmail.com>,
Abhinav Kumar <abhinav.kumar@linux.dev>,
Jessica Zhang <jesszhan0024@gmail.com>,
Sean Paul <sean@poorly.run>,
Marijn Suijten <marijn.suijten@somainline.org>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org,
freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH v2 2/3] drm/msm: Destroy the VM_BIND entity when its queue is closed
Date: Sat, 14 Nov 2026 17:19:01 +0900 [thread overview]
Message-ID: <20261114081902.1669-3-arpe1618@gmail.com> (raw)
In-Reply-To: <20261114081902.1669-1-arpe1618@gmail.com>
The entity of a VM_BIND submitqueue is attached to the per-VM scheduler,
and msm_gem_vm_close() calls drm_sched_fini() on that scheduler when the
file is closed, which frees its run queues. The submitqueue itself is
only destroyed on its final put, though, and every VM_BIND job holds a
reference to it. msm_submitqueue_close() only flushes the entity, and a
queue that was closed earlier with MSM_SUBMITQUEUE_CLOSE is not flushed
at all.
The flush gives up after a timeout when the process exits, or on a
fatal signal, and it only kills the queued jobs when the process exits
because of SIGKILL. In these cases, and after MSM_SUBMITQUEUE_CLOSE,
the entity can still have a callback armed on the in-fence of a
VM_BIND job when drm_sched_fini() runs. When that fence signals,
drm_sched_entity_wakeup() dereferences entity->rq->sched, and so reads
a run queue that drm_sched_fini() has freed. If the jobs were killed,
the final put of the queue then calls drm_sched_entity_destroy(), which
reads the same freed run queue in drm_sched_entity_flush(). If they
were not, they never run, and keep the queue, its context and the VM
alive.
Destroy the VM_BIND entity when userspace closes the queue, on file
close or with MSM_SUBMITQUEUE_CLOSE, instead of on the final put, and
refuse new VM_BIND jobs on a closed queue. In the MSM_SUBMITQUEUE_CLOSE
path, do it after dropping ctxlock, as destroying the entity waits for
the jobs queued on it.
As a result, MSM_SUBMITQUEUE_CLOSE on a VM_BIND queue now waits
(killably) for the jobs already queued on it, and a fatal signal during
that wait cancels the remaining ones, where they used to still run. On
file close, the jobs still queued when the wait gives up are now always
cancelled, as they already were when the process was killed while
exiting, instead of being left on the entity. With the previous patch,
such jobs apply their unmaps and release their pins and references.
This was found with an AI coding assistant, which also drafted this
patch and its changelog. It has not been reproduced, and the change
has only been compile-tested.
Fixes: 92395af63a99 ("drm/msm: Add VM_BIND submitqueue")
Cc: stable@vger.kernel.org
Signed-off-by: Jiwoo Kim <arpe1618@gmail.com>
---
The scoped_guard() in msm_submitqueue_remove() relies on commit
ea69d489d3a6 ("drm/msm: Rework queuelock"), so trees older than v7.3
need a manual backport.
If MSM_SUBMITQUEUE_CLOSE should rather not block, the destroy of closed
VM_BIND queues could instead be deferred to file close, e.g. with a
per-context list of them.
drivers/gpu/drm/msm/msm_gem_vma.c | 5 +++
drivers/gpu/drm/msm/msm_gpu.h | 6 ++++
drivers/gpu/drm/msm/msm_submitqueue.c | 50 +++++++++++++++++++--------
3 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index a6f106d0cdef..b1fa1d749c2f 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -1532,6 +1532,11 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file)
if (ret)
goto out_post_unlock;
+ if (queue->vm_bind_closed) {
+ ret = -ENOENT;
+ goto out_unlock;
+ }
+
if (args->flags & MSM_VM_BIND_FENCE_FD_IN) {
struct dma_fence *in_fence;
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index bc5b31eb1eca..561f2d998e99 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -596,6 +596,12 @@ struct msm_gpu_submitqueue {
struct kref ref;
struct drm_sched_entity *entity;
+ /**
+ * @vm_bind_closed: the queue was closed by userspace, and its VM_BIND
+ * entity is being or has been destroyed. Protected by @lock.
+ */
+ bool vm_bind_closed;
+
/** @_vm_bind_entity: used for @entity pointer for VM_BIND queues */
struct drm_sched_entity _vm_bind_entity[0];
};
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
index 8d550d281704..2dbe42551bd8 100644
--- a/drivers/gpu/drm/msm/msm_submitqueue.c
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -79,9 +79,6 @@ void msm_submitqueue_destroy(struct kref *kref)
idr_destroy(&queue->fence_idr);
- if (queue->entity == &queue->_vm_bind_entity[0])
- drm_sched_entity_destroy(queue->entity);
-
msm_context_put(queue->ctx);
kfree(queue);
@@ -107,6 +104,25 @@ struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_context *ctx,
return NULL;
}
+/*
+ * The VM_BIND scheduler is torn down by msm_gem_vm_close() when the file is
+ * closed, but a VM_BIND queue can outlive that, as long as a job still holds
+ * a reference to it. So destroy the VM_BIND entity here, when userspace
+ * closes the queue, rather than on the final put. Both ways a queue is taken
+ * off ctx->submitqueues come through here.
+ */
+static void msm_submitqueue_close_vm_bind(struct msm_gpu_submitqueue *queue)
+{
+ if (queue->entity != &queue->_vm_bind_entity[0])
+ return;
+
+ mutex_lock(&queue->lock);
+ queue->vm_bind_closed = true;
+ mutex_unlock(&queue->lock);
+
+ drm_sched_entity_destroy(queue->entity);
+}
+
void msm_submitqueue_close(struct msm_context *ctx)
{
struct msm_gpu_submitqueue *queue, *tmp;
@@ -119,8 +135,7 @@ void msm_submitqueue_close(struct msm_context *ctx)
* be any more user ioctls coming our way
*/
list_for_each_entry_safe(queue, tmp, &ctx->submitqueues, node) {
- if (queue->entity == &queue->_vm_bind_entity[0])
- drm_sched_entity_flush(queue->entity, MAX_WAIT_SCHED_ENTITY_Q_EMPTY);
+ msm_submitqueue_close_vm_bind(queue);
list_del(&queue->node);
msm_submitqueue_put(queue);
}
@@ -326,7 +341,7 @@ int msm_submitqueue_query(struct drm_device *drm, struct msm_context *ctx,
int msm_submitqueue_remove(struct msm_context *ctx, u32 id)
{
- struct msm_gpu_submitqueue *entry;
+ struct msm_gpu_submitqueue *entry, *queue = NULL;
if (!ctx)
return 0;
@@ -338,16 +353,23 @@ int msm_submitqueue_remove(struct msm_context *ctx, u32 id)
if (!id)
return -ENOENT;
- guard(rwsem_write)(&ctx->ctxlock);
-
- list_for_each_entry(entry, &ctx->submitqueues, node) {
- if (entry->id == id) {
- list_del(&entry->node);
- msm_submitqueue_put(entry);
- return 0;
+ scoped_guard(rwsem_write, &ctx->ctxlock) {
+ list_for_each_entry(entry, &ctx->submitqueues, node) {
+ if (entry->id == id) {
+ list_del(&entry->node);
+ queue = entry;
+ break;
+ }
}
}
- return -ENOENT;
+ if (!queue)
+ return -ENOENT;
+
+ /* Not under ctxlock: destroying the entity can wait for its jobs */
+ msm_submitqueue_close_vm_bind(queue);
+ msm_submitqueue_put(queue);
+
+ return 0;
}
--
2.43.0
next prev parent reply other threads:[~2026-11-14 8:19 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 8:18 [PATCH v2 0/3] drm/msm: Fix VM_BIND job, queue and entity lifetimes Jiwoo Kim
2026-11-14 8:19 ` [PATCH v2 1/3] drm/msm: Release the pins and ops of a VM_BIND job that never ran Jiwoo Kim
2026-11-14 8:57 ` sashiko-bot
2026-11-14 8:19 ` Jiwoo Kim [this message]
2026-11-14 8:19 ` [PATCH v2 3/3] drm/msm: Put the VM_BIND queue last in msm_vma_job_free() Jiwoo Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261114081902.1669-3-arpe1618@gmail.com \
--to=arpe1618@gmail.com \
--cc=abhinav.kumar@linux.dev \
--cc=airlied@gmail.com \
--cc=akhilpo@oss.qualcomm.com \
--cc=antomani103@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=freedreno@lists.freedesktop.org \
--cc=jesszhan0024@gmail.com \
--cc=konradybcio@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lumag@kernel.org \
--cc=marijn.suijten@somainline.org \
--cc=robin.clark@oss.qualcomm.com \
--cc=sean@poorly.run \
--cc=simona@ffwll.ch \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.