[PATCH RFC v2 03/11] remoteproc: virtio: support dynamic number of vrings
Francesco Valla
francesco at valla.it
Sun Nov 1 15:26:40 PST 2026
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 existing 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 255 due to the u8 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.
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 at valla.it>
---
drivers/remoteproc/remoteproc_core.c | 7 -------
drivers/remoteproc/remoteproc_virtio.c | 12 ++++++------
include/linux/remoteproc.h | 10 ++++------
3 files changed, 10 insertions(+), 19 deletions(-)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 23f8539a99bd..c946ecd980a5 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 29a3a4c18097..c56d3330adfe 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -135,8 +135,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)
@@ -510,13 +509,16 @@ 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 = devm_kzalloc_flex(dev, *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)
@@ -534,8 +536,6 @@ 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);
@@ -586,7 +586,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);
}
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 00019b1895e6..52e1eccbe42e 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -322,10 +322,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
@@ -353,9 +349,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 {
struct rproc_subdev subdev;
@@ -364,9 +361,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);
--
2.56.0
More information about the linux-arm-kernel
mailing list