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/[email protected]/
> 
> Signed-off-by: Francesco Valla <[email protected]>
> ---
>  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 <[email protected]>
> 

Reply via email to