From: Karl Mehltretter <kmehltretter@gmail.com>
To: "Michael S. Tsirkin" <mst@redhat.com>,
Jason Wang <jasowangio@gmail.com>,
Gerd Hoffmann <kraxel@redhat.com>
Cc: "Karl Mehltretter" <kmehltretter@gmail.com>,
"Xuan Zhuo" <xuanzhuo@linux.alibaba.com>,
"Eugenio Pérez" <eperezma@redhat.com>,
"Dmitry Torokhov" <dmitry.torokhov@gmail.com>,
"Rusty Russell" <rusty@rustcorp.com.au>,
"Pawel Moll" <pawel.moll@arm.com>,
"Cornelia Huck" <cohuck@redhat.com>,
"Halil Pasic" <pasic@linux.ibm.com>,
"Eric Farman" <farman@linux.ibm.com>,
"Richard Weinberger" <richard@nod.at>,
"Anton Ivanov" <anton.ivanov@cambridgegreys.com>,
"Johannes Berg" <johannes@sipsolutions.net>,
"Hans de Goede" <hansg@kernel.org>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Vadim Pasternak" <vadimp@nvidia.com>,
"Bjorn Andersson" <andersson@kernel.org>,
"Mathieu Poirier" <mathieu.poirier@linaro.org>,
virtualization@lists.linux.dev, linux-input@vger.kernel.org,
linux-s390@vger.kernel.org, kvm@vger.kernel.org,
linux-um@lists.infradead.org,
platform-driver-x86@vger.kernel.org,
linux-remoteproc@vger.kernel.org, linux-kernel@vger.kernel.org,
"Heiko Carstens" <hca@linux.ibm.com>,
"Vasily Gorbik" <gor@linux.ibm.com>,
"Alexander Gordeev" <agordeev@linux.ibm.com>,
"Christian Borntraeger" <borntraeger@linux.ibm.com>,
"Sven Schnelle" <svens@linux.ibm.com>
Subject: [PATCH v3 3/6] remoteproc: implement synchronize_cbs() for virtio devices
Date: Tue, 8 Sep 2026 07:38:14 +0200 [thread overview]
Message-ID: <20260908053817.26065-4-kmehltretter@gmail.com> (raw)
In-Reply-To: <20260908053817.26065-1-kmehltretter@gmail.com>
Platform drivers invoke rproc_vq_interrupt() from hard-IRQ handlers,
threaded handlers, and work items. Because rpmsg callbacks may sleep,
the virtio core's synchronize_rcu() fallback does not synchronize with
callbacks across all these contexts. A device reset can therefore
complete while a callback is still running.
Add an SRCU domain per rproc. Protect both the queue lookup and
vring_interrupt() with it, and synchronize the domain in the new hook.
__rproc_virtio_del_vqs() can race with rproc_vq_interrupt() too. Clear
all queue pointers and synchronize the SRCU domain before freeing the
queues, so callers that already found a queue can finish using it.
Read rvring->vq once to avoid a second load after deletion starts.
The SRCU domain has the same lifetime as struct rproc. Its cleanup can
sleep, so document that rproc_free() and rproc_put() must not drop the
last reference from atomic context.
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
drivers/remoteproc/remoteproc_core.c | 12 ++++++++
drivers/remoteproc/remoteproc_virtio.c | 37 +++++++++++++++++++++-----
include/linux/remoteproc.h | 3 +++
3 files changed, 45 insertions(+), 7 deletions(-)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index f003be006b1b..6756f2fe4ec5 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -2367,6 +2367,7 @@ static void rproc_type_release(struct device *dev)
dev_info(&rproc->dev, "releasing %s\n", rproc->name);
+ cleanup_srcu_struct(&rproc->vq_srcu);
idr_destroy(&rproc->notifyids);
if (rproc->index >= 0)
@@ -2464,6 +2465,11 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
if (!rproc)
return NULL;
+ if (init_srcu_struct(&rproc->vq_srcu)) {
+ kfree(rproc);
+ return NULL;
+ }
+
rproc->priv = &rproc[1];
rproc->auto_boot = true;
rproc->elf_class = ELFCLASSNONE;
@@ -2526,6 +2532,9 @@ EXPORT_SYMBOL(rproc_alloc);
*
* If no one holds any reference to rproc anymore, then its refcount would
* now drop to zero, and it would be freed.
+ *
+ * Context: Any context, but the last reference must not be dropped from
+ * atomic context.
*/
void rproc_free(struct rproc *rproc)
{
@@ -2541,6 +2550,9 @@ EXPORT_SYMBOL(rproc_free);
*
* If no one holds any reference to rproc anymore, then its refcount would
* now drop to zero, and it would be freed.
+ *
+ * Context: Any context, but the last reference must not be dropped from
+ * atomic context.
*/
void rproc_put(struct rproc *rproc)
{
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index d5e9ff045a28..7fefb4bd7adc 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -23,6 +23,7 @@
#include <linux/err.h>
#include <linux/kref.h>
#include <linux/slab.h>
+#include <linux/srcu.h>
#include "remoteproc_internal.h"
@@ -88,15 +89,23 @@ static bool rproc_virtio_notify(struct virtqueue *vq)
*/
irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid)
{
+ irqreturn_t ret = IRQ_NONE;
struct rproc_vring *rvring;
+ struct virtqueue *vq;
+ int idx;
dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid);
+ idx = srcu_read_lock(&rproc->vq_srcu);
+
rvring = idr_find(&rproc->notifyids, notifyid);
- if (!rvring || !rvring->vq)
- return IRQ_NONE;
+ vq = rvring ? READ_ONCE(rvring->vq) : NULL;
+ if (vq)
+ ret = vring_interrupt(0, vq);
- return vring_interrupt(0, rvring->vq);
+ srcu_read_unlock(&rproc->vq_srcu, idx);
+
+ return ret;
}
EXPORT_SYMBOL(rproc_vq_interrupt);
@@ -153,7 +162,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
vq->num_max = num;
- rvring->vq = vq;
+ WRITE_ONCE(rvring->vq, vq);
vq->priv = rvring;
/* Update vring in resource table */
@@ -165,14 +174,20 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
{
+ struct rproc *rproc = vdev_to_rproc(vdev);
struct virtqueue *vq, *n;
struct rproc_vring *rvring;
- list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
+ list_for_each_entry(vq, &vdev->vqs, list) {
rvring = vq->priv;
- rvring->vq = NULL;
- vring_del_virtqueue(vq);
+ WRITE_ONCE(rvring->vq, NULL);
}
+
+ /* Synchronize with rproc_vq_interrupt() callers that found a queue. */
+ synchronize_srcu(&rproc->vq_srcu);
+
+ list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+ vring_del_virtqueue(vq);
}
static void rproc_virtio_del_vqs(struct virtio_device *vdev)
@@ -242,6 +257,13 @@ static void rproc_virtio_reset(struct virtio_device *vdev)
dev_dbg(&vdev->dev, "reset !\n");
}
+static void rproc_virtio_synchronize_cbs(struct virtio_device *vdev)
+{
+ struct rproc *rproc = vdev_to_rproc(vdev);
+
+ synchronize_srcu(&rproc->vq_srcu);
+}
+
/* provide the vdev features as retrieved from the firmware */
static u64 rproc_virtio_get_features(struct virtio_device *vdev)
{
@@ -330,6 +352,7 @@ static const struct virtio_config_ops rproc_virtio_config_ops = {
.find_vqs = rproc_virtio_find_vqs,
.del_vqs = rproc_virtio_del_vqs,
.reset = rproc_virtio_reset,
+ .synchronize_cbs = rproc_virtio_synchronize_cbs,
.set_status = rproc_virtio_set_status,
.get_status = rproc_virtio_get_status,
.get = rproc_virtio_get,
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 7c1546d48008..93a182b1868a 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -41,6 +41,7 @@
#include <linux/cdev.h>
#include <linux/completion.h>
#include <linux/idr.h>
+#include <linux/srcu.h>
#include <linux/of.h>
#include <linux/rsc_table.h>
@@ -256,6 +257,7 @@ enum rproc_features {
* @mappings: list of iommu mappings we initiated, needed on shutdown
* @bootaddr: address of first instruction to boot rproc with (optional)
* @rvdevs: list of remote virtio devices
+ * @vq_srcu: SRCU domain for the virtqueue callbacks of @rvdevs
* @subdevs: list of subdevices, to following the running state
* @notifyids: idr for dynamically assigning rproc-wide unique notify ids
* @index: index of this rproc device
@@ -298,6 +300,7 @@ struct rproc {
struct list_head mappings;
u64 bootaddr;
struct list_head rvdevs;
+ struct srcu_struct vq_srcu;
struct list_head subdevs;
struct idr notifyids;
int index;
--
2.39.5 (Apple Git-154)
next prev parent reply other threads:[~2026-09-08 5:39 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 5:38 [PATCH v3 0/6] virtio: fix and add callback synchronization hooks Karl Mehltretter
2026-09-08 5:38 ` [PATCH v3 1/6] virtio_ccw: fix synchronize_cbs() after interrupt fallback Karl Mehltretter
2026-09-08 5:50 ` sashiko-bot
2026-09-08 5:38 ` [PATCH v3 2/6] virtio_ccw: always take irq_lock in the classic interrupt handler Karl Mehltretter
2026-09-08 5:51 ` sashiko-bot
2026-09-08 8:14 ` Michael S. Tsirkin
2026-09-08 5:38 ` Karl Mehltretter [this message]
2026-09-08 5:54 ` [PATCH v3 3/6] remoteproc: implement synchronize_cbs() for virtio devices sashiko-bot
2026-09-08 5:38 ` [PATCH v3 4/6] um: virtio_uml: implement synchronize_cbs() Karl Mehltretter
2026-09-08 5:50 ` sashiko-bot
2026-09-08 5:38 ` [PATCH v3 5/6] platform/mellanox: mlxbf-tmfifo: " Karl Mehltretter
2026-09-08 5:52 ` sashiko-bot
2026-09-08 5:38 ` [PATCH v3 6/6] virtio_vdpa: " Karl Mehltretter
2026-09-08 5:51 ` sashiko-bot
2026-09-08 8:31 ` Michael S. Tsirkin
2026-09-08 8:06 ` [PATCH v3 0/6] virtio: fix and add callback synchronization hooks Michael S. Tsirkin
2026-09-08 8:25 ` Michael S. Tsirkin
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=20260908053817.26065-4-kmehltretter@gmail.com \
--to=kmehltretter@gmail.com \
--cc=agordeev@linux.ibm.com \
--cc=andersson@kernel.org \
--cc=anton.ivanov@cambridgegreys.com \
--cc=borntraeger@linux.ibm.com \
--cc=cohuck@redhat.com \
--cc=dmitry.torokhov@gmail.com \
--cc=eperezma@redhat.com \
--cc=farman@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=hansg@kernel.org \
--cc=hca@linux.ibm.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=jasowangio@gmail.com \
--cc=johannes@sipsolutions.net \
--cc=kraxel@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-remoteproc@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=linux-um@lists.infradead.org \
--cc=mathieu.poirier@linaro.org \
--cc=mst@redhat.com \
--cc=pasic@linux.ibm.com \
--cc=pawel.moll@arm.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=richard@nod.at \
--cc=rusty@rustcorp.com.au \
--cc=svens@linux.ibm.com \
--cc=vadimp@nvidia.com \
--cc=virtualization@lists.linux.dev \
--cc=xuanzhuo@linux.alibaba.com \
/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.