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]> >

