* [PATCH] remoteproc: virtio: support dynamic number of vrings
@ 2026-06-21 21:57 Francesco Valla
2026-06-24 17:55 ` Mathieu Poirier
0 siblings, 1 reply; 2+ messages in thread
From: Francesco Valla @ 2026-06-21 21:57 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Kees Cook, Gustavo A. R. Silva
Cc: linux-remoteproc, linux-kernel, linux-hardening, Francesco Valla
The number of vrings for each vdev has been fixed to 2 since the
introduction of multi-vdev support [1]; this is completely fine for the
rpmsg usecase, but can conflict with other virtio devices (CAN for
example requires 3 virtqueues, entropy only 1, network a variable number
and so on).
Remove the static vring allocation, transforming it to a flex array that
is allocated at vdev probe time; for the existent usecases (i.e.: mainly
rpmsg) this leads to no functional change, except the additional memory
used for the counter associated to the new array.
The maximum number of virtqueues is limited to 256 due to the uint8_t
value used inside the resource table to indicate the number of vring to
allocate; for this reason, no additional plausibility check is performed
on the number of vrings indicated by the resource table.
As a side effect, this also fixes the single virtqueue usecase, which
was apparently supported also before but for which the remove action
caused an error (because the remove action was trying to unmap also the
second vring, which was in fact not mapped).
[1] https://lore.kernel.org/all/1330589497-4139-5-git-send-email-ohad@wizery.com/
Signed-off-by: Francesco Valla <francesco@valla.it>
---
drivers/remoteproc/remoteproc_core.c | 7 -------
drivers/remoteproc/remoteproc_virtio.c | 21 +++++++++++++--------
include/linux/remoteproc.h | 10 ++++------
3 files changed, 17 insertions(+), 21 deletions(-)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index f003be006b1b..88504d6eed93 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -473,7 +473,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
{
struct fw_rsc_vdev *rsc = ptr;
struct device *dev = &rproc->dev;
- struct rproc_vdev *rvdev;
size_t rsc_size;
struct rproc_vdev_data rvdev_data;
struct platform_device *pdev;
@@ -494,12 +493,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
dev_dbg(dev, "vdev rsc: id %d, dfeatures 0x%x, cfg len %d, %d vrings\n",
rsc->id, rsc->dfeatures, rsc->config_len, rsc->num_of_vrings);
- /* we currently support only two vrings per rvdev */
- if (rsc->num_of_vrings > ARRAY_SIZE(rvdev->vring)) {
- dev_err(dev, "too many vrings: %d\n", rsc->num_of_vrings);
- return -EINVAL;
- }
-
rvdev_data.id = rsc->id;
rvdev_data.index = rproc->nb_vdev++;
rvdev_data.rsc_offset = offset;
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index d5e9ff045a28..96f13f828b8e 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -115,8 +115,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
void *addr;
int num, size;
- /* we're temporarily limited to two virtqueues per rvdev */
- if (id >= ARRAY_SIZE(rvdev->vring))
+ if (id >= rvdev->num_vrings)
return ERR_PTR(-EINVAL);
if (!name)
@@ -503,17 +502,20 @@ static int rproc_virtio_probe(struct platform_device *pdev)
if (!rvdev_data)
return -EINVAL;
- rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL);
+ rsc = rvdev_data->rsc;
+
+ rvdev = kzalloc_flex(*rvdev, vring, rsc->num_of_vrings);
if (!rvdev)
return -ENOMEM;
rvdev->id = rvdev_data->id;
rvdev->rproc = rproc;
rvdev->index = rvdev_data->index;
+ rvdev->num_vrings = rsc->num_of_vrings;
ret = copy_dma_range_map(dev, rproc->dev.parent);
if (ret)
- return ret;
+ goto free_rvdev;
/* Make device dma capable by inheriting from parent's capabilities */
set_dma_ops(dev, get_dma_ops(rproc->dev.parent));
@@ -527,13 +529,11 @@ static int rproc_virtio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rvdev);
rvdev->pdev = pdev;
- rsc = rvdev_data->rsc;
-
/* parse the vrings */
for (i = 0; i < rsc->num_of_vrings; i++) {
ret = rproc_parse_vring(rvdev, rsc, i);
if (ret)
- return ret;
+ goto free_rvdev;
}
/* remember the resource offset*/
@@ -569,6 +569,9 @@ static int rproc_virtio_probe(struct platform_device *pdev)
for (i--; i >= 0; i--)
rproc_free_vring(&rvdev->vring[i]);
+free_rvdev:
+ kfree(rvdev);
+
return ret;
}
@@ -579,7 +582,7 @@ static void rproc_virtio_remove(struct platform_device *pdev)
struct rproc_vring *rvring;
int id;
- for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
+ for (id = 0; id < rvdev->num_vrings; id++) {
rvring = &rvdev->vring[id];
rproc_free_vring(rvring);
}
@@ -588,6 +591,8 @@ static void rproc_virtio_remove(struct platform_device *pdev)
rproc_remove_rvdev(rvdev);
put_device(&rproc->dev);
+
+ kfree(rvdev);
}
/* Platform driver */
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 7c1546d48008..222e1a56cebc 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -339,10 +339,6 @@ struct rproc_subdev {
void (*unprepare)(struct rproc_subdev *subdev);
};
-/* we currently support only two vrings per rvdev */
-
-#define RVDEV_NUM_VRINGS 2
-
/**
* struct rproc_vring - remoteproc vring state
* @va: virtual address
@@ -370,9 +366,10 @@ struct rproc_vring {
* @id: virtio device id (as in virtio_ids.h)
* @node: list node
* @rproc: the rproc handle
- * @vring: the vrings for this vdev
* @rsc_offset: offset of the vdev's resource entry
* @index: vdev position versus other vdev declared in resource table
+ * @num_vrings: the number of vrings for this vdev
+ * @vring: the vrings for this vdev
*/
struct rproc_vdev {
@@ -382,9 +379,10 @@ struct rproc_vdev {
unsigned int id;
struct list_head node;
struct rproc *rproc;
- struct rproc_vring vring[RVDEV_NUM_VRINGS];
u32 rsc_offset;
u32 index;
+ unsigned int num_vrings;
+ struct rproc_vring vring[] __counted_by(num_vrings);
};
struct rproc *rproc_get_by_phandle(phandle phandle);
---
base-commit: ef0c9f75a19532d7675384708fc8621e10850104
change-id: 20260618-vring_flex-b4d23d1974ba
Best regards,
--
Francesco Valla <francesco@valla.it>
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] remoteproc: virtio: support dynamic number of vrings
2026-06-21 21:57 [PATCH] remoteproc: virtio: support dynamic number of vrings Francesco Valla
@ 2026-06-24 17:55 ` Mathieu Poirier
0 siblings, 0 replies; 2+ messages in thread
From: Mathieu Poirier @ 2026-06-24 17:55 UTC (permalink / raw)
To: Francesco Valla
Cc: Bjorn Andersson, Kees Cook, Gustavo A. R. Silva, linux-remoteproc,
linux-kernel, linux-hardening
Hi Francesco,
On Sun, Jun 21, 2026 at 11:57:31PM +0200, Francesco Valla wrote:
> The number of vrings for each vdev has been fixed to 2 since the
> introduction of multi-vdev support [1]; this is completely fine for the
> rpmsg usecase, but can conflict with other virtio devices (CAN for
> example requires 3 virtqueues, entropy only 1, network a variable number
> and so on).
I suppose the remoteproc subsystem is involved because these other virtio
devices are behind a remote processor? If so, how does virtio drivers for the
devices get called?
Otherwise I'm good with the code.
Thanks,
Mathieu
>
> Remove the static vring allocation, transforming it to a flex array that
> is allocated at vdev probe time; for the existent usecases (i.e.: mainly
> rpmsg) this leads to no functional change, except the additional memory
> used for the counter associated to the new array.
>
> The maximum number of virtqueues is limited to 256 due to the uint8_t
> value used inside the resource table to indicate the number of vring to
> allocate; for this reason, no additional plausibility check is performed
> on the number of vrings indicated by the resource table.
>
> As a side effect, this also fixes the single virtqueue usecase, which
> was apparently supported also before but for which the remove action
> caused an error (because the remove action was trying to unmap also the
> second vring, which was in fact not mapped).
>
> [1] https://lore.kernel.org/all/1330589497-4139-5-git-send-email-ohad@wizery.com/
>
> Signed-off-by: Francesco Valla <francesco@valla.it>
> ---
> drivers/remoteproc/remoteproc_core.c | 7 -------
> drivers/remoteproc/remoteproc_virtio.c | 21 +++++++++++++--------
> include/linux/remoteproc.h | 10 ++++------
> 3 files changed, 17 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index f003be006b1b..88504d6eed93 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -473,7 +473,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> {
> struct fw_rsc_vdev *rsc = ptr;
> struct device *dev = &rproc->dev;
> - struct rproc_vdev *rvdev;
> size_t rsc_size;
> struct rproc_vdev_data rvdev_data;
> struct platform_device *pdev;
> @@ -494,12 +493,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> dev_dbg(dev, "vdev rsc: id %d, dfeatures 0x%x, cfg len %d, %d vrings\n",
> rsc->id, rsc->dfeatures, rsc->config_len, rsc->num_of_vrings);
>
> - /* we currently support only two vrings per rvdev */
> - if (rsc->num_of_vrings > ARRAY_SIZE(rvdev->vring)) {
> - dev_err(dev, "too many vrings: %d\n", rsc->num_of_vrings);
> - return -EINVAL;
> - }
> -
> rvdev_data.id = rsc->id;
> rvdev_data.index = rproc->nb_vdev++;
> rvdev_data.rsc_offset = offset;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index d5e9ff045a28..96f13f828b8e 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -115,8 +115,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
> void *addr;
> int num, size;
>
> - /* we're temporarily limited to two virtqueues per rvdev */
> - if (id >= ARRAY_SIZE(rvdev->vring))
> + if (id >= rvdev->num_vrings)
> return ERR_PTR(-EINVAL);
>
> if (!name)
> @@ -503,17 +502,20 @@ static int rproc_virtio_probe(struct platform_device *pdev)
> if (!rvdev_data)
> return -EINVAL;
>
> - rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL);
> + rsc = rvdev_data->rsc;
> +
> + rvdev = kzalloc_flex(*rvdev, vring, rsc->num_of_vrings);
> if (!rvdev)
> return -ENOMEM;
>
> rvdev->id = rvdev_data->id;
> rvdev->rproc = rproc;
> rvdev->index = rvdev_data->index;
> + rvdev->num_vrings = rsc->num_of_vrings;
>
> ret = copy_dma_range_map(dev, rproc->dev.parent);
> if (ret)
> - return ret;
> + goto free_rvdev;
>
> /* Make device dma capable by inheriting from parent's capabilities */
> set_dma_ops(dev, get_dma_ops(rproc->dev.parent));
> @@ -527,13 +529,11 @@ static int rproc_virtio_probe(struct platform_device *pdev)
> platform_set_drvdata(pdev, rvdev);
> rvdev->pdev = pdev;
>
> - rsc = rvdev_data->rsc;
> -
> /* parse the vrings */
> for (i = 0; i < rsc->num_of_vrings; i++) {
> ret = rproc_parse_vring(rvdev, rsc, i);
> if (ret)
> - return ret;
> + goto free_rvdev;
> }
>
> /* remember the resource offset*/
> @@ -569,6 +569,9 @@ static int rproc_virtio_probe(struct platform_device *pdev)
> for (i--; i >= 0; i--)
> rproc_free_vring(&rvdev->vring[i]);
>
> +free_rvdev:
> + kfree(rvdev);
> +
> return ret;
> }
>
> @@ -579,7 +582,7 @@ static void rproc_virtio_remove(struct platform_device *pdev)
> struct rproc_vring *rvring;
> int id;
>
> - for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> + for (id = 0; id < rvdev->num_vrings; id++) {
> rvring = &rvdev->vring[id];
> rproc_free_vring(rvring);
> }
> @@ -588,6 +591,8 @@ static void rproc_virtio_remove(struct platform_device *pdev)
> rproc_remove_rvdev(rvdev);
>
> put_device(&rproc->dev);
> +
> + kfree(rvdev);
> }
>
> /* Platform driver */
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index 7c1546d48008..222e1a56cebc 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -339,10 +339,6 @@ struct rproc_subdev {
> void (*unprepare)(struct rproc_subdev *subdev);
> };
>
> -/* we currently support only two vrings per rvdev */
> -
> -#define RVDEV_NUM_VRINGS 2
> -
> /**
> * struct rproc_vring - remoteproc vring state
> * @va: virtual address
> @@ -370,9 +366,10 @@ struct rproc_vring {
> * @id: virtio device id (as in virtio_ids.h)
> * @node: list node
> * @rproc: the rproc handle
> - * @vring: the vrings for this vdev
> * @rsc_offset: offset of the vdev's resource entry
> * @index: vdev position versus other vdev declared in resource table
> + * @num_vrings: the number of vrings for this vdev
> + * @vring: the vrings for this vdev
> */
> struct rproc_vdev {
>
> @@ -382,9 +379,10 @@ struct rproc_vdev {
> unsigned int id;
> struct list_head node;
> struct rproc *rproc;
> - struct rproc_vring vring[RVDEV_NUM_VRINGS];
> u32 rsc_offset;
> u32 index;
> + unsigned int num_vrings;
> + struct rproc_vring vring[] __counted_by(num_vrings);
> };
>
> struct rproc *rproc_get_by_phandle(phandle phandle);
>
> ---
> base-commit: ef0c9f75a19532d7675384708fc8621e10850104
> change-id: 20260618-vring_flex-b4d23d1974ba
>
> Best regards,
> --
> Francesco Valla <francesco@valla.it>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-24 17:55 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-21 21:57 [PATCH] remoteproc: virtio: support dynamic number of vrings Francesco Valla
2026-06-24 17:55 ` Mathieu Poirier
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.