Re: [PATCH] remoteproc: virtio: support dynamic number of vrings

From: Mathieu Poirier

Date: Wed Jun 24 2026 - 13:55:53 EST


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@xxxxxxxxxx/
>
> Signed-off-by: Francesco Valla <francesco@xxxxxxxx>
> ---
> 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@xxxxxxxx>
>