* [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device
@ 2022-04-06 9:54 Arnaud Pouliquen
2022-04-06 9:54 ` [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions Arnaud Pouliquen
` (4 more replies)
0 siblings, 5 replies; 16+ messages in thread
From: Arnaud Pouliquen @ 2022-04-06 9:54 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, Rob Herring,
Christoph Hellwig, Stefano Stabellini, Bruce Ashfield,
arnaud.pouliquen
1) Update from V4 [1]:
Minor updates based on Mathieu's comments.
Updates are listed in the commit message of each patch.
[1] https://lkml.org/lkml/2022/3/14/1177
2) Patchset description:
This series is a part of the work initiated a long time ago in
the series "remoteproc: Decorelate virtio from core"[2]
Objective of the work:
- Update the remoteproc VirtIO device creation (use platform device)
- Allow to declare remoteproc VirtIO device in DT
- declare resources associated to a remote proc VirtIO
- declare a list of VirtIO supported by the platform.
- Prepare the enhancement to more VirtIO devices (e.g I2C, audio, video, ...).
For instance be able to declare a I2C device in a virtio-i2C node.
- Keep the legacy working!
- Try to improve the picture about concerns reported by Christoph Hellwing [3][4]
[2] https://lkml.org/lkml/2020/4/16/1817
[3] https://lkml.org/lkml/2021/6/23/607
[4] https://patchwork.kernel.org/project/linux-remoteproc/patch/AOKowLclCbOCKxyiJ71WeNyuAAj2q8EUtxrXbyky5E@cp7-web-042.plabs.ch/
In term of device tree this would result in such hierarchy (stm32mp1 example with 2 virtio RPMSG):
m4_rproc: m4@10000000 {
compatible = "st,stm32mp1-m4";
reg = <0x10000000 0x40000>,
<0x30000000 0x40000>,
<0x38000000 0x10000>;
memory-region = <&retram>, <&mcuram>,<&mcuram2>;
mboxes = <&ipcc 2>, <&ipcc 3>;
mbox-names = "shutdown", "detach";
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
vdev@0 {
compatible = "rproc-virtio";
reg = <0>;
virtio,id = <7>; /* RPMSG */
memory-region = <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>;
mboxes = <&ipcc 0>, <&ipcc 1>;
mbox-names = "vq0", "vq1";
status = "okay";
};
vdev@1 {
compatible = "rproc-virtio";
reg = <1>;
virtio,id = <7>; /*RPMSG */
memory-region = <&vdev1vring0>, <&vdev1vring1>, <&vdev1buffer>;
mboxes = <&ipcc 4>, <&ipcc 5>;
mbox-names = "vq0", "vq1";
status = "okay";
};
};
I have divided the work in 4 steps to simplify the review, This series implements only
the step 1:
step 1: redefine the remoteproc VirtIO device as a platform device
- migrate rvdev management in remoteproc virtio.c,
- create a remotproc virtio config ( can be disabled for platform that not use VirtIO IPC.
step 2: add possibility to declare and probe a VirtIO sub node
- VirtIO bindings declaration,
- multi DT VirtIO devices support,
- introduction of a remote proc virtio bind device mechanism ,
=> https://github.com/arnopo/linux/commits/step2-virtio-in-DT
step 3: Add memory declaration in VirtIO subnode
=> https://github.com/arnopo/linux/commits/step3-virtio-memories
step 4: Add mailbox declaration in VirtIO subnode
=> https://github.com/arnopo/linux/commits/step4-virtio-mailboxes
Arnaud Pouliquen (4):
remoteproc: core: Introduce virtio device add/remove functions
remoteproc: core: Introduce rproc_register_rvdev function
remoteproc: Move rproc_vdev management to remoteproc_virtio.c
remoteproc: virtio: Create platform device for the remoteproc_virtio
drivers/remoteproc/remoteproc_core.c | 154 +++---------------
drivers/remoteproc/remoteproc_internal.h | 23 ++-
drivers/remoteproc/remoteproc_virtio.c | 193 ++++++++++++++++++++---
include/linux/remoteproc.h | 6 +-
4 files changed, 215 insertions(+), 161 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions
2022-04-06 9:54 [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Arnaud Pouliquen
@ 2022-04-06 9:54 ` Arnaud Pouliquen
2022-06-01 17:29 ` Mathieu Poirier
2022-04-06 9:54 ` [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function Arnaud Pouliquen
` (3 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Arnaud Pouliquen @ 2022-04-06 9:54 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, Rob Herring,
Christoph Hellwig, Stefano Stabellini, Bruce Ashfield,
arnaud.pouliquen
In preparation of the migration of the management of rvdev in
remoteproc_virtio.c, this patch spins off new functions to manage the
remoteproc virtio device.
- rproc_rvdev_add_device
- rproc_rvdev_remove_device
The rproc_rvdev_add_device and rproc_rvdev_remove_device will be
moved to remoteproc_virtio.c.
The rproc_vdev_data structure is introduced to provide information for
the rvdev creation. This structure allows to manage the rvdev and vrings
allocation in the rproc_rvdev_add_device function.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
drivers/remoteproc/remoteproc_core.c | 157 +++++++++++++----------
drivers/remoteproc/remoteproc_internal.h | 15 +++
2 files changed, 106 insertions(+), 66 deletions(-)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index c510125769b9..3a469220ac73 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -484,74 +484,23 @@ static int copy_dma_range_map(struct device *to, struct device *from)
return 0;
}
-/**
- * rproc_handle_vdev() - handle a vdev fw resource
- * @rproc: the remote processor
- * @ptr: the vring resource descriptor
- * @offset: offset of the resource entry
- * @avail: size of available data (for sanity checking the image)
- *
- * This resource entry requests the host to statically register a virtio
- * device (vdev), and setup everything needed to support it. It contains
- * everything needed to make it possible: the virtio device id, virtio
- * device features, vrings information, virtio config space, etc...
- *
- * Before registering the vdev, the vrings are allocated from non-cacheable
- * physically contiguous memory. Currently we only support two vrings per
- * remote processor (temporary limitation). We might also want to consider
- * doing the vring allocation only later when ->find_vqs() is invoked, and
- * then release them upon ->del_vqs().
- *
- * Note: @da is currently not really handled correctly: we dynamically
- * allocate it using the DMA API, ignoring requested hard coded addresses,
- * and we don't take care of any required IOMMU programming. This is all
- * going to be taken care of when the generic iommu-based DMA API will be
- * merged. Meanwhile, statically-addressed iommu-based firmware images should
- * use RSC_DEVMEM resource entries to map their required @da to the physical
- * address of their base CMA region (ouch, hacky!).
- *
- * Return: 0 on success, or an appropriate error code otherwise
- */
-static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
- int offset, int avail)
+static struct rproc_vdev *
+rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
{
- struct fw_rsc_vdev *rsc = ptr;
- struct device *dev = &rproc->dev;
struct rproc_vdev *rvdev;
- int i, ret;
+ struct fw_rsc_vdev *rsc = rvdev_data->rsc;
char name[16];
-
- /* make sure resource isn't truncated */
- if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
- avail) {
- dev_err(dev, "vdev rsc is truncated\n");
- return -EINVAL;
- }
-
- /* make sure reserved bytes are zeroes */
- if (rsc->reserved[0] || rsc->reserved[1]) {
- dev_err(dev, "vdev rsc has non zero reserved bytes\n");
- return -EINVAL;
- }
-
- 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;
- }
+ int i, ret;
rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
if (!rvdev)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
kref_init(&rvdev->refcount);
- rvdev->id = rsc->id;
+ rvdev->id = rvdev_data->id;
rvdev->rproc = rproc;
- rvdev->index = rproc->nb_vdev++;
+ rvdev->index = rvdev_data->index;
/* Initialise vdev subdevice */
snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
@@ -563,7 +512,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
ret = device_register(&rvdev->dev);
if (ret) {
put_device(&rvdev->dev);
- return ret;
+ return ERR_PTR(ret);
}
ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
@@ -576,7 +525,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
ret = dma_coerce_mask_and_coherent(&rvdev->dev,
dma_get_mask(rproc->dev.parent));
if (ret) {
- dev_warn(dev,
+ dev_warn(&rvdev->dev,
"Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
}
@@ -589,7 +538,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
}
/* remember the resource offset*/
- rvdev->rsc_offset = offset;
+ rvdev->rsc_offset = rvdev_data->rsc_offset;
/* allocate the vring resources */
for (i = 0; i < rsc->num_of_vrings; i++) {
@@ -605,21 +554,20 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
rproc_add_subdev(rproc, &rvdev->subdev);
- return 0;
+ return rvdev;
unwind_vring_allocations:
for (i--; i >= 0; i--)
rproc_free_vring(&rvdev->vring[i]);
free_rvdev:
device_unregister(&rvdev->dev);
- return ret;
+ return ERR_PTR(ret);
}
-void rproc_vdev_release(struct kref *ref)
+static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
{
- struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
- struct rproc_vring *rvring;
struct rproc *rproc = rvdev->rproc;
+ struct rproc_vring *rvring;
int id;
for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
@@ -632,6 +580,83 @@ void rproc_vdev_release(struct kref *ref)
device_unregister(&rvdev->dev);
}
+/**
+ * rproc_handle_vdev() - handle a vdev fw resource
+ * @rproc: the remote processor
+ * @ptr: the vring resource descriptor
+ * @offset: offset of the resource entry
+ * @avail: size of available data (for sanity checking the image)
+ *
+ * This resource entry requests the host to statically register a virtio
+ * device (vdev), and setup everything needed to support it. It contains
+ * everything needed to make it possible: the virtio device id, virtio
+ * device features, vrings information, virtio config space, etc...
+ *
+ * Before registering the vdev, the vrings are allocated from non-cacheable
+ * physically contiguous memory. Currently we only support two vrings per
+ * remote processor (temporary limitation). We might also want to consider
+ * doing the vring allocation only later when ->find_vqs() is invoked, and
+ * then release them upon ->del_vqs().
+ *
+ * Note: @da is currently not really handled correctly: we dynamically
+ * allocate it using the DMA API, ignoring requested hard coded addresses,
+ * and we don't take care of any required IOMMU programming. This is all
+ * going to be taken care of when the generic iommu-based DMA API will be
+ * merged. Meanwhile, statically-addressed iommu-based firmware images should
+ * use RSC_DEVMEM resource entries to map their required @da to the physical
+ * address of their base CMA region (ouch, hacky!).
+ *
+ * Return: 0 on success, or an appropriate error code otherwise
+ */
+static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
+ int offset, int avail)
+{
+ struct fw_rsc_vdev *rsc = ptr;
+ struct device *dev = &rproc->dev;
+ struct rproc_vdev *rvdev;
+ struct rproc_vdev_data rvdev_data;
+
+ /* make sure resource isn't truncated */
+ if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
+ avail) {
+ dev_err(dev, "vdev rsc is truncated\n");
+ return -EINVAL;
+ }
+
+ /* make sure reserved bytes are zeroes */
+ if (rsc->reserved[0] || rsc->reserved[1]) {
+ dev_err(dev, "vdev rsc has non zero reserved bytes\n");
+ return -EINVAL;
+ }
+
+ 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;
+ rvdev_data.rsc = rsc;
+
+ rvdev = rproc_rvdev_add_device(rproc, &rvdev_data);
+ if (IS_ERR(rvdev))
+ return PTR_ERR(rvdev);
+
+ return 0;
+}
+
+void rproc_vdev_release(struct kref *ref)
+{
+ struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
+
+ rproc_rvdev_remove_device(rvdev);
+}
+
/**
* rproc_handle_trace() - handle a shared trace buffer resource
* @rproc: the remote processor
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 72d4d3d7d94d..99f2ff88079f 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -24,6 +24,21 @@ struct rproc_debug_trace {
struct rproc_mem_entry trace_mem;
};
+/**
+ * struct rproc_vdev_data - remoteproc virtio device data
+ * @rsc_offset: offset of the vdev's resource entry
+ * @id: virtio device id (as in virtio_ids.h)
+ * @index: vdev position versus other vdev declared in resource table
+ * @rsc: pointer to the vdev resource entry. Valid onlyduring vdev init as the resource can
+ * be cached by rproc.
+ */
+struct rproc_vdev_data {
+ u32 rsc_offset;
+ unsigned int id;
+ unsigned int index;
+ struct fw_rsc_vdev *rsc;
+};
+
/* from remoteproc_core.c */
void rproc_release(struct kref *kref);
irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
--
2.25.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function
2022-04-06 9:54 [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Arnaud Pouliquen
2022-04-06 9:54 ` [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions Arnaud Pouliquen
@ 2022-04-06 9:54 ` Arnaud Pouliquen
2022-06-01 17:41 ` Mathieu Poirier
2022-04-06 9:54 ` [RFC PATCH v5 3/4] remoteproc: Move rproc_vdev management to remoteproc_virtio.c Arnaud Pouliquen
` (2 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Arnaud Pouliquen @ 2022-04-06 9:54 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, Rob Herring,
Christoph Hellwig, Stefano Stabellini, Bruce Ashfield,
arnaud.pouliquen
The rproc structure contains a list of registered rproc_vdev structure.
To be able to move the management of the rproc_vdev structure in
remoteproc_virtio.c (i.e rproc_rvdev_add_device and
rproc_rvdev_remove_device functions), introduce the rproc_register_rvdev
and rproc_unregister_rvdev functions.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
drivers/remoteproc/remoteproc_core.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 3a469220ac73..081bea39daf4 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -484,6 +484,18 @@ static int copy_dma_range_map(struct device *to, struct device *from)
return 0;
}
+static void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
+{
+ if (rvdev && rproc)
+ list_add_tail(&rvdev->node, &rproc->rvdevs);
+}
+
+static void rproc_remove_rvdev(struct rproc_vdev *rvdev)
+{
+ if (rvdev)
+ list_del(&rvdev->node);
+}
+
static struct rproc_vdev *
rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
{
@@ -547,7 +559,7 @@ rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
goto unwind_vring_allocations;
}
- list_add_tail(&rvdev->node, &rproc->rvdevs);
+ rproc_add_rvdev(rproc, rvdev);
rvdev->subdev.start = rproc_vdev_do_start;
rvdev->subdev.stop = rproc_vdev_do_stop;
@@ -576,7 +588,7 @@ static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
}
rproc_remove_subdev(rproc, &rvdev->subdev);
- list_del(&rvdev->node);
+ rproc_remove_rvdev(rvdev);
device_unregister(&rvdev->dev);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC PATCH v5 3/4] remoteproc: Move rproc_vdev management to remoteproc_virtio.c
2022-04-06 9:54 [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Arnaud Pouliquen
2022-04-06 9:54 ` [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions Arnaud Pouliquen
2022-04-06 9:54 ` [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function Arnaud Pouliquen
@ 2022-04-06 9:54 ` Arnaud Pouliquen
2022-07-05 16:07 ` Mathieu Poirier
2022-04-06 9:54 ` [RFC PATCH v5 4/4] remoteproc: virtio: Create platform device for the remoteproc_virtio Arnaud Pouliquen
2022-05-31 17:49 ` [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Mathieu Poirier
4 siblings, 1 reply; 16+ messages in thread
From: Arnaud Pouliquen @ 2022-04-06 9:54 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, Rob Herring,
Christoph Hellwig, Stefano Stabellini, Bruce Ashfield,
arnaud.pouliquen
Move functions related to the management of the rproc_vdev
structure in the remoteproc_virtio.c.
The aim is to decorrelate as possible the virtio management from
the core part.
Due to the strong correlation between the vrings and the resource table
the rproc_alloc/parse/free_vring functions are kept in the remoteproc core.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
Update vs previous revision:
- clean up bad rproc_free_vring call in rproc_vdev_release
---
drivers/remoteproc/remoteproc_core.c | 162 +----------------------
drivers/remoteproc/remoteproc_internal.h | 11 +-
drivers/remoteproc/remoteproc_virtio.c | 159 +++++++++++++++++++++-
3 files changed, 167 insertions(+), 165 deletions(-)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 081bea39daf4..bd6d3f2decc6 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -23,9 +23,7 @@
#include <linux/panic_notifier.h>
#include <linux/slab.h>
#include <linux/mutex.h>
-#include <linux/dma-map-ops.h>
#include <linux/dma-mapping.h>
-#include <linux/dma-direct.h> /* XXX: pokes into bus_dma_range */
#include <linux/firmware.h>
#include <linux/string.h>
#include <linux/debugfs.h>
@@ -383,7 +381,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
return 0;
}
-static int
+int
rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
{
struct rproc *rproc = rvdev->rproc;
@@ -434,164 +432,17 @@ void rproc_free_vring(struct rproc_vring *rvring)
}
}
-static int rproc_vdev_do_start(struct rproc_subdev *subdev)
-{
- struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
-
- return rproc_add_virtio_dev(rvdev, rvdev->id);
-}
-
-static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
-{
- struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
- int ret;
-
- ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
- if (ret)
- dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
-}
-
-/**
- * rproc_rvdev_release() - release the existence of a rvdev
- *
- * @dev: the subdevice's dev
- */
-static void rproc_rvdev_release(struct device *dev)
-{
- struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
-
- of_reserved_mem_device_release(dev);
-
- kfree(rvdev);
-}
-
-static int copy_dma_range_map(struct device *to, struct device *from)
-{
- const struct bus_dma_region *map = from->dma_range_map, *new_map, *r;
- int num_ranges = 0;
-
- if (!map)
- return 0;
-
- for (r = map; r->size; r++)
- num_ranges++;
-
- new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)),
- GFP_KERNEL);
- if (!new_map)
- return -ENOMEM;
- to->dma_range_map = new_map;
- return 0;
-}
-
-static void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
+void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
{
if (rvdev && rproc)
list_add_tail(&rvdev->node, &rproc->rvdevs);
}
-static void rproc_remove_rvdev(struct rproc_vdev *rvdev)
+void rproc_remove_rvdev(struct rproc_vdev *rvdev)
{
if (rvdev)
list_del(&rvdev->node);
}
-
-static struct rproc_vdev *
-rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
-{
- struct rproc_vdev *rvdev;
- struct fw_rsc_vdev *rsc = rvdev_data->rsc;
- char name[16];
- int i, ret;
-
- rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
- if (!rvdev)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&rvdev->refcount);
-
- rvdev->id = rvdev_data->id;
- rvdev->rproc = rproc;
- rvdev->index = rvdev_data->index;
-
- /* Initialise vdev subdevice */
- snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
- rvdev->dev.parent = &rproc->dev;
- rvdev->dev.release = rproc_rvdev_release;
- dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
- dev_set_drvdata(&rvdev->dev, rvdev);
-
- ret = device_register(&rvdev->dev);
- if (ret) {
- put_device(&rvdev->dev);
- return ERR_PTR(ret);
- }
-
- ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
- if (ret)
- goto free_rvdev;
-
- /* Make device dma capable by inheriting from parent's capabilities */
- set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
-
- ret = dma_coerce_mask_and_coherent(&rvdev->dev,
- dma_get_mask(rproc->dev.parent));
- if (ret) {
- dev_warn(&rvdev->dev,
- "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
- dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
- }
-
- /* parse the vrings */
- for (i = 0; i < rsc->num_of_vrings; i++) {
- ret = rproc_parse_vring(rvdev, rsc, i);
- if (ret)
- goto free_rvdev;
- }
-
- /* remember the resource offset*/
- rvdev->rsc_offset = rvdev_data->rsc_offset;
-
- /* allocate the vring resources */
- for (i = 0; i < rsc->num_of_vrings; i++) {
- ret = rproc_alloc_vring(rvdev, i);
- if (ret)
- goto unwind_vring_allocations;
- }
-
- rproc_add_rvdev(rproc, rvdev);
-
- rvdev->subdev.start = rproc_vdev_do_start;
- rvdev->subdev.stop = rproc_vdev_do_stop;
-
- rproc_add_subdev(rproc, &rvdev->subdev);
-
- return rvdev;
-
-unwind_vring_allocations:
- for (i--; i >= 0; i--)
- rproc_free_vring(&rvdev->vring[i]);
-free_rvdev:
- device_unregister(&rvdev->dev);
- return ERR_PTR(ret);
-}
-
-static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
-{
- struct rproc *rproc = rvdev->rproc;
- struct rproc_vring *rvring;
- int id;
-
- for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
- rvring = &rvdev->vring[id];
- rproc_free_vring(rvring);
- }
-
- rproc_remove_subdev(rproc, &rvdev->subdev);
- rproc_remove_rvdev(rvdev);
- device_unregister(&rvdev->dev);
-}
-
/**
* rproc_handle_vdev() - handle a vdev fw resource
* @rproc: the remote processor
@@ -662,13 +513,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
return 0;
}
-void rproc_vdev_release(struct kref *ref)
-{
- struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
-
- rproc_rvdev_remove_device(rvdev);
-}
-
/**
* rproc_handle_trace() - handle a shared trace buffer resource
* @rproc: the remote processor
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 99f2ff88079f..f82f9a5378ae 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -41,14 +41,14 @@ struct rproc_vdev_data {
/* from remoteproc_core.c */
void rproc_release(struct kref *kref);
-irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
-void rproc_vdev_release(struct kref *ref);
int rproc_of_parse_firmware(struct device *dev, int index,
const char **fw_name);
/* from remoteproc_virtio.c */
-int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
-int rproc_remove_virtio_dev(struct device *dev, void *data);
+struct rproc_vdev *rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data);
+void rproc_rvdev_remove_device(struct rproc_vdev *rvdev);
+irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
+void rproc_vdev_release(struct kref *ref);
/* from remoteproc_debugfs.c */
void rproc_remove_trace_file(struct dentry *tfile);
@@ -98,6 +98,7 @@ static inline void rproc_char_device_remove(struct rproc *rproc)
void rproc_free_vring(struct rproc_vring *rvring);
int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
+int rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i);
phys_addr_t rproc_va_to_pa(void *cpu_addr);
int rproc_trigger_recovery(struct rproc *rproc);
@@ -110,6 +111,8 @@ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
const struct firmware *fw);
struct rproc_mem_entry *
rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...);
+void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev);
+void rproc_remove_rvdev(struct rproc_vdev *rvdev);
static inline int rproc_prepare_device(struct rproc *rproc)
{
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 70ab496d0431..e2e796ab2fd8 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -9,7 +9,9 @@
* Brian Swetland <swetland@google.com>
*/
+#include <linux/dma-direct.h>
#include <linux/dma-map-ops.h>
+#include <linux/dma-mapping.h>
#include <linux/export.h>
#include <linux/of_reserved_mem.h>
#include <linux/remoteproc.h>
@@ -23,6 +25,25 @@
#include "remoteproc_internal.h"
+static int copy_dma_range_map(struct device *to, struct device *from)
+{
+ const struct bus_dma_region *map = from->dma_range_map, *new_map, *r;
+ int num_ranges = 0;
+
+ if (!map)
+ return 0;
+
+ for (r = map; r->size; r++)
+ num_ranges++;
+
+ new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)),
+ GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+ to->dma_range_map = new_map;
+ return 0;
+}
+
static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
{
return container_of(vdev->dev.parent, struct rproc_vdev, dev);
@@ -339,7 +360,7 @@ static void rproc_virtio_dev_release(struct device *dev)
*
* Return: 0 on success or an appropriate error value otherwise
*/
-int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
+static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
{
struct rproc *rproc = rvdev->rproc;
struct device *dev = &rvdev->dev;
@@ -447,10 +468,144 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
*
* Return: 0
*/
-int rproc_remove_virtio_dev(struct device *dev, void *data)
+static int rproc_remove_virtio_dev(struct device *dev, void *data)
{
struct virtio_device *vdev = dev_to_virtio(dev);
unregister_virtio_device(vdev);
return 0;
}
+
+static int rproc_vdev_do_start(struct rproc_subdev *subdev)
+{
+ struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
+
+ return rproc_add_virtio_dev(rvdev, rvdev->id);
+}
+
+static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
+{
+ struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
+ int ret;
+
+ ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
+ if (ret)
+ dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
+}
+
+/**
+ * rproc_rvdev_release() - release the existence of a rvdev
+ *
+ * @dev: the subdevice's dev
+ */
+static void rproc_rvdev_release(struct device *dev)
+{
+ struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
+
+ of_reserved_mem_device_release(dev);
+
+ kfree(rvdev);
+}
+
+struct rproc_vdev *
+rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
+{
+ struct rproc_vdev *rvdev;
+ struct fw_rsc_vdev *rsc = rvdev_data->rsc;
+ char name[16];
+ int i, ret;
+
+ rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
+ if (!rvdev)
+ return ERR_PTR(-ENOMEM);
+
+ kref_init(&rvdev->refcount);
+
+ rvdev->id = rvdev_data->id;
+ rvdev->rproc = rproc;
+ rvdev->index = rvdev_data->index;
+
+ /* Initialise vdev subdevice */
+ snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
+ rvdev->dev.parent = &rproc->dev;
+ rvdev->dev.release = rproc_rvdev_release;
+ dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
+ dev_set_drvdata(&rvdev->dev, rvdev);
+
+ ret = device_register(&rvdev->dev);
+ if (ret) {
+ put_device(&rvdev->dev);
+ return ERR_PTR(ret);
+ }
+
+ ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
+ if (ret)
+ goto free_rvdev;
+
+ /* Make device dma capable by inheriting from parent's capabilities */
+ set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
+
+ ret = dma_coerce_mask_and_coherent(&rvdev->dev,
+ dma_get_mask(rproc->dev.parent));
+ if (ret) {
+ dev_warn(&rvdev->dev,
+ "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
+ dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
+ }
+
+ /* parse the vrings */
+ for (i = 0; i < rsc->num_of_vrings; i++) {
+ ret = rproc_parse_vring(rvdev, rsc, i);
+ if (ret)
+ goto free_rvdev;
+ }
+
+ /* remember the resource offset*/
+ rvdev->rsc_offset = rvdev_data->rsc_offset;
+
+ /* allocate the vring resources */
+ for (i = 0; i < rsc->num_of_vrings; i++) {
+ ret = rproc_alloc_vring(rvdev, i);
+ if (ret)
+ goto unwind_vring_allocations;
+ }
+
+ rproc_add_rvdev(rproc, rvdev);
+
+ rvdev->subdev.start = rproc_vdev_do_start;
+ rvdev->subdev.stop = rproc_vdev_do_stop;
+
+ rproc_add_subdev(rproc, &rvdev->subdev);
+
+ return rvdev;
+
+unwind_vring_allocations:
+ for (i--; i >= 0; i--)
+ rproc_free_vring(&rvdev->vring[i]);
+free_rvdev:
+ device_unregister(&rvdev->dev);
+ return ERR_PTR(ret);
+}
+
+void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
+{
+ struct rproc *rproc = rvdev->rproc;
+ struct rproc_vring *rvring;
+ int id;
+
+ for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
+ rvring = &rvdev->vring[id];
+ rproc_free_vring(rvring);
+ }
+
+ rproc_remove_subdev(rproc, &rvdev->subdev);
+ rproc_remove_rvdev(rvdev);
+ device_unregister(&rvdev->dev);
+}
+
+void rproc_vdev_release(struct kref *ref)
+{
+ struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
+
+ rproc_rvdev_remove_device(rvdev);
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC PATCH v5 4/4] remoteproc: virtio: Create platform device for the remoteproc_virtio
2022-04-06 9:54 [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Arnaud Pouliquen
` (2 preceding siblings ...)
2022-04-06 9:54 ` [RFC PATCH v5 3/4] remoteproc: Move rproc_vdev management to remoteproc_virtio.c Arnaud Pouliquen
@ 2022-04-06 9:54 ` Arnaud Pouliquen
2022-06-02 17:42 ` Mathieu Poirier
2022-05-31 17:49 ` [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Mathieu Poirier
4 siblings, 1 reply; 16+ messages in thread
From: Arnaud Pouliquen @ 2022-04-06 9:54 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, Rob Herring,
Christoph Hellwig, Stefano Stabellini, Bruce Ashfield,
arnaud.pouliquen
Define a platform driver to manage the remoteproc virtio device as
a platform devices.
The platform device allows to pass rproc_vdev_data platform data to
specify properties that are stored in the rproc_vdev structure.
Such approach will allow to preserve legacy remoteproc virtio device
creation but also to probe the device using device tree mechanism.
remoteproc_virtio.c update:
- Add rproc_virtio_driver platform driver. The probe/remove ops replace
the rproc_rvdev_add_device/rproc_rvdev_remove_device functions.
- All reference to the rvdev->dev has been updated to rvdev-pdev->dev.
- rproc_rvdev_release is removed as associated to the rvdev device.
- The use of rvdev->kref counter is replaced by get/put_device on the
remoteproc virtio platform device.
- The vdev device no longer increments rproc device counter.
increment/decrement is done in rproc_virtio_probe/rproc_virtio_remove
function in charge of the vrings allocation/free.
remoteproc_core.c update:
Migrate from the rvdev device to the rvdev platform device.
From this patch, when a vdev resource is found in the resource table
the remoteproc core register a platform device.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
Update vs previous revision:
- Updated the compatible name to align with the "virtio, <transport>"
name used for instance for "virtio,mmio"
---
drivers/remoteproc/remoteproc_core.c | 13 +-
drivers/remoteproc/remoteproc_internal.h | 3 -
drivers/remoteproc/remoteproc_virtio.c | 146 +++++++++++------------
include/linux/remoteproc.h | 6 +-
4 files changed, 84 insertions(+), 84 deletions(-)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index bd6d3f2decc6..c0c88ecaa66e 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -478,6 +478,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
struct device *dev = &rproc->dev;
struct rproc_vdev *rvdev;
struct rproc_vdev_data rvdev_data;
+ struct platform_device *pdev;
/* make sure resource isn't truncated */
if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
@@ -506,9 +507,13 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
rvdev_data.rsc_offset = offset;
rvdev_data.rsc = rsc;
- rvdev = rproc_rvdev_add_device(rproc, &rvdev_data);
- if (IS_ERR(rvdev))
- return PTR_ERR(rvdev);
+ pdev = platform_device_register_data(dev, "rproc-virtio", rvdev_data.index, &rvdev_data,
+ sizeof(rvdev_data));
+ if (IS_ERR(pdev)) {
+ dev_err(rproc->dev.parent,
+ "failed to create rproc-virtio device\n");
+ return PTR_ERR(pdev);
+ }
return 0;
}
@@ -1248,7 +1253,7 @@ void rproc_resource_cleanup(struct rproc *rproc)
/* clean up remote vdev entries */
list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)
- kref_put(&rvdev->refcount, rproc_vdev_release);
+ platform_device_unregister(rvdev->pdev);
rproc_coredump_cleanup(rproc);
}
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index f82f9a5378ae..41176f4b35c9 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -45,10 +45,7 @@ int rproc_of_parse_firmware(struct device *dev, int index,
const char **fw_name);
/* from remoteproc_virtio.c */
-struct rproc_vdev *rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data);
-void rproc_rvdev_remove_device(struct rproc_vdev *rvdev);
irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
-void rproc_vdev_release(struct kref *ref);
/* from remoteproc_debugfs.c */
void rproc_remove_trace_file(struct dentry *tfile);
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index e2e796ab2fd8..3937c1e5eb19 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -13,6 +13,7 @@
#include <linux/dma-map-ops.h>
#include <linux/dma-mapping.h>
#include <linux/export.h>
+#include <linux/of_platform.h>
#include <linux/of_reserved_mem.h>
#include <linux/remoteproc.h>
#include <linux/virtio.h>
@@ -46,7 +47,11 @@ static int copy_dma_range_map(struct device *to, struct device *from)
static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
{
- return container_of(vdev->dev.parent, struct rproc_vdev, dev);
+ struct platform_device *pdev;
+
+ pdev = container_of(vdev->dev.parent, struct platform_device, dev);
+
+ return platform_get_drvdata(pdev);
}
static struct rproc *vdev_to_rproc(struct virtio_device *vdev)
@@ -341,13 +346,10 @@ static void rproc_virtio_dev_release(struct device *dev)
{
struct virtio_device *vdev = dev_to_virtio(dev);
struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
- struct rproc *rproc = vdev_to_rproc(vdev);
kfree(vdev);
- kref_put(&rvdev->refcount, rproc_vdev_release);
-
- put_device(&rproc->dev);
+ put_device(&rvdev->pdev->dev);
}
/**
@@ -363,7 +365,7 @@ static void rproc_virtio_dev_release(struct device *dev)
static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
{
struct rproc *rproc = rvdev->rproc;
- struct device *dev = &rvdev->dev;
+ struct device *dev = &rvdev->pdev->dev;
struct virtio_device *vdev;
struct rproc_mem_entry *mem;
int ret;
@@ -433,18 +435,8 @@ static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
vdev->dev.parent = dev;
vdev->dev.release = rproc_virtio_dev_release;
- /*
- * We're indirectly making a non-temporary copy of the rproc pointer
- * here, because drivers probed with this vdev will indirectly
- * access the wrapping rproc.
- *
- * Therefore we must increment the rproc refcount here, and decrement
- * it _only_ when the vdev is released.
- */
- get_device(&rproc->dev);
-
/* Reference the vdev and vring allocations */
- kref_get(&rvdev->refcount);
+ get_device(dev);
ret = register_virtio_device(vdev);
if (ret) {
@@ -486,78 +478,57 @@ static int rproc_vdev_do_start(struct rproc_subdev *subdev)
static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
{
struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
+ struct device *dev = &rvdev->pdev->dev;
int ret;
- ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
+ ret = device_for_each_child(dev, NULL, rproc_remove_virtio_dev);
if (ret)
- dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
+ dev_warn(dev, "can't remove vdev child device: %d\n", ret);
}
-/**
- * rproc_rvdev_release() - release the existence of a rvdev
- *
- * @dev: the subdevice's dev
- */
-static void rproc_rvdev_release(struct device *dev)
-{
- struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
-
- of_reserved_mem_device_release(dev);
-
- kfree(rvdev);
-}
-
-struct rproc_vdev *
-rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
+static int rproc_virtio_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct rproc_vdev_data *rvdev_data = dev->platform_data;
struct rproc_vdev *rvdev;
- struct fw_rsc_vdev *rsc = rvdev_data->rsc;
- char name[16];
+ struct rproc *rproc = container_of(dev->parent, struct rproc, dev);
+ struct fw_rsc_vdev *rsc;
int i, ret;
- rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
- if (!rvdev)
- return ERR_PTR(-ENOMEM);
+ if (!rvdev_data)
+ return -EINVAL;
- kref_init(&rvdev->refcount);
+ rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL);
+ if (!rvdev)
+ return -ENOMEM;
rvdev->id = rvdev_data->id;
rvdev->rproc = rproc;
rvdev->index = rvdev_data->index;
- /* Initialise vdev subdevice */
- snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
- rvdev->dev.parent = &rproc->dev;
- rvdev->dev.release = rproc_rvdev_release;
- dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
- dev_set_drvdata(&rvdev->dev, rvdev);
-
- ret = device_register(&rvdev->dev);
- if (ret) {
- put_device(&rvdev->dev);
- return ERR_PTR(ret);
- }
-
- ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
+ ret = copy_dma_range_map(dev, rproc->dev.parent);
if (ret)
- goto free_rvdev;
+ return ret;
/* Make device dma capable by inheriting from parent's capabilities */
- set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
+ set_dma_ops(dev, get_dma_ops(rproc->dev.parent));
- ret = dma_coerce_mask_and_coherent(&rvdev->dev,
- dma_get_mask(rproc->dev.parent));
+ ret = dma_coerce_mask_and_coherent(dev, dma_get_mask(rproc->dev.parent));
if (ret) {
- dev_warn(&rvdev->dev,
- "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
+ dev_warn(dev, "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
}
+ 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)
- goto free_rvdev;
+ return ret;
}
/* remember the resource offset*/
@@ -577,18 +548,30 @@ rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
rproc_add_subdev(rproc, &rvdev->subdev);
- return rvdev;
+ dev_dbg(dev, "virtio dev %d added\n", rvdev->index);
+
+ /*
+ * We're indirectly making a non-temporary copy of the rproc pointer
+ * here, because the platform devicer or the vdev device will indirectly
+ * access the wrapping rproc.
+ *
+ * Therefore we must increment the rproc refcount here, and decrement
+ * it _only_ on platform remove.
+ */
+ get_device(&rproc->dev);
+
+ return 0;
unwind_vring_allocations:
for (i--; i >= 0; i--)
rproc_free_vring(&rvdev->vring[i]);
-free_rvdev:
- device_unregister(&rvdev->dev);
- return ERR_PTR(ret);
+
+ return ret;
}
-void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
+static int rproc_virtio_remove(struct platform_device *pdev)
{
+ struct rproc_vdev *rvdev = dev_get_drvdata(&pdev->dev);
struct rproc *rproc = rvdev->rproc;
struct rproc_vring *rvring;
int id;
@@ -600,12 +583,29 @@ void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
rproc_remove_subdev(rproc, &rvdev->subdev);
rproc_remove_rvdev(rvdev);
- device_unregister(&rvdev->dev);
-}
-void rproc_vdev_release(struct kref *ref)
-{
- struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
+ of_reserved_mem_device_release(&pdev->dev);
+
+ dev_dbg(&pdev->dev, "virtio dev %d removed\n", rvdev->index);
- rproc_rvdev_remove_device(rvdev);
+ /* The remote proc device can be removed */
+ put_device(&rproc->dev);
+
+ return 0;
}
+
+/* Platform driver */
+static const struct of_device_id rproc_virtio_match[] = {
+ { .compatible = "virtio,rproc", },
+ {},
+};
+
+static struct platform_driver rproc_virtio_driver = {
+ .probe = rproc_virtio_probe,
+ .remove = rproc_virtio_remove,
+ .driver = {
+ .name = "rproc-virtio",
+ .of_match_table = rproc_virtio_match,
+ },
+};
+builtin_platform_driver(rproc_virtio_driver);
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 7c943f0a2fc4..64b9809d0ec1 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -616,9 +616,8 @@ struct rproc_vring {
/**
* struct rproc_vdev - remoteproc state for a supported virtio device
- * @refcount: reference counter for the vdev and vring allocations
* @subdev: handle for registering the vdev as a rproc subdevice
- * @dev: device struct used for reference count semantics
+ * @pdev: remoteproc virtio platform device
* @id: virtio device id (as in virtio_ids.h)
* @node: list node
* @rproc: the rproc handle
@@ -627,10 +626,9 @@ struct rproc_vring {
* @index: vdev position versus other vdev declared in resource table
*/
struct rproc_vdev {
- struct kref refcount;
struct rproc_subdev subdev;
- struct device dev;
+ struct platform_device *pdev;
unsigned int id;
struct list_head node;
--
2.25.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device
2022-04-06 9:54 [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Arnaud Pouliquen
` (3 preceding siblings ...)
2022-04-06 9:54 ` [RFC PATCH v5 4/4] remoteproc: virtio: Create platform device for the remoteproc_virtio Arnaud Pouliquen
@ 2022-05-31 17:49 ` Mathieu Poirier
4 siblings, 0 replies; 16+ messages in thread
From: Mathieu Poirier @ 2022-05-31 17:49 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
I have started looking at this set. Comments to follow in the coming days.
Thanks,
Mathieu
On Wed, Apr 06, 2022 at 11:54:42AM +0200, Arnaud Pouliquen wrote:
> 1) Update from V4 [1]:
>
> Minor updates based on Mathieu's comments.
> Updates are listed in the commit message of each patch.
>
> [1] https://lkml.org/lkml/2022/3/14/1177
>
> 2) Patchset description:
>
> This series is a part of the work initiated a long time ago in
> the series "remoteproc: Decorelate virtio from core"[2]
>
> Objective of the work:
> - Update the remoteproc VirtIO device creation (use platform device)
> - Allow to declare remoteproc VirtIO device in DT
> - declare resources associated to a remote proc VirtIO
> - declare a list of VirtIO supported by the platform.
> - Prepare the enhancement to more VirtIO devices (e.g I2C, audio, video, ...).
> For instance be able to declare a I2C device in a virtio-i2C node.
> - Keep the legacy working!
> - Try to improve the picture about concerns reported by Christoph Hellwing [3][4]
>
> [2] https://lkml.org/lkml/2020/4/16/1817
> [3] https://lkml.org/lkml/2021/6/23/607
> [4] https://patchwork.kernel.org/project/linux-remoteproc/patch/AOKowLclCbOCKxyiJ71WeNyuAAj2q8EUtxrXbyky5E@cp7-web-042.plabs.ch/
>
> In term of device tree this would result in such hierarchy (stm32mp1 example with 2 virtio RPMSG):
>
> m4_rproc: m4@10000000 {
> compatible = "st,stm32mp1-m4";
> reg = <0x10000000 0x40000>,
> <0x30000000 0x40000>,
> <0x38000000 0x10000>;
> memory-region = <&retram>, <&mcuram>,<&mcuram2>;
> mboxes = <&ipcc 2>, <&ipcc 3>;
> mbox-names = "shutdown", "detach";
> status = "okay";
>
> #address-cells = <1>;
> #size-cells = <0>;
>
> vdev@0 {
> compatible = "rproc-virtio";
> reg = <0>;
> virtio,id = <7>; /* RPMSG */
> memory-region = <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>;
> mboxes = <&ipcc 0>, <&ipcc 1>;
> mbox-names = "vq0", "vq1";
> status = "okay";
> };
>
> vdev@1 {
> compatible = "rproc-virtio";
> reg = <1>;
> virtio,id = <7>; /*RPMSG */
> memory-region = <&vdev1vring0>, <&vdev1vring1>, <&vdev1buffer>;
> mboxes = <&ipcc 4>, <&ipcc 5>;
> mbox-names = "vq0", "vq1";
> status = "okay";
> };
> };
>
> I have divided the work in 4 steps to simplify the review, This series implements only
> the step 1:
> step 1: redefine the remoteproc VirtIO device as a platform device
> - migrate rvdev management in remoteproc virtio.c,
> - create a remotproc virtio config ( can be disabled for platform that not use VirtIO IPC.
> step 2: add possibility to declare and probe a VirtIO sub node
> - VirtIO bindings declaration,
> - multi DT VirtIO devices support,
> - introduction of a remote proc virtio bind device mechanism ,
> => https://github.com/arnopo/linux/commits/step2-virtio-in-DT
> step 3: Add memory declaration in VirtIO subnode
> => https://github.com/arnopo/linux/commits/step3-virtio-memories
> step 4: Add mailbox declaration in VirtIO subnode
> => https://github.com/arnopo/linux/commits/step4-virtio-mailboxes
>
> Arnaud Pouliquen (4):
> remoteproc: core: Introduce virtio device add/remove functions
> remoteproc: core: Introduce rproc_register_rvdev function
> remoteproc: Move rproc_vdev management to remoteproc_virtio.c
> remoteproc: virtio: Create platform device for the remoteproc_virtio
>
> drivers/remoteproc/remoteproc_core.c | 154 +++---------------
> drivers/remoteproc/remoteproc_internal.h | 23 ++-
> drivers/remoteproc/remoteproc_virtio.c | 193 ++++++++++++++++++++---
> include/linux/remoteproc.h | 6 +-
> 4 files changed, 215 insertions(+), 161 deletions(-)
>
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions
2022-04-06 9:54 ` [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions Arnaud Pouliquen
@ 2022-06-01 17:29 ` Mathieu Poirier
2022-06-02 17:51 ` Mathieu Poirier
0 siblings, 1 reply; 16+ messages in thread
From: Mathieu Poirier @ 2022-06-01 17:29 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Wed, Apr 06, 2022 at 11:54:43AM +0200, Arnaud Pouliquen wrote:
> In preparation of the migration of the management of rvdev in
> remoteproc_virtio.c, this patch spins off new functions to manage the
> remoteproc virtio device.
> - rproc_rvdev_add_device
> - rproc_rvdev_remove_device
>
> The rproc_rvdev_add_device and rproc_rvdev_remove_device will be
> moved to remoteproc_virtio.c.
>
> The rproc_vdev_data structure is introduced to provide information for
> the rvdev creation. This structure allows to manage the rvdev and vrings
> allocation in the rproc_rvdev_add_device function.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> ---
> drivers/remoteproc/remoteproc_core.c | 157 +++++++++++++----------
> drivers/remoteproc/remoteproc_internal.h | 15 +++
> 2 files changed, 106 insertions(+), 66 deletions(-)
>
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index c510125769b9..3a469220ac73 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -484,74 +484,23 @@ static int copy_dma_range_map(struct device *to, struct device *from)
> return 0;
> }
>
> -/**
> - * rproc_handle_vdev() - handle a vdev fw resource
> - * @rproc: the remote processor
> - * @ptr: the vring resource descriptor
> - * @offset: offset of the resource entry
> - * @avail: size of available data (for sanity checking the image)
> - *
> - * This resource entry requests the host to statically register a virtio
> - * device (vdev), and setup everything needed to support it. It contains
> - * everything needed to make it possible: the virtio device id, virtio
> - * device features, vrings information, virtio config space, etc...
> - *
> - * Before registering the vdev, the vrings are allocated from non-cacheable
> - * physically contiguous memory. Currently we only support two vrings per
> - * remote processor (temporary limitation). We might also want to consider
> - * doing the vring allocation only later when ->find_vqs() is invoked, and
> - * then release them upon ->del_vqs().
> - *
> - * Note: @da is currently not really handled correctly: we dynamically
> - * allocate it using the DMA API, ignoring requested hard coded addresses,
> - * and we don't take care of any required IOMMU programming. This is all
> - * going to be taken care of when the generic iommu-based DMA API will be
> - * merged. Meanwhile, statically-addressed iommu-based firmware images should
> - * use RSC_DEVMEM resource entries to map their required @da to the physical
> - * address of their base CMA region (ouch, hacky!).
> - *
> - * Return: 0 on success, or an appropriate error code otherwise
> - */
> -static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> - int offset, int avail)
> +static struct rproc_vdev *
> +rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> {
> - struct fw_rsc_vdev *rsc = ptr;
> - struct device *dev = &rproc->dev;
> struct rproc_vdev *rvdev;
> - int i, ret;
> + struct fw_rsc_vdev *rsc = rvdev_data->rsc;
> char name[16];
> -
> - /* make sure resource isn't truncated */
> - if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
> - avail) {
> - dev_err(dev, "vdev rsc is truncated\n");
> - return -EINVAL;
> - }
> -
> - /* make sure reserved bytes are zeroes */
> - if (rsc->reserved[0] || rsc->reserved[1]) {
> - dev_err(dev, "vdev rsc has non zero reserved bytes\n");
> - return -EINVAL;
> - }
> -
> - 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;
> - }
> + int i, ret;
>
> rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
> if (!rvdev)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> kref_init(&rvdev->refcount);
>
> - rvdev->id = rsc->id;
> + rvdev->id = rvdev_data->id;
> rvdev->rproc = rproc;
> - rvdev->index = rproc->nb_vdev++;
> + rvdev->index = rvdev_data->index;
>
> /* Initialise vdev subdevice */
> snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> @@ -563,7 +512,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> ret = device_register(&rvdev->dev);
> if (ret) {
> put_device(&rvdev->dev);
> - return ret;
> + return ERR_PTR(ret);
> }
>
> ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> @@ -576,7 +525,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> ret = dma_coerce_mask_and_coherent(&rvdev->dev,
> dma_get_mask(rproc->dev.parent));
> if (ret) {
> - dev_warn(dev,
> + dev_warn(&rvdev->dev,
> "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
> }
> @@ -589,7 +538,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> }
>
> /* remember the resource offset*/
> - rvdev->rsc_offset = offset;
> + rvdev->rsc_offset = rvdev_data->rsc_offset;
>
> /* allocate the vring resources */
> for (i = 0; i < rsc->num_of_vrings; i++) {
> @@ -605,21 +554,20 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
>
> rproc_add_subdev(rproc, &rvdev->subdev);
>
> - return 0;
> + return rvdev;
>
> unwind_vring_allocations:
> for (i--; i >= 0; i--)
> rproc_free_vring(&rvdev->vring[i]);
> free_rvdev:
> device_unregister(&rvdev->dev);
> - return ret;
> + return ERR_PTR(ret);
> }
>
> -void rproc_vdev_release(struct kref *ref)
> +static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> {
> - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> - struct rproc_vring *rvring;
> struct rproc *rproc = rvdev->rproc;
> + struct rproc_vring *rvring;
> int id;
>
> for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> @@ -632,6 +580,83 @@ void rproc_vdev_release(struct kref *ref)
> device_unregister(&rvdev->dev);
> }
>
> +/**
> + * rproc_handle_vdev() - handle a vdev fw resource
> + * @rproc: the remote processor
> + * @ptr: the vring resource descriptor
> + * @offset: offset of the resource entry
> + * @avail: size of available data (for sanity checking the image)
> + *
> + * This resource entry requests the host to statically register a virtio
> + * device (vdev), and setup everything needed to support it. It contains
> + * everything needed to make it possible: the virtio device id, virtio
> + * device features, vrings information, virtio config space, etc...
> + *
> + * Before registering the vdev, the vrings are allocated from non-cacheable
> + * physically contiguous memory. Currently we only support two vrings per
> + * remote processor (temporary limitation). We might also want to consider
> + * doing the vring allocation only later when ->find_vqs() is invoked, and
> + * then release them upon ->del_vqs().
> + *
> + * Note: @da is currently not really handled correctly: we dynamically
> + * allocate it using the DMA API, ignoring requested hard coded addresses,
> + * and we don't take care of any required IOMMU programming. This is all
> + * going to be taken care of when the generic iommu-based DMA API will be
> + * merged. Meanwhile, statically-addressed iommu-based firmware images should
> + * use RSC_DEVMEM resource entries to map their required @da to the physical
> + * address of their base CMA region (ouch, hacky!).
> + *
> + * Return: 0 on success, or an appropriate error code otherwise
> + */
> +static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> + int offset, int avail)
> +{
> + struct fw_rsc_vdev *rsc = ptr;
> + struct device *dev = &rproc->dev;
> + struct rproc_vdev *rvdev;
> + struct rproc_vdev_data rvdev_data;
> +
> + /* make sure resource isn't truncated */
> + if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
> + avail) {
> + dev_err(dev, "vdev rsc is truncated\n");
> + return -EINVAL;
> + }
> +
> + /* make sure reserved bytes are zeroes */
> + if (rsc->reserved[0] || rsc->reserved[1]) {
> + dev_err(dev, "vdev rsc has non zero reserved bytes\n");
> + return -EINVAL;
> + }
> +
> + 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;
> + rvdev_data.rsc = rsc;
> +
> + rvdev = rproc_rvdev_add_device(rproc, &rvdev_data);
> + if (IS_ERR(rvdev))
> + return PTR_ERR(rvdev);
> +
> + return 0;
> +}
> +
> +void rproc_vdev_release(struct kref *ref)
> +{
> + struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> +
> + rproc_rvdev_remove_device(rvdev);
> +}
> +
> /**
> * rproc_handle_trace() - handle a shared trace buffer resource
> * @rproc: the remote processor
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index 72d4d3d7d94d..99f2ff88079f 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -24,6 +24,21 @@ struct rproc_debug_trace {
> struct rproc_mem_entry trace_mem;
> };
>
> +/**
> + * struct rproc_vdev_data - remoteproc virtio device data
> + * @rsc_offset: offset of the vdev's resource entry
> + * @id: virtio device id (as in virtio_ids.h)
> + * @index: vdev position versus other vdev declared in resource table
> + * @rsc: pointer to the vdev resource entry. Valid onlyduring vdev init as the resource can
> + * be cached by rproc.
> + */
> +struct rproc_vdev_data {
> + u32 rsc_offset;
> + unsigned int id;
> + unsigned int index;
rvdev->index is a u32 so rproc_vdev_data::index should also be a u32.
With the above:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> + struct fw_rsc_vdev *rsc;
> +};
> +
> /* from remoteproc_core.c */
> void rproc_release(struct kref *kref);
> irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function
2022-04-06 9:54 ` [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function Arnaud Pouliquen
@ 2022-06-01 17:41 ` Mathieu Poirier
2022-06-03 11:53 ` Arnaud POULIQUEN
0 siblings, 1 reply; 16+ messages in thread
From: Mathieu Poirier @ 2022-06-01 17:41 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Wed, Apr 06, 2022 at 11:54:44AM +0200, Arnaud Pouliquen wrote:
> The rproc structure contains a list of registered rproc_vdev structure.
This should be rproc_rvdev.
> To be able to move the management of the rproc_vdev structure in
> remoteproc_virtio.c (i.e rproc_rvdev_add_device and
> rproc_rvdev_remove_device functions), introduce the rproc_register_rvdev
> and rproc_unregister_rvdev functions.
The name of those functions doesn't match the content of the patch.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> ---
> drivers/remoteproc/remoteproc_core.c | 16 ++++++++++++++--
> 1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 3a469220ac73..081bea39daf4 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -484,6 +484,18 @@ static int copy_dma_range_map(struct device *to, struct device *from)
> return 0;
> }
>
> +static void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
> +{
> + if (rvdev && rproc)
> + list_add_tail(&rvdev->node, &rproc->rvdevs);
> +}
> +
> +static void rproc_remove_rvdev(struct rproc_vdev *rvdev)
> +{
> + if (rvdev)
> + list_del(&rvdev->node);
> +}
> +
> static struct rproc_vdev *
> rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> {
> @@ -547,7 +559,7 @@ rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> goto unwind_vring_allocations;
> }
>
> - list_add_tail(&rvdev->node, &rproc->rvdevs);
> + rproc_add_rvdev(rproc, rvdev);
>
> rvdev->subdev.start = rproc_vdev_do_start;
> rvdev->subdev.stop = rproc_vdev_do_stop;
> @@ -576,7 +588,7 @@ static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> }
>
> rproc_remove_subdev(rproc, &rvdev->subdev);
> - list_del(&rvdev->node);
> + rproc_remove_rvdev(rvdev);
With the above:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> device_unregister(&rvdev->dev);
> }
>
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 4/4] remoteproc: virtio: Create platform device for the remoteproc_virtio
2022-04-06 9:54 ` [RFC PATCH v5 4/4] remoteproc: virtio: Create platform device for the remoteproc_virtio Arnaud Pouliquen
@ 2022-06-02 17:42 ` Mathieu Poirier
0 siblings, 0 replies; 16+ messages in thread
From: Mathieu Poirier @ 2022-06-02 17:42 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Wed, Apr 06, 2022 at 11:54:46AM +0200, Arnaud Pouliquen wrote:
> Define a platform driver to manage the remoteproc virtio device as
> a platform devices.
>
> The platform device allows to pass rproc_vdev_data platform data to
> specify properties that are stored in the rproc_vdev structure.
>
> Such approach will allow to preserve legacy remoteproc virtio device
> creation but also to probe the device using device tree mechanism.
>
> remoteproc_virtio.c update:
> - Add rproc_virtio_driver platform driver. The probe/remove ops replace
> the rproc_rvdev_add_device/rproc_rvdev_remove_device functions.
> - All reference to the rvdev->dev has been updated to rvdev-pdev->dev.
> - rproc_rvdev_release is removed as associated to the rvdev device.
> - The use of rvdev->kref counter is replaced by get/put_device on the
> remoteproc virtio platform device.
> - The vdev device no longer increments rproc device counter.
> increment/decrement is done in rproc_virtio_probe/rproc_virtio_remove
> function in charge of the vrings allocation/free.
>
> remoteproc_core.c update:
> Migrate from the rvdev device to the rvdev platform device.
> From this patch, when a vdev resource is found in the resource table
> the remoteproc core register a platform device.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> ---
> Update vs previous revision:
> - Updated the compatible name to align with the "virtio, <transport>"
> name used for instance for "virtio,mmio"
> ---
> drivers/remoteproc/remoteproc_core.c | 13 +-
> drivers/remoteproc/remoteproc_internal.h | 3 -
> drivers/remoteproc/remoteproc_virtio.c | 146 +++++++++++------------
> include/linux/remoteproc.h | 6 +-
> 4 files changed, 84 insertions(+), 84 deletions(-)
>
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index bd6d3f2decc6..c0c88ecaa66e 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -478,6 +478,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> struct device *dev = &rproc->dev;
> struct rproc_vdev *rvdev;
> struct rproc_vdev_data rvdev_data;
> + struct platform_device *pdev;
>
> /* make sure resource isn't truncated */
> if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
> @@ -506,9 +507,13 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> rvdev_data.rsc_offset = offset;
> rvdev_data.rsc = rsc;
>
> - rvdev = rproc_rvdev_add_device(rproc, &rvdev_data);
> - if (IS_ERR(rvdev))
> - return PTR_ERR(rvdev);
> + pdev = platform_device_register_data(dev, "rproc-virtio", rvdev_data.index, &rvdev_data,
> + sizeof(rvdev_data));
> + if (IS_ERR(pdev)) {
> + dev_err(rproc->dev.parent,
dev_err(dev,
> + "failed to create rproc-virtio device\n");
> + return PTR_ERR(pdev);
> + }
>
> return 0;
> }
> @@ -1248,7 +1253,7 @@ void rproc_resource_cleanup(struct rproc *rproc)
>
> /* clean up remote vdev entries */
> list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)
> - kref_put(&rvdev->refcount, rproc_vdev_release);
> + platform_device_unregister(rvdev->pdev);
>
> rproc_coredump_cleanup(rproc);
> }
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index f82f9a5378ae..41176f4b35c9 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -45,10 +45,7 @@ int rproc_of_parse_firmware(struct device *dev, int index,
> const char **fw_name);
>
> /* from remoteproc_virtio.c */
> -struct rproc_vdev *rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data);
> -void rproc_rvdev_remove_device(struct rproc_vdev *rvdev);
> irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
> -void rproc_vdev_release(struct kref *ref);
>
> /* from remoteproc_debugfs.c */
> void rproc_remove_trace_file(struct dentry *tfile);
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index e2e796ab2fd8..3937c1e5eb19 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -13,6 +13,7 @@
> #include <linux/dma-map-ops.h>
> #include <linux/dma-mapping.h>
> #include <linux/export.h>
> +#include <linux/of_platform.h>
> #include <linux/of_reserved_mem.h>
> #include <linux/remoteproc.h>
> #include <linux/virtio.h>
> @@ -46,7 +47,11 @@ static int copy_dma_range_map(struct device *to, struct device *from)
>
> static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
> {
> - return container_of(vdev->dev.parent, struct rproc_vdev, dev);
> + struct platform_device *pdev;
> +
> + pdev = container_of(vdev->dev.parent, struct platform_device, dev);
> +
> + return platform_get_drvdata(pdev);
> }
>
> static struct rproc *vdev_to_rproc(struct virtio_device *vdev)
> @@ -341,13 +346,10 @@ static void rproc_virtio_dev_release(struct device *dev)
> {
> struct virtio_device *vdev = dev_to_virtio(dev);
> struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
> - struct rproc *rproc = vdev_to_rproc(vdev);
>
> kfree(vdev);
>
> - kref_put(&rvdev->refcount, rproc_vdev_release);
> -
> - put_device(&rproc->dev);
> + put_device(&rvdev->pdev->dev);
> }
>
> /**
> @@ -363,7 +365,7 @@ static void rproc_virtio_dev_release(struct device *dev)
> static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
> {
> struct rproc *rproc = rvdev->rproc;
> - struct device *dev = &rvdev->dev;
> + struct device *dev = &rvdev->pdev->dev;
> struct virtio_device *vdev;
> struct rproc_mem_entry *mem;
> int ret;
> @@ -433,18 +435,8 @@ static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
> vdev->dev.parent = dev;
> vdev->dev.release = rproc_virtio_dev_release;
>
> - /*
> - * We're indirectly making a non-temporary copy of the rproc pointer
> - * here, because drivers probed with this vdev will indirectly
> - * access the wrapping rproc.
> - *
> - * Therefore we must increment the rproc refcount here, and decrement
> - * it _only_ when the vdev is released.
> - */
> - get_device(&rproc->dev);
> -
> /* Reference the vdev and vring allocations */
> - kref_get(&rvdev->refcount);
> + get_device(dev);
>
> ret = register_virtio_device(vdev);
> if (ret) {
> @@ -486,78 +478,57 @@ static int rproc_vdev_do_start(struct rproc_subdev *subdev)
> static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
> {
> struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> + struct device *dev = &rvdev->pdev->dev;
> int ret;
>
> - ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
> + ret = device_for_each_child(dev, NULL, rproc_remove_virtio_dev);
> if (ret)
> - dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
> + dev_warn(dev, "can't remove vdev child device: %d\n", ret);
> }
>
> -/**
> - * rproc_rvdev_release() - release the existence of a rvdev
> - *
> - * @dev: the subdevice's dev
> - */
> -static void rproc_rvdev_release(struct device *dev)
> -{
> - struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
> -
> - of_reserved_mem_device_release(dev);
> -
> - kfree(rvdev);
> -}
> -
> -struct rproc_vdev *
> -rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> +static int rproc_virtio_probe(struct platform_device *pdev)
> {
> + struct device *dev = &pdev->dev;
> + struct rproc_vdev_data *rvdev_data = dev->platform_data;
> struct rproc_vdev *rvdev;
> - struct fw_rsc_vdev *rsc = rvdev_data->rsc;
> - char name[16];
> + struct rproc *rproc = container_of(dev->parent, struct rproc, dev);
> + struct fw_rsc_vdev *rsc;
> int i, ret;
>
> - rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
> - if (!rvdev)
> - return ERR_PTR(-ENOMEM);
> + if (!rvdev_data)
> + return -EINVAL;
>
> - kref_init(&rvdev->refcount);
> + rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL);
> + if (!rvdev)
> + return -ENOMEM;
>
> rvdev->id = rvdev_data->id;
> rvdev->rproc = rproc;
> rvdev->index = rvdev_data->index;
>
> - /* Initialise vdev subdevice */
> - snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> - rvdev->dev.parent = &rproc->dev;
> - rvdev->dev.release = rproc_rvdev_release;
> - dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
> - dev_set_drvdata(&rvdev->dev, rvdev);
> -
> - ret = device_register(&rvdev->dev);
> - if (ret) {
> - put_device(&rvdev->dev);
> - return ERR_PTR(ret);
> - }
> -
> - ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> + ret = copy_dma_range_map(dev, rproc->dev.parent);
> if (ret)
> - goto free_rvdev;
> + return ret;
>
> /* Make device dma capable by inheriting from parent's capabilities */
> - set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
> + set_dma_ops(dev, get_dma_ops(rproc->dev.parent));
>
> - ret = dma_coerce_mask_and_coherent(&rvdev->dev,
> - dma_get_mask(rproc->dev.parent));
> + ret = dma_coerce_mask_and_coherent(dev, dma_get_mask(rproc->dev.parent));
> if (ret) {
> - dev_warn(&rvdev->dev,
> - "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> + dev_warn(dev, "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
> }
>
> + 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)
> - goto free_rvdev;
> + return ret;
> }
>
> /* remember the resource offset*/
> @@ -577,18 +548,30 @@ rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
>
> rproc_add_subdev(rproc, &rvdev->subdev);
>
> - return rvdev;
> + dev_dbg(dev, "virtio dev %d added\n", rvdev->index);
Please remove this along with the one in rproc_vdev_release().
> +
> + /*
> + * We're indirectly making a non-temporary copy of the rproc pointer
> + * here, because the platform devicer or the vdev device will indirectly
> + * access the wrapping rproc.
> + *
> + * Therefore we must increment the rproc refcount here, and decrement
> + * it _only_ on platform remove.
> + */
> + get_device(&rproc->dev);
> +
> + return 0;
>
> unwind_vring_allocations:
> for (i--; i >= 0; i--)
> rproc_free_vring(&rvdev->vring[i]);
> -free_rvdev:
> - device_unregister(&rvdev->dev);
> - return ERR_PTR(ret);
> +
> + return ret;
> }
>
> -void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> +static int rproc_virtio_remove(struct platform_device *pdev)
> {
> + struct rproc_vdev *rvdev = dev_get_drvdata(&pdev->dev);
> struct rproc *rproc = rvdev->rproc;
> struct rproc_vring *rvring;
> int id;
> @@ -600,12 +583,29 @@ void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
>
> rproc_remove_subdev(rproc, &rvdev->subdev);
> rproc_remove_rvdev(rvdev);
> - device_unregister(&rvdev->dev);
> -}
>
> -void rproc_vdev_release(struct kref *ref)
> -{
> - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> + of_reserved_mem_device_release(&pdev->dev);
> +
> + dev_dbg(&pdev->dev, "virtio dev %d removed\n", rvdev->index);
>
> - rproc_rvdev_remove_device(rvdev);
> + /* The remote proc device can be removed */
This comment doesn't make sense - the remoteproc device can't be removed here.
Please refactor.
Thanks,
Mathieu
> + put_device(&rproc->dev);
> +
> + return 0;
> }
> +
> +/* Platform driver */
> +static const struct of_device_id rproc_virtio_match[] = {
> + { .compatible = "virtio,rproc", },
> + {},
> +};
> +
> +static struct platform_driver rproc_virtio_driver = {
> + .probe = rproc_virtio_probe,
> + .remove = rproc_virtio_remove,
> + .driver = {
> + .name = "rproc-virtio",
> + .of_match_table = rproc_virtio_match,
> + },
> +};
> +builtin_platform_driver(rproc_virtio_driver);
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index 7c943f0a2fc4..64b9809d0ec1 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -616,9 +616,8 @@ struct rproc_vring {
>
> /**
> * struct rproc_vdev - remoteproc state for a supported virtio device
> - * @refcount: reference counter for the vdev and vring allocations
> * @subdev: handle for registering the vdev as a rproc subdevice
> - * @dev: device struct used for reference count semantics
> + * @pdev: remoteproc virtio platform device
> * @id: virtio device id (as in virtio_ids.h)
> * @node: list node
> * @rproc: the rproc handle
> @@ -627,10 +626,9 @@ struct rproc_vring {
> * @index: vdev position versus other vdev declared in resource table
> */
> struct rproc_vdev {
> - struct kref refcount;
>
> struct rproc_subdev subdev;
> - struct device dev;
> + struct platform_device *pdev;
>
> unsigned int id;
> struct list_head node;
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions
2022-06-01 17:29 ` Mathieu Poirier
@ 2022-06-02 17:51 ` Mathieu Poirier
2022-06-02 17:52 ` Mathieu Poirier
0 siblings, 1 reply; 16+ messages in thread
From: Mathieu Poirier @ 2022-06-02 17:51 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Wed, Jun 01, 2022 at 11:29:45AM -0600, Mathieu Poirier wrote:
> On Wed, Apr 06, 2022 at 11:54:43AM +0200, Arnaud Pouliquen wrote:
> > In preparation of the migration of the management of rvdev in
> > remoteproc_virtio.c, this patch spins off new functions to manage the
> > remoteproc virtio device.
> > - rproc_rvdev_add_device
> > - rproc_rvdev_remove_device
> >
> > The rproc_rvdev_add_device and rproc_rvdev_remove_device will be
> > moved to remoteproc_virtio.c.
> >
> > The rproc_vdev_data structure is introduced to provide information for
> > the rvdev creation. This structure allows to manage the rvdev and vrings
> > allocation in the rproc_rvdev_add_device function.
> >
> > Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> > ---
> > drivers/remoteproc/remoteproc_core.c | 157 +++++++++++++----------
> > drivers/remoteproc/remoteproc_internal.h | 15 +++
> > 2 files changed, 106 insertions(+), 66 deletions(-)
> >
> > diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> > index c510125769b9..3a469220ac73 100644
> > --- a/drivers/remoteproc/remoteproc_core.c
> > +++ b/drivers/remoteproc/remoteproc_core.c
> > @@ -484,74 +484,23 @@ static int copy_dma_range_map(struct device *to, struct device *from)
> > return 0;
> > }
> >
> > -/**
> > - * rproc_handle_vdev() - handle a vdev fw resource
> > - * @rproc: the remote processor
> > - * @ptr: the vring resource descriptor
> > - * @offset: offset of the resource entry
> > - * @avail: size of available data (for sanity checking the image)
> > - *
> > - * This resource entry requests the host to statically register a virtio
> > - * device (vdev), and setup everything needed to support it. It contains
> > - * everything needed to make it possible: the virtio device id, virtio
> > - * device features, vrings information, virtio config space, etc...
> > - *
> > - * Before registering the vdev, the vrings are allocated from non-cacheable
> > - * physically contiguous memory. Currently we only support two vrings per
> > - * remote processor (temporary limitation). We might also want to consider
> > - * doing the vring allocation only later when ->find_vqs() is invoked, and
> > - * then release them upon ->del_vqs().
> > - *
> > - * Note: @da is currently not really handled correctly: we dynamically
> > - * allocate it using the DMA API, ignoring requested hard coded addresses,
> > - * and we don't take care of any required IOMMU programming. This is all
> > - * going to be taken care of when the generic iommu-based DMA API will be
> > - * merged. Meanwhile, statically-addressed iommu-based firmware images should
> > - * use RSC_DEVMEM resource entries to map their required @da to the physical
> > - * address of their base CMA region (ouch, hacky!).
> > - *
> > - * Return: 0 on success, or an appropriate error code otherwise
> > - */
> > -static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > - int offset, int avail)
> > +static struct rproc_vdev *
> > +rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> > {
> > - struct fw_rsc_vdev *rsc = ptr;
> > - struct device *dev = &rproc->dev;
> > struct rproc_vdev *rvdev;
> > - int i, ret;
> > + struct fw_rsc_vdev *rsc = rvdev_data->rsc;
> > char name[16];
> > -
> > - /* make sure resource isn't truncated */
> > - if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
> > - avail) {
> > - dev_err(dev, "vdev rsc is truncated\n");
> > - return -EINVAL;
> > - }
> > -
> > - /* make sure reserved bytes are zeroes */
> > - if (rsc->reserved[0] || rsc->reserved[1]) {
> > - dev_err(dev, "vdev rsc has non zero reserved bytes\n");
> > - return -EINVAL;
> > - }
> > -
> > - 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;
> > - }
> > + int i, ret;
> >
> > rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
> > if (!rvdev)
> > - return -ENOMEM;
> > + return ERR_PTR(-ENOMEM);
> >
> > kref_init(&rvdev->refcount);
> >
> > - rvdev->id = rsc->id;
> > + rvdev->id = rvdev_data->id;
> > rvdev->rproc = rproc;
> > - rvdev->index = rproc->nb_vdev++;
> > + rvdev->index = rvdev_data->index;
> >
> > /* Initialise vdev subdevice */
> > snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> > @@ -563,7 +512,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > ret = device_register(&rvdev->dev);
> > if (ret) {
> > put_device(&rvdev->dev);
> > - return ret;
> > + return ERR_PTR(ret);
> > }
> >
> > ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> > @@ -576,7 +525,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > ret = dma_coerce_mask_and_coherent(&rvdev->dev,
> > dma_get_mask(rproc->dev.parent));
> > if (ret) {
> > - dev_warn(dev,
> > + dev_warn(&rvdev->dev,
> > "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> > dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
> > }
> > @@ -589,7 +538,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > }
> >
> > /* remember the resource offset*/
> > - rvdev->rsc_offset = offset;
> > + rvdev->rsc_offset = rvdev_data->rsc_offset;
> >
> > /* allocate the vring resources */
> > for (i = 0; i < rsc->num_of_vrings; i++) {
> > @@ -605,21 +554,20 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> >
> > rproc_add_subdev(rproc, &rvdev->subdev);
> >
> > - return 0;
> > + return rvdev;
> >
> > unwind_vring_allocations:
> > for (i--; i >= 0; i--)
> > rproc_free_vring(&rvdev->vring[i]);
> > free_rvdev:
> > device_unregister(&rvdev->dev);
> > - return ret;
> > + return ERR_PTR(ret);
> > }
> >
> > -void rproc_vdev_release(struct kref *ref)
> > +static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> > {
> > - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> > - struct rproc_vring *rvring;
> > struct rproc *rproc = rvdev->rproc;
> > + struct rproc_vring *rvring;
> > int id;
> >
> > for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> > @@ -632,6 +580,83 @@ void rproc_vdev_release(struct kref *ref)
> > device_unregister(&rvdev->dev);
> > }
> >
> > +/**
> > + * rproc_handle_vdev() - handle a vdev fw resource
> > + * @rproc: the remote processor
> > + * @ptr: the vring resource descriptor
> > + * @offset: offset of the resource entry
> > + * @avail: size of available data (for sanity checking the image)
> > + *
> > + * This resource entry requests the host to statically register a virtio
> > + * device (vdev), and setup everything needed to support it. It contains
> > + * everything needed to make it possible: the virtio device id, virtio
> > + * device features, vrings information, virtio config space, etc...
> > + *
> > + * Before registering the vdev, the vrings are allocated from non-cacheable
> > + * physically contiguous memory. Currently we only support two vrings per
> > + * remote processor (temporary limitation). We might also want to consider
> > + * doing the vring allocation only later when ->find_vqs() is invoked, and
> > + * then release them upon ->del_vqs().
> > + *
> > + * Note: @da is currently not really handled correctly: we dynamically
> > + * allocate it using the DMA API, ignoring requested hard coded addresses,
> > + * and we don't take care of any required IOMMU programming. This is all
> > + * going to be taken care of when the generic iommu-based DMA API will be
> > + * merged. Meanwhile, statically-addressed iommu-based firmware images should
> > + * use RSC_DEVMEM resource entries to map their required @da to the physical
> > + * address of their base CMA region (ouch, hacky!).
> > + *
> > + * Return: 0 on success, or an appropriate error code otherwise
> > + */
> > +static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > + int offset, int avail)
> > +{
> > + struct fw_rsc_vdev *rsc = ptr;
> > + struct device *dev = &rproc->dev;
> > + struct rproc_vdev *rvdev;
> > + struct rproc_vdev_data rvdev_data;
> > +
> > + /* make sure resource isn't truncated */
> > + if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
> > + avail) {
> > + dev_err(dev, "vdev rsc is truncated\n");
> > + return -EINVAL;
> > + }
> > +
> > + /* make sure reserved bytes are zeroes */
> > + if (rsc->reserved[0] || rsc->reserved[1]) {
> > + dev_err(dev, "vdev rsc has non zero reserved bytes\n");
> > + return -EINVAL;
> > + }
> > +
> > + 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;
> > + rvdev_data.rsc = rsc;
> > +
> > + rvdev = rproc_rvdev_add_device(rproc, &rvdev_data);
> > + if (IS_ERR(rvdev))
> > + return PTR_ERR(rvdev);
> > +
> > + return 0;
> > +}
> > +
> > +void rproc_vdev_release(struct kref *ref)
> > +{
> > + struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> > +
> > + rproc_rvdev_remove_device(rvdev);
I understand that rproc_rvdev_remove_device() is created to counter balance
rproc_rvdev_add_device() but in this case it doesn't provide much. Moreover it
is removed and rproc_vdev_release() renamed in patch 4, making that one more
complex than it should be. As such please leave rproc_vdev_release() unchanged.
> > +}
> > +
> > /**
> > * rproc_handle_trace() - handle a shared trace buffer resource
> > * @rproc: the remote processor
> > diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> > index 72d4d3d7d94d..99f2ff88079f 100644
> > --- a/drivers/remoteproc/remoteproc_internal.h
> > +++ b/drivers/remoteproc/remoteproc_internal.h
> > @@ -24,6 +24,21 @@ struct rproc_debug_trace {
> > struct rproc_mem_entry trace_mem;
> > };
> >
> > +/**
> > + * struct rproc_vdev_data - remoteproc virtio device data
> > + * @rsc_offset: offset of the vdev's resource entry
> > + * @id: virtio device id (as in virtio_ids.h)
> > + * @index: vdev position versus other vdev declared in resource table
> > + * @rsc: pointer to the vdev resource entry. Valid onlyduring vdev init as the resource can
> > + * be cached by rproc.
> > + */
> > +struct rproc_vdev_data {
> > + u32 rsc_offset;
> > + unsigned int id;
> > + unsigned int index;
>
> rvdev->index is a u32 so rproc_vdev_data::index should also be a u32.
>
> With the above:
>
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
I'll take that back to see how the above refactoring fans out.
I am done reviewing this set.
Thanks,
Mathieu
>
>
> > + struct fw_rsc_vdev *rsc;
> > +};
> > +
> > /* from remoteproc_core.c */
> > void rproc_release(struct kref *kref);
> > irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
> > --
> > 2.25.1
> >
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions
2022-06-02 17:51 ` Mathieu Poirier
@ 2022-06-02 17:52 ` Mathieu Poirier
0 siblings, 0 replies; 16+ messages in thread
From: Mathieu Poirier @ 2022-06-02 17:52 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Thu, Jun 02, 2022 at 11:51:52AM -0600, Mathieu Poirier wrote:
> On Wed, Jun 01, 2022 at 11:29:45AM -0600, Mathieu Poirier wrote:
> > On Wed, Apr 06, 2022 at 11:54:43AM +0200, Arnaud Pouliquen wrote:
> > > In preparation of the migration of the management of rvdev in
> > > remoteproc_virtio.c, this patch spins off new functions to manage the
> > > remoteproc virtio device.
> > > - rproc_rvdev_add_device
> > > - rproc_rvdev_remove_device
> > >
> > > The rproc_rvdev_add_device and rproc_rvdev_remove_device will be
> > > moved to remoteproc_virtio.c.
> > >
> > > The rproc_vdev_data structure is introduced to provide information for
> > > the rvdev creation. This structure allows to manage the rvdev and vrings
> > > allocation in the rproc_rvdev_add_device function.
> > >
> > > Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> > > ---
> > > drivers/remoteproc/remoteproc_core.c | 157 +++++++++++++----------
> > > drivers/remoteproc/remoteproc_internal.h | 15 +++
> > > 2 files changed, 106 insertions(+), 66 deletions(-)
> > >
> > > diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> > > index c510125769b9..3a469220ac73 100644
> > > --- a/drivers/remoteproc/remoteproc_core.c
> > > +++ b/drivers/remoteproc/remoteproc_core.c
> > > @@ -484,74 +484,23 @@ static int copy_dma_range_map(struct device *to, struct device *from)
> > > return 0;
> > > }
> > >
> > > -/**
> > > - * rproc_handle_vdev() - handle a vdev fw resource
> > > - * @rproc: the remote processor
> > > - * @ptr: the vring resource descriptor
> > > - * @offset: offset of the resource entry
> > > - * @avail: size of available data (for sanity checking the image)
> > > - *
> > > - * This resource entry requests the host to statically register a virtio
> > > - * device (vdev), and setup everything needed to support it. It contains
> > > - * everything needed to make it possible: the virtio device id, virtio
> > > - * device features, vrings information, virtio config space, etc...
> > > - *
> > > - * Before registering the vdev, the vrings are allocated from non-cacheable
> > > - * physically contiguous memory. Currently we only support two vrings per
> > > - * remote processor (temporary limitation). We might also want to consider
> > > - * doing the vring allocation only later when ->find_vqs() is invoked, and
> > > - * then release them upon ->del_vqs().
> > > - *
> > > - * Note: @da is currently not really handled correctly: we dynamically
> > > - * allocate it using the DMA API, ignoring requested hard coded addresses,
> > > - * and we don't take care of any required IOMMU programming. This is all
> > > - * going to be taken care of when the generic iommu-based DMA API will be
> > > - * merged. Meanwhile, statically-addressed iommu-based firmware images should
> > > - * use RSC_DEVMEM resource entries to map their required @da to the physical
> > > - * address of their base CMA region (ouch, hacky!).
> > > - *
> > > - * Return: 0 on success, or an appropriate error code otherwise
> > > - */
> > > -static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > > - int offset, int avail)
> > > +static struct rproc_vdev *
> > > +rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> > > {
> > > - struct fw_rsc_vdev *rsc = ptr;
> > > - struct device *dev = &rproc->dev;
> > > struct rproc_vdev *rvdev;
> > > - int i, ret;
> > > + struct fw_rsc_vdev *rsc = rvdev_data->rsc;
> > > char name[16];
> > > -
> > > - /* make sure resource isn't truncated */
> > > - if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
> > > - avail) {
> > > - dev_err(dev, "vdev rsc is truncated\n");
> > > - return -EINVAL;
> > > - }
> > > -
> > > - /* make sure reserved bytes are zeroes */
> > > - if (rsc->reserved[0] || rsc->reserved[1]) {
> > > - dev_err(dev, "vdev rsc has non zero reserved bytes\n");
> > > - return -EINVAL;
> > > - }
> > > -
> > > - 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;
> > > - }
> > > + int i, ret;
> > >
> > > rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
> > > if (!rvdev)
> > > - return -ENOMEM;
> > > + return ERR_PTR(-ENOMEM);
> > >
> > > kref_init(&rvdev->refcount);
> > >
> > > - rvdev->id = rsc->id;
> > > + rvdev->id = rvdev_data->id;
> > > rvdev->rproc = rproc;
> > > - rvdev->index = rproc->nb_vdev++;
> > > + rvdev->index = rvdev_data->index;
> > >
> > > /* Initialise vdev subdevice */
> > > snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> > > @@ -563,7 +512,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > > ret = device_register(&rvdev->dev);
> > > if (ret) {
> > > put_device(&rvdev->dev);
> > > - return ret;
> > > + return ERR_PTR(ret);
> > > }
> > >
> > > ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> > > @@ -576,7 +525,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > > ret = dma_coerce_mask_and_coherent(&rvdev->dev,
> > > dma_get_mask(rproc->dev.parent));
> > > if (ret) {
> > > - dev_warn(dev,
> > > + dev_warn(&rvdev->dev,
> > > "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> > > dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
> > > }
> > > @@ -589,7 +538,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > > }
> > >
> > > /* remember the resource offset*/
> > > - rvdev->rsc_offset = offset;
> > > + rvdev->rsc_offset = rvdev_data->rsc_offset;
> > >
> > > /* allocate the vring resources */
> > > for (i = 0; i < rsc->num_of_vrings; i++) {
> > > @@ -605,21 +554,20 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > >
> > > rproc_add_subdev(rproc, &rvdev->subdev);
> > >
> > > - return 0;
> > > + return rvdev;
> > >
> > > unwind_vring_allocations:
> > > for (i--; i >= 0; i--)
> > > rproc_free_vring(&rvdev->vring[i]);
> > > free_rvdev:
> > > device_unregister(&rvdev->dev);
> > > - return ret;
> > > + return ERR_PTR(ret);
> > > }
> > >
> > > -void rproc_vdev_release(struct kref *ref)
> > > +static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> > > {
> > > - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> > > - struct rproc_vring *rvring;
> > > struct rproc *rproc = rvdev->rproc;
> > > + struct rproc_vring *rvring;
> > > int id;
> > >
> > > for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> > > @@ -632,6 +580,83 @@ void rproc_vdev_release(struct kref *ref)
> > > device_unregister(&rvdev->dev);
> > > }
> > >
> > > +/**
> > > + * rproc_handle_vdev() - handle a vdev fw resource
> > > + * @rproc: the remote processor
> > > + * @ptr: the vring resource descriptor
> > > + * @offset: offset of the resource entry
> > > + * @avail: size of available data (for sanity checking the image)
> > > + *
> > > + * This resource entry requests the host to statically register a virtio
> > > + * device (vdev), and setup everything needed to support it. It contains
> > > + * everything needed to make it possible: the virtio device id, virtio
> > > + * device features, vrings information, virtio config space, etc...
> > > + *
> > > + * Before registering the vdev, the vrings are allocated from non-cacheable
> > > + * physically contiguous memory. Currently we only support two vrings per
> > > + * remote processor (temporary limitation). We might also want to consider
> > > + * doing the vring allocation only later when ->find_vqs() is invoked, and
> > > + * then release them upon ->del_vqs().
> > > + *
> > > + * Note: @da is currently not really handled correctly: we dynamically
> > > + * allocate it using the DMA API, ignoring requested hard coded addresses,
> > > + * and we don't take care of any required IOMMU programming. This is all
> > > + * going to be taken care of when the generic iommu-based DMA API will be
> > > + * merged. Meanwhile, statically-addressed iommu-based firmware images should
> > > + * use RSC_DEVMEM resource entries to map their required @da to the physical
> > > + * address of their base CMA region (ouch, hacky!).
> > > + *
> > > + * Return: 0 on success, or an appropriate error code otherwise
> > > + */
> > > +static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > > + int offset, int avail)
> > > +{
> > > + struct fw_rsc_vdev *rsc = ptr;
> > > + struct device *dev = &rproc->dev;
> > > + struct rproc_vdev *rvdev;
> > > + struct rproc_vdev_data rvdev_data;
> > > +
> > > + /* make sure resource isn't truncated */
> > > + if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len >
> > > + avail) {
> > > + dev_err(dev, "vdev rsc is truncated\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + /* make sure reserved bytes are zeroes */
> > > + if (rsc->reserved[0] || rsc->reserved[1]) {
> > > + dev_err(dev, "vdev rsc has non zero reserved bytes\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + 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;
> > > + rvdev_data.rsc = rsc;
> > > +
> > > + rvdev = rproc_rvdev_add_device(rproc, &rvdev_data);
> > > + if (IS_ERR(rvdev))
> > > + return PTR_ERR(rvdev);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +void rproc_vdev_release(struct kref *ref)
> > > +{
> > > + struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> > > +
> > > + rproc_rvdev_remove_device(rvdev);
>
> I understand that rproc_rvdev_remove_device() is created to counter balance
> rproc_rvdev_add_device() but in this case it doesn't provide much. Moreover it
> is removed and rproc_vdev_release() renamed in patch 4, making that one more
> complex than it should be. As such please leave rproc_vdev_release() unchanged.
>
> > > +}
> > > +
> > > /**
> > > * rproc_handle_trace() - handle a shared trace buffer resource
> > > * @rproc: the remote processor
> > > diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> > > index 72d4d3d7d94d..99f2ff88079f 100644
> > > --- a/drivers/remoteproc/remoteproc_internal.h
> > > +++ b/drivers/remoteproc/remoteproc_internal.h
> > > @@ -24,6 +24,21 @@ struct rproc_debug_trace {
> > > struct rproc_mem_entry trace_mem;
> > > };
> > >
> > > +/**
> > > + * struct rproc_vdev_data - remoteproc virtio device data
> > > + * @rsc_offset: offset of the vdev's resource entry
> > > + * @id: virtio device id (as in virtio_ids.h)
> > > + * @index: vdev position versus other vdev declared in resource table
> > > + * @rsc: pointer to the vdev resource entry. Valid onlyduring vdev init as the resource can
> > > + * be cached by rproc.
> > > + */
> > > +struct rproc_vdev_data {
> > > + u32 rsc_offset;
> > > + unsigned int id;
> > > + unsigned int index;
> >
> > rvdev->index is a u32 so rproc_vdev_data::index should also be a u32.
> >
> > With the above:
> >
> > Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
> I'll take that back to see how the above refactoring fans out.
>
> I am done reviewing this set.
You can drop the "RFC" for the next revision, we are well past that point.
>
> Thanks,
> Mathieu
>
> >
> >
> > > + struct fw_rsc_vdev *rsc;
> > > +};
> > > +
> > > /* from remoteproc_core.c */
> > > void rproc_release(struct kref *kref);
> > > irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
> > > --
> > > 2.25.1
> > >
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function
2022-06-01 17:41 ` Mathieu Poirier
@ 2022-06-03 11:53 ` Arnaud POULIQUEN
2022-06-06 15:47 ` Mathieu Poirier
2022-06-06 16:20 ` Mathieu Poirier
0 siblings, 2 replies; 16+ messages in thread
From: Arnaud POULIQUEN @ 2022-06-03 11:53 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
Hello Mathieu,
On 6/1/22 19:41, Mathieu Poirier wrote:
> On Wed, Apr 06, 2022 at 11:54:44AM +0200, Arnaud Pouliquen wrote:
>> The rproc structure contains a list of registered rproc_vdev structure.
>
> This should be rproc_rvdev.
Thanks for your review!
I will send a new version according to your comments except
this one.
The structure name rproc_vdev is the good one, or
or maybe I'm missing something?
Thanks,
Arnaud
>
>> To be able to move the management of the rproc_vdev structure in
>> remoteproc_virtio.c (i.e rproc_rvdev_add_device and
>> rproc_rvdev_remove_device functions), introduce the rproc_register_rvdev
>> and rproc_unregister_rvdev functions.
>
> The name of those functions doesn't match the content of the patch.
>
>>
>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>> ---
>> drivers/remoteproc/remoteproc_core.c | 16 ++++++++++++++--
>> 1 file changed, 14 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
>> index 3a469220ac73..081bea39daf4 100644
>> --- a/drivers/remoteproc/remoteproc_core.c
>> +++ b/drivers/remoteproc/remoteproc_core.c
>> @@ -484,6 +484,18 @@ static int copy_dma_range_map(struct device *to, struct device *from)
>> return 0;
>> }
>>
>> +static void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
>> +{
>> + if (rvdev && rproc)
>> + list_add_tail(&rvdev->node, &rproc->rvdevs);
>> +}
>> +
>> +static void rproc_remove_rvdev(struct rproc_vdev *rvdev)
>> +{
>> + if (rvdev)
>> + list_del(&rvdev->node);
>> +}
>> +
>> static struct rproc_vdev *
>> rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
>> {
>> @@ -547,7 +559,7 @@ rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
>> goto unwind_vring_allocations;
>> }
>>
>> - list_add_tail(&rvdev->node, &rproc->rvdevs);
>> + rproc_add_rvdev(rproc, rvdev);
>>
>> rvdev->subdev.start = rproc_vdev_do_start;
>> rvdev->subdev.stop = rproc_vdev_do_stop;
>> @@ -576,7 +588,7 @@ static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
>> }
>>
>> rproc_remove_subdev(rproc, &rvdev->subdev);
>> - list_del(&rvdev->node);
>> + rproc_remove_rvdev(rvdev);
>
> With the above:
>
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
>> device_unregister(&rvdev->dev);
>> }
>>
>> --
>> 2.25.1
>>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function
2022-06-03 11:53 ` Arnaud POULIQUEN
@ 2022-06-06 15:47 ` Mathieu Poirier
2022-06-06 16:20 ` Mathieu Poirier
1 sibling, 0 replies; 16+ messages in thread
From: Mathieu Poirier @ 2022-06-06 15:47 UTC (permalink / raw)
To: Arnaud POULIQUEN
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Fri, 3 Jun 2022 at 05:54, Arnaud POULIQUEN
<arnaud.pouliquen@foss.st.com> wrote:
>
> Hello Mathieu,
>
> On 6/1/22 19:41, Mathieu Poirier wrote:
> > On Wed, Apr 06, 2022 at 11:54:44AM +0200, Arnaud Pouliquen wrote:
> >> The rproc structure contains a list of registered rproc_vdev structure.
> >
> > This should be rproc_rvdev.
>
> Thanks for your review!
>
> I will send a new version according to your comments except
> this one.
> The structure name rproc_vdev is the good one, or
> or maybe I'm missing something?
>
Structure rproc does not contain a list of rproc_vdev, it contains a
list of rproc_rvdev in rproc::rvdevs.
> Thanks,
> Arnaud
>
> >
> >> To be able to move the management of the rproc_vdev structure in
> >> remoteproc_virtio.c (i.e rproc_rvdev_add_device and
> >> rproc_rvdev_remove_device functions), introduce the rproc_register_rvdev
> >> and rproc_unregister_rvdev functions.
> >
> > The name of those functions doesn't match the content of the patch.
> >
> >>
> >> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> >> ---
> >> drivers/remoteproc/remoteproc_core.c | 16 ++++++++++++++--
> >> 1 file changed, 14 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> >> index 3a469220ac73..081bea39daf4 100644
> >> --- a/drivers/remoteproc/remoteproc_core.c
> >> +++ b/drivers/remoteproc/remoteproc_core.c
> >> @@ -484,6 +484,18 @@ static int copy_dma_range_map(struct device *to, struct device *from)
> >> return 0;
> >> }
> >>
> >> +static void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
> >> +{
> >> + if (rvdev && rproc)
> >> + list_add_tail(&rvdev->node, &rproc->rvdevs);
> >> +}
> >> +
> >> +static void rproc_remove_rvdev(struct rproc_vdev *rvdev)
> >> +{
> >> + if (rvdev)
> >> + list_del(&rvdev->node);
> >> +}
> >> +
> >> static struct rproc_vdev *
> >> rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> >> {
> >> @@ -547,7 +559,7 @@ rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> >> goto unwind_vring_allocations;
> >> }
> >>
> >> - list_add_tail(&rvdev->node, &rproc->rvdevs);
> >> + rproc_add_rvdev(rproc, rvdev);
> >>
> >> rvdev->subdev.start = rproc_vdev_do_start;
> >> rvdev->subdev.stop = rproc_vdev_do_stop;
> >> @@ -576,7 +588,7 @@ static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> >> }
> >>
> >> rproc_remove_subdev(rproc, &rvdev->subdev);
> >> - list_del(&rvdev->node);
> >> + rproc_remove_rvdev(rvdev);
> >
> > With the above:
> >
> > Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> >
> >> device_unregister(&rvdev->dev);
> >> }
> >>
> >> --
> >> 2.25.1
> >>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function
2022-06-03 11:53 ` Arnaud POULIQUEN
2022-06-06 15:47 ` Mathieu Poirier
@ 2022-06-06 16:20 ` Mathieu Poirier
1 sibling, 0 replies; 16+ messages in thread
From: Mathieu Poirier @ 2022-06-06 16:20 UTC (permalink / raw)
To: Arnaud POULIQUEN
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Fri, 3 Jun 2022 at 05:54, Arnaud POULIQUEN
<arnaud.pouliquen@foss.st.com> wrote:
>
> Hello Mathieu,
>
> On 6/1/22 19:41, Mathieu Poirier wrote:
> > On Wed, Apr 06, 2022 at 11:54:44AM +0200, Arnaud Pouliquen wrote:
> >> The rproc structure contains a list of registered rproc_vdev structure.
> >
> > This should be rproc_rvdev.
>
> Thanks for your review!
>
> I will send a new version according to your comments except
> this one.
> The structure name rproc_vdev is the good one, or
> or maybe I'm missing something?
>
You are correct - I had the name of the variable, i.e rvdev, found in
rproc_handle_vdev() in my head. You can forget this comment.
> Thanks,
> Arnaud
>
> >
> >> To be able to move the management of the rproc_vdev structure in
> >> remoteproc_virtio.c (i.e rproc_rvdev_add_device and
> >> rproc_rvdev_remove_device functions), introduce the rproc_register_rvdev
> >> and rproc_unregister_rvdev functions.
> >
> > The name of those functions doesn't match the content of the patch.
> >
> >>
> >> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> >> ---
> >> drivers/remoteproc/remoteproc_core.c | 16 ++++++++++++++--
> >> 1 file changed, 14 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> >> index 3a469220ac73..081bea39daf4 100644
> >> --- a/drivers/remoteproc/remoteproc_core.c
> >> +++ b/drivers/remoteproc/remoteproc_core.c
> >> @@ -484,6 +484,18 @@ static int copy_dma_range_map(struct device *to, struct device *from)
> >> return 0;
> >> }
> >>
> >> +static void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
> >> +{
> >> + if (rvdev && rproc)
> >> + list_add_tail(&rvdev->node, &rproc->rvdevs);
> >> +}
> >> +
> >> +static void rproc_remove_rvdev(struct rproc_vdev *rvdev)
> >> +{
> >> + if (rvdev)
> >> + list_del(&rvdev->node);
> >> +}
> >> +
> >> static struct rproc_vdev *
> >> rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> >> {
> >> @@ -547,7 +559,7 @@ rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> >> goto unwind_vring_allocations;
> >> }
> >>
> >> - list_add_tail(&rvdev->node, &rproc->rvdevs);
> >> + rproc_add_rvdev(rproc, rvdev);
> >>
> >> rvdev->subdev.start = rproc_vdev_do_start;
> >> rvdev->subdev.stop = rproc_vdev_do_stop;
> >> @@ -576,7 +588,7 @@ static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> >> }
> >>
> >> rproc_remove_subdev(rproc, &rvdev->subdev);
> >> - list_del(&rvdev->node);
> >> + rproc_remove_rvdev(rvdev);
> >
> > With the above:
> >
> > Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> >
> >> device_unregister(&rvdev->dev);
> >> }
> >>
> >> --
> >> 2.25.1
> >>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 3/4] remoteproc: Move rproc_vdev management to remoteproc_virtio.c
2022-04-06 9:54 ` [RFC PATCH v5 3/4] remoteproc: Move rproc_vdev management to remoteproc_virtio.c Arnaud Pouliquen
@ 2022-07-05 16:07 ` Mathieu Poirier
2022-07-05 16:26 ` Mathieu Poirier
0 siblings, 1 reply; 16+ messages in thread
From: Mathieu Poirier @ 2022-07-05 16:07 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Wed, Apr 06, 2022 at 11:54:45AM +0200, Arnaud Pouliquen wrote:
> Move functions related to the management of the rproc_vdev
> structure in the remoteproc_virtio.c.
> The aim is to decorrelate as possible the virtio management from
> the core part.
>
> Due to the strong correlation between the vrings and the resource table
> the rproc_alloc/parse/free_vring functions are kept in the remoteproc core.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>
> ---
> Update vs previous revision:
> - clean up bad rproc_free_vring call in rproc_vdev_release
Stale comment. What has changed in this revision is that
rproc_rvdev_remove_device() has been dropped.
> ---
> drivers/remoteproc/remoteproc_core.c | 162 +----------------------
> drivers/remoteproc/remoteproc_internal.h | 11 +-
> drivers/remoteproc/remoteproc_virtio.c | 159 +++++++++++++++++++++-
> 3 files changed, 167 insertions(+), 165 deletions(-)
>
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 081bea39daf4..bd6d3f2decc6 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -23,9 +23,7 @@
> #include <linux/panic_notifier.h>
> #include <linux/slab.h>
> #include <linux/mutex.h>
> -#include <linux/dma-map-ops.h>
> #include <linux/dma-mapping.h>
> -#include <linux/dma-direct.h> /* XXX: pokes into bus_dma_range */
> #include <linux/firmware.h>
> #include <linux/string.h>
> #include <linux/debugfs.h>
> @@ -383,7 +381,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
> return 0;
> }
>
> -static int
> +int
> rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
> {
> struct rproc *rproc = rvdev->rproc;
> @@ -434,164 +432,17 @@ void rproc_free_vring(struct rproc_vring *rvring)
> }
> }
>
> -static int rproc_vdev_do_start(struct rproc_subdev *subdev)
> -{
> - struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> -
> - return rproc_add_virtio_dev(rvdev, rvdev->id);
> -}
> -
> -static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
> -{
> - struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> - int ret;
> -
> - ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
> - if (ret)
> - dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
> -}
> -
> -/**
> - * rproc_rvdev_release() - release the existence of a rvdev
> - *
> - * @dev: the subdevice's dev
> - */
> -static void rproc_rvdev_release(struct device *dev)
> -{
> - struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
> -
> - of_reserved_mem_device_release(dev);
> -
> - kfree(rvdev);
> -}
> -
> -static int copy_dma_range_map(struct device *to, struct device *from)
> -{
> - const struct bus_dma_region *map = from->dma_range_map, *new_map, *r;
> - int num_ranges = 0;
> -
> - if (!map)
> - return 0;
> -
> - for (r = map; r->size; r++)
> - num_ranges++;
> -
> - new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)),
> - GFP_KERNEL);
> - if (!new_map)
> - return -ENOMEM;
> - to->dma_range_map = new_map;
> - return 0;
> -}
> -
> -static void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
> +void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
> {
> if (rvdev && rproc)
> list_add_tail(&rvdev->node, &rproc->rvdevs);
> }
>
> -static void rproc_remove_rvdev(struct rproc_vdev *rvdev)
> +void rproc_remove_rvdev(struct rproc_vdev *rvdev)
> {
> if (rvdev)
> list_del(&rvdev->node);
> }
> -
> -static struct rproc_vdev *
> -rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> -{
> - struct rproc_vdev *rvdev;
> - struct fw_rsc_vdev *rsc = rvdev_data->rsc;
> - char name[16];
> - int i, ret;
> -
> - rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
> - if (!rvdev)
> - return ERR_PTR(-ENOMEM);
> -
> - kref_init(&rvdev->refcount);
> -
> - rvdev->id = rvdev_data->id;
> - rvdev->rproc = rproc;
> - rvdev->index = rvdev_data->index;
> -
> - /* Initialise vdev subdevice */
> - snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> - rvdev->dev.parent = &rproc->dev;
> - rvdev->dev.release = rproc_rvdev_release;
> - dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
> - dev_set_drvdata(&rvdev->dev, rvdev);
> -
> - ret = device_register(&rvdev->dev);
> - if (ret) {
> - put_device(&rvdev->dev);
> - return ERR_PTR(ret);
> - }
> -
> - ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> - if (ret)
> - goto free_rvdev;
> -
> - /* Make device dma capable by inheriting from parent's capabilities */
> - set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
> -
> - ret = dma_coerce_mask_and_coherent(&rvdev->dev,
> - dma_get_mask(rproc->dev.parent));
> - if (ret) {
> - dev_warn(&rvdev->dev,
> - "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> - dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
> - }
> -
> - /* parse the vrings */
> - for (i = 0; i < rsc->num_of_vrings; i++) {
> - ret = rproc_parse_vring(rvdev, rsc, i);
> - if (ret)
> - goto free_rvdev;
> - }
> -
> - /* remember the resource offset*/
> - rvdev->rsc_offset = rvdev_data->rsc_offset;
> -
> - /* allocate the vring resources */
> - for (i = 0; i < rsc->num_of_vrings; i++) {
> - ret = rproc_alloc_vring(rvdev, i);
> - if (ret)
> - goto unwind_vring_allocations;
> - }
> -
> - rproc_add_rvdev(rproc, rvdev);
> -
> - rvdev->subdev.start = rproc_vdev_do_start;
> - rvdev->subdev.stop = rproc_vdev_do_stop;
> -
> - rproc_add_subdev(rproc, &rvdev->subdev);
> -
> - return rvdev;
> -
> -unwind_vring_allocations:
> - for (i--; i >= 0; i--)
> - rproc_free_vring(&rvdev->vring[i]);
> -free_rvdev:
> - device_unregister(&rvdev->dev);
> - return ERR_PTR(ret);
> -}
> -
> -static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> -{
> - struct rproc *rproc = rvdev->rproc;
> - struct rproc_vring *rvring;
> - int id;
> -
> - for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> - rvring = &rvdev->vring[id];
> - rproc_free_vring(rvring);
> - }
> -
> - rproc_remove_subdev(rproc, &rvdev->subdev);
> - rproc_remove_rvdev(rvdev);
> - device_unregister(&rvdev->dev);
> -}
> -
> /**
> * rproc_handle_vdev() - handle a vdev fw resource
> * @rproc: the remote processor
> @@ -662,13 +513,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> return 0;
> }
>
> -void rproc_vdev_release(struct kref *ref)
> -{
> - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> -
> - rproc_rvdev_remove_device(rvdev);
> -}
> -
> /**
> * rproc_handle_trace() - handle a shared trace buffer resource
> * @rproc: the remote processor
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index 99f2ff88079f..f82f9a5378ae 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -41,14 +41,14 @@ struct rproc_vdev_data {
>
> /* from remoteproc_core.c */
> void rproc_release(struct kref *kref);
> -irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
> -void rproc_vdev_release(struct kref *ref);
> int rproc_of_parse_firmware(struct device *dev, int index,
> const char **fw_name);
>
> /* from remoteproc_virtio.c */
> -int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
> -int rproc_remove_virtio_dev(struct device *dev, void *data);
> +struct rproc_vdev *rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data);
> +void rproc_rvdev_remove_device(struct rproc_vdev *rvdev);
Stale
> +irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
> +void rproc_vdev_release(struct kref *ref);
>
> /* from remoteproc_debugfs.c */
> void rproc_remove_trace_file(struct dentry *tfile);
> @@ -98,6 +98,7 @@ static inline void rproc_char_device_remove(struct rproc *rproc)
>
> void rproc_free_vring(struct rproc_vring *rvring);
> int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
> +int rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i);
>
> phys_addr_t rproc_va_to_pa(void *cpu_addr);
> int rproc_trigger_recovery(struct rproc *rproc);
> @@ -110,6 +111,8 @@ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
> const struct firmware *fw);
> struct rproc_mem_entry *
> rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...);
> +void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev);
> +void rproc_remove_rvdev(struct rproc_vdev *rvdev);
>
> static inline int rproc_prepare_device(struct rproc *rproc)
> {
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..e2e796ab2fd8 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -9,7 +9,9 @@
> * Brian Swetland <swetland@google.com>
> */
>
> +#include <linux/dma-direct.h>
> #include <linux/dma-map-ops.h>
> +#include <linux/dma-mapping.h>
> #include <linux/export.h>
> #include <linux/of_reserved_mem.h>
> #include <linux/remoteproc.h>
> @@ -23,6 +25,25 @@
>
> #include "remoteproc_internal.h"
>
> +static int copy_dma_range_map(struct device *to, struct device *from)
> +{
> + const struct bus_dma_region *map = from->dma_range_map, *new_map, *r;
> + int num_ranges = 0;
> +
> + if (!map)
> + return 0;
> +
> + for (r = map; r->size; r++)
> + num_ranges++;
> +
> + new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)),
> + GFP_KERNEL);
> + if (!new_map)
> + return -ENOMEM;
> + to->dma_range_map = new_map;
> + return 0;
> +}
> +
> static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
> {
> return container_of(vdev->dev.parent, struct rproc_vdev, dev);
> @@ -339,7 +360,7 @@ static void rproc_virtio_dev_release(struct device *dev)
> *
> * Return: 0 on success or an appropriate error value otherwise
> */
> -int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
> +static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
> {
> struct rproc *rproc = rvdev->rproc;
> struct device *dev = &rvdev->dev;
> @@ -447,10 +468,144 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
> *
> * Return: 0
> */
> -int rproc_remove_virtio_dev(struct device *dev, void *data)
> +static int rproc_remove_virtio_dev(struct device *dev, void *data)
> {
> struct virtio_device *vdev = dev_to_virtio(dev);
>
> unregister_virtio_device(vdev);
> return 0;
> }
> +
> +static int rproc_vdev_do_start(struct rproc_subdev *subdev)
> +{
> + struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> +
> + return rproc_add_virtio_dev(rvdev, rvdev->id);
> +}
> +
> +static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
> +{
> + struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> + int ret;
> +
> + ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
> + if (ret)
> + dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
> +}
> +
> +/**
> + * rproc_rvdev_release() - release the existence of a rvdev
> + *
> + * @dev: the subdevice's dev
> + */
> +static void rproc_rvdev_release(struct device *dev)
> +{
> + struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
> +
> + of_reserved_mem_device_release(dev);
> +
> + kfree(rvdev);
> +}
> +
> +struct rproc_vdev *
> +rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> +{
> + struct rproc_vdev *rvdev;
> + struct fw_rsc_vdev *rsc = rvdev_data->rsc;
> + char name[16];
> + int i, ret;
> +
> + rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
> + if (!rvdev)
> + return ERR_PTR(-ENOMEM);
> +
> + kref_init(&rvdev->refcount);
> +
> + rvdev->id = rvdev_data->id;
> + rvdev->rproc = rproc;
> + rvdev->index = rvdev_data->index;
> +
> + /* Initialise vdev subdevice */
> + snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> + rvdev->dev.parent = &rproc->dev;
> + rvdev->dev.release = rproc_rvdev_release;
> + dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
> + dev_set_drvdata(&rvdev->dev, rvdev);
> +
> + ret = device_register(&rvdev->dev);
> + if (ret) {
> + put_device(&rvdev->dev);
> + return ERR_PTR(ret);
> + }
> +
> + ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> + if (ret)
> + goto free_rvdev;
> +
> + /* Make device dma capable by inheriting from parent's capabilities */
> + set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
> +
> + ret = dma_coerce_mask_and_coherent(&rvdev->dev,
> + dma_get_mask(rproc->dev.parent));
> + if (ret) {
> + dev_warn(&rvdev->dev,
> + "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> + dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
> + }
> +
> + /* parse the vrings */
> + for (i = 0; i < rsc->num_of_vrings; i++) {
> + ret = rproc_parse_vring(rvdev, rsc, i);
> + if (ret)
> + goto free_rvdev;
> + }
> +
> + /* remember the resource offset*/
> + rvdev->rsc_offset = rvdev_data->rsc_offset;
> +
> + /* allocate the vring resources */
> + for (i = 0; i < rsc->num_of_vrings; i++) {
> + ret = rproc_alloc_vring(rvdev, i);
> + if (ret)
> + goto unwind_vring_allocations;
> + }
> +
> + rproc_add_rvdev(rproc, rvdev);
> +
> + rvdev->subdev.start = rproc_vdev_do_start;
> + rvdev->subdev.stop = rproc_vdev_do_stop;
> +
> + rproc_add_subdev(rproc, &rvdev->subdev);
> +
> + return rvdev;
> +
> +unwind_vring_allocations:
> + for (i--; i >= 0; i--)
> + rproc_free_vring(&rvdev->vring[i]);
> +free_rvdev:
> + device_unregister(&rvdev->dev);
> + return ERR_PTR(ret);
> +}
> +
> +void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> +{
> + struct rproc *rproc = rvdev->rproc;
> + struct rproc_vring *rvring;
> + int id;
> +
> + for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> + rvring = &rvdev->vring[id];
> + rproc_free_vring(rvring);
> + }
> +
> + rproc_remove_subdev(rproc, &rvdev->subdev);
> + rproc_remove_rvdev(rvdev);
> + device_unregister(&rvdev->dev);
> +}
> +
> +void rproc_vdev_release(struct kref *ref)
> +{
> + struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> +
> + rproc_rvdev_remove_device(rvdev);
> +}
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH v5 3/4] remoteproc: Move rproc_vdev management to remoteproc_virtio.c
2022-07-05 16:07 ` Mathieu Poirier
@ 2022-07-05 16:26 ` Mathieu Poirier
0 siblings, 0 replies; 16+ messages in thread
From: Mathieu Poirier @ 2022-07-05 16:26 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
Rob Herring, Christoph Hellwig, Stefano Stabellini,
Bruce Ashfield
On Tue, Jul 05, 2022 at 10:07:22AM -0600, Mathieu Poirier wrote:
> On Wed, Apr 06, 2022 at 11:54:45AM +0200, Arnaud Pouliquen wrote:
> > Move functions related to the management of the rproc_vdev
> > structure in the remoteproc_virtio.c.
> > The aim is to decorrelate as possible the virtio management from
> > the core part.
> >
> > Due to the strong correlation between the vrings and the resource table
> > the rproc_alloc/parse/free_vring functions are kept in the remoteproc core.
> >
> > Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> >
> > ---
> > Update vs previous revision:
> > - clean up bad rproc_free_vring call in rproc_vdev_release
>
> Stale comment. What has changed in this revision is that
> rproc_rvdev_remove_device() has been dropped.
Void the comments for this patch. I was looking at this earlier revision to
compare with the current v6. Please find my comments there.
>
> > ---
> > drivers/remoteproc/remoteproc_core.c | 162 +----------------------
> > drivers/remoteproc/remoteproc_internal.h | 11 +-
> > drivers/remoteproc/remoteproc_virtio.c | 159 +++++++++++++++++++++-
> > 3 files changed, 167 insertions(+), 165 deletions(-)
> >
> > diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> > index 081bea39daf4..bd6d3f2decc6 100644
> > --- a/drivers/remoteproc/remoteproc_core.c
> > +++ b/drivers/remoteproc/remoteproc_core.c
> > @@ -23,9 +23,7 @@
> > #include <linux/panic_notifier.h>
> > #include <linux/slab.h>
> > #include <linux/mutex.h>
> > -#include <linux/dma-map-ops.h>
> > #include <linux/dma-mapping.h>
> > -#include <linux/dma-direct.h> /* XXX: pokes into bus_dma_range */
> > #include <linux/firmware.h>
> > #include <linux/string.h>
> > #include <linux/debugfs.h>
> > @@ -383,7 +381,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
> > return 0;
> > }
> >
> > -static int
> > +int
> > rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
> > {
> > struct rproc *rproc = rvdev->rproc;
> > @@ -434,164 +432,17 @@ void rproc_free_vring(struct rproc_vring *rvring)
> > }
> > }
> >
> > -static int rproc_vdev_do_start(struct rproc_subdev *subdev)
> > -{
> > - struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> > -
> > - return rproc_add_virtio_dev(rvdev, rvdev->id);
> > -}
> > -
> > -static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
> > -{
> > - struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> > - int ret;
> > -
> > - ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
> > - if (ret)
> > - dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
> > -}
> > -
> > -/**
> > - * rproc_rvdev_release() - release the existence of a rvdev
> > - *
> > - * @dev: the subdevice's dev
> > - */
> > -static void rproc_rvdev_release(struct device *dev)
> > -{
> > - struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
> > -
> > - of_reserved_mem_device_release(dev);
> > -
> > - kfree(rvdev);
> > -}
> > -
> > -static int copy_dma_range_map(struct device *to, struct device *from)
> > -{
> > - const struct bus_dma_region *map = from->dma_range_map, *new_map, *r;
> > - int num_ranges = 0;
> > -
> > - if (!map)
> > - return 0;
> > -
> > - for (r = map; r->size; r++)
> > - num_ranges++;
> > -
> > - new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)),
> > - GFP_KERNEL);
> > - if (!new_map)
> > - return -ENOMEM;
> > - to->dma_range_map = new_map;
> > - return 0;
> > -}
> > -
> > -static void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
> > +void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev)
> > {
> > if (rvdev && rproc)
> > list_add_tail(&rvdev->node, &rproc->rvdevs);
> > }
> >
> > -static void rproc_remove_rvdev(struct rproc_vdev *rvdev)
> > +void rproc_remove_rvdev(struct rproc_vdev *rvdev)
> > {
> > if (rvdev)
> > list_del(&rvdev->node);
> > }
> > -
> > -static struct rproc_vdev *
> > -rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> > -{
> > - struct rproc_vdev *rvdev;
> > - struct fw_rsc_vdev *rsc = rvdev_data->rsc;
> > - char name[16];
> > - int i, ret;
> > -
> > - rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
> > - if (!rvdev)
> > - return ERR_PTR(-ENOMEM);
> > -
> > - kref_init(&rvdev->refcount);
> > -
> > - rvdev->id = rvdev_data->id;
> > - rvdev->rproc = rproc;
> > - rvdev->index = rvdev_data->index;
> > -
> > - /* Initialise vdev subdevice */
> > - snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> > - rvdev->dev.parent = &rproc->dev;
> > - rvdev->dev.release = rproc_rvdev_release;
> > - dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
> > - dev_set_drvdata(&rvdev->dev, rvdev);
> > -
> > - ret = device_register(&rvdev->dev);
> > - if (ret) {
> > - put_device(&rvdev->dev);
> > - return ERR_PTR(ret);
> > - }
> > -
> > - ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> > - if (ret)
> > - goto free_rvdev;
> > -
> > - /* Make device dma capable by inheriting from parent's capabilities */
> > - set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
> > -
> > - ret = dma_coerce_mask_and_coherent(&rvdev->dev,
> > - dma_get_mask(rproc->dev.parent));
> > - if (ret) {
> > - dev_warn(&rvdev->dev,
> > - "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> > - dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
> > - }
> > -
> > - /* parse the vrings */
> > - for (i = 0; i < rsc->num_of_vrings; i++) {
> > - ret = rproc_parse_vring(rvdev, rsc, i);
> > - if (ret)
> > - goto free_rvdev;
> > - }
> > -
> > - /* remember the resource offset*/
> > - rvdev->rsc_offset = rvdev_data->rsc_offset;
> > -
> > - /* allocate the vring resources */
> > - for (i = 0; i < rsc->num_of_vrings; i++) {
> > - ret = rproc_alloc_vring(rvdev, i);
> > - if (ret)
> > - goto unwind_vring_allocations;
> > - }
> > -
> > - rproc_add_rvdev(rproc, rvdev);
> > -
> > - rvdev->subdev.start = rproc_vdev_do_start;
> > - rvdev->subdev.stop = rproc_vdev_do_stop;
> > -
> > - rproc_add_subdev(rproc, &rvdev->subdev);
> > -
> > - return rvdev;
> > -
> > -unwind_vring_allocations:
> > - for (i--; i >= 0; i--)
> > - rproc_free_vring(&rvdev->vring[i]);
> > -free_rvdev:
> > - device_unregister(&rvdev->dev);
> > - return ERR_PTR(ret);
> > -}
> > -
> > -static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> > -{
> > - struct rproc *rproc = rvdev->rproc;
> > - struct rproc_vring *rvring;
> > - int id;
> > -
> > - for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> > - rvring = &rvdev->vring[id];
> > - rproc_free_vring(rvring);
> > - }
> > -
> > - rproc_remove_subdev(rproc, &rvdev->subdev);
> > - rproc_remove_rvdev(rvdev);
> > - device_unregister(&rvdev->dev);
> > -}
> > -
> > /**
> > * rproc_handle_vdev() - handle a vdev fw resource
> > * @rproc: the remote processor
> > @@ -662,13 +513,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> > return 0;
> > }
> >
> > -void rproc_vdev_release(struct kref *ref)
> > -{
> > - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> > -
> > - rproc_rvdev_remove_device(rvdev);
> > -}
> > -
> > /**
> > * rproc_handle_trace() - handle a shared trace buffer resource
> > * @rproc: the remote processor
> > diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> > index 99f2ff88079f..f82f9a5378ae 100644
> > --- a/drivers/remoteproc/remoteproc_internal.h
> > +++ b/drivers/remoteproc/remoteproc_internal.h
> > @@ -41,14 +41,14 @@ struct rproc_vdev_data {
> >
> > /* from remoteproc_core.c */
> > void rproc_release(struct kref *kref);
> > -irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
> > -void rproc_vdev_release(struct kref *ref);
> > int rproc_of_parse_firmware(struct device *dev, int index,
> > const char **fw_name);
> >
> > /* from remoteproc_virtio.c */
> > -int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
> > -int rproc_remove_virtio_dev(struct device *dev, void *data);
> > +struct rproc_vdev *rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data);
> > +void rproc_rvdev_remove_device(struct rproc_vdev *rvdev);
>
> Stale
>
> > +irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
> > +void rproc_vdev_release(struct kref *ref);
> >
> > /* from remoteproc_debugfs.c */
> > void rproc_remove_trace_file(struct dentry *tfile);
> > @@ -98,6 +98,7 @@ static inline void rproc_char_device_remove(struct rproc *rproc)
> >
> > void rproc_free_vring(struct rproc_vring *rvring);
> > int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
> > +int rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i);
> >
> > phys_addr_t rproc_va_to_pa(void *cpu_addr);
> > int rproc_trigger_recovery(struct rproc *rproc);
> > @@ -110,6 +111,8 @@ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
> > const struct firmware *fw);
> > struct rproc_mem_entry *
> > rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...);
> > +void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev);
> > +void rproc_remove_rvdev(struct rproc_vdev *rvdev);
> >
> > static inline int rproc_prepare_device(struct rproc *rproc)
> > {
> > diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> > index 70ab496d0431..e2e796ab2fd8 100644
> > --- a/drivers/remoteproc/remoteproc_virtio.c
> > +++ b/drivers/remoteproc/remoteproc_virtio.c
> > @@ -9,7 +9,9 @@
> > * Brian Swetland <swetland@google.com>
> > */
> >
> > +#include <linux/dma-direct.h>
> > #include <linux/dma-map-ops.h>
> > +#include <linux/dma-mapping.h>
> > #include <linux/export.h>
> > #include <linux/of_reserved_mem.h>
> > #include <linux/remoteproc.h>
> > @@ -23,6 +25,25 @@
> >
> > #include "remoteproc_internal.h"
> >
> > +static int copy_dma_range_map(struct device *to, struct device *from)
> > +{
> > + const struct bus_dma_region *map = from->dma_range_map, *new_map, *r;
> > + int num_ranges = 0;
> > +
> > + if (!map)
> > + return 0;
> > +
> > + for (r = map; r->size; r++)
> > + num_ranges++;
> > +
> > + new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)),
> > + GFP_KERNEL);
> > + if (!new_map)
> > + return -ENOMEM;
> > + to->dma_range_map = new_map;
> > + return 0;
> > +}
> > +
> > static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
> > {
> > return container_of(vdev->dev.parent, struct rproc_vdev, dev);
> > @@ -339,7 +360,7 @@ static void rproc_virtio_dev_release(struct device *dev)
> > *
> > * Return: 0 on success or an appropriate error value otherwise
> > */
> > -int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
> > +static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
> > {
> > struct rproc *rproc = rvdev->rproc;
> > struct device *dev = &rvdev->dev;
> > @@ -447,10 +468,144 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
> > *
> > * Return: 0
> > */
> > -int rproc_remove_virtio_dev(struct device *dev, void *data)
> > +static int rproc_remove_virtio_dev(struct device *dev, void *data)
> > {
> > struct virtio_device *vdev = dev_to_virtio(dev);
> >
> > unregister_virtio_device(vdev);
> > return 0;
> > }
> > +
> > +static int rproc_vdev_do_start(struct rproc_subdev *subdev)
> > +{
> > + struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> > +
> > + return rproc_add_virtio_dev(rvdev, rvdev->id);
> > +}
> > +
> > +static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
> > +{
> > + struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
> > + int ret;
> > +
> > + ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
> > + if (ret)
> > + dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
> > +}
> > +
> > +/**
> > + * rproc_rvdev_release() - release the existence of a rvdev
> > + *
> > + * @dev: the subdevice's dev
> > + */
> > +static void rproc_rvdev_release(struct device *dev)
> > +{
> > + struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
> > +
> > + of_reserved_mem_device_release(dev);
> > +
> > + kfree(rvdev);
> > +}
> > +
> > +struct rproc_vdev *
> > +rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data)
> > +{
> > + struct rproc_vdev *rvdev;
> > + struct fw_rsc_vdev *rsc = rvdev_data->rsc;
> > + char name[16];
> > + int i, ret;
> > +
> > + rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL);
> > + if (!rvdev)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + kref_init(&rvdev->refcount);
> > +
> > + rvdev->id = rvdev_data->id;
> > + rvdev->rproc = rproc;
> > + rvdev->index = rvdev_data->index;
> > +
> > + /* Initialise vdev subdevice */
> > + snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> > + rvdev->dev.parent = &rproc->dev;
> > + rvdev->dev.release = rproc_rvdev_release;
> > + dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
> > + dev_set_drvdata(&rvdev->dev, rvdev);
> > +
> > + ret = device_register(&rvdev->dev);
> > + if (ret) {
> > + put_device(&rvdev->dev);
> > + return ERR_PTR(ret);
> > + }
> > +
> > + ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> > + if (ret)
> > + goto free_rvdev;
> > +
> > + /* Make device dma capable by inheriting from parent's capabilities */
> > + set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
> > +
> > + ret = dma_coerce_mask_and_coherent(&rvdev->dev,
> > + dma_get_mask(rproc->dev.parent));
> > + if (ret) {
> > + dev_warn(&rvdev->dev,
> > + "Failed to set DMA mask %llx. Trying to continue... (%pe)\n",
> > + dma_get_mask(rproc->dev.parent), ERR_PTR(ret));
> > + }
> > +
> > + /* parse the vrings */
> > + for (i = 0; i < rsc->num_of_vrings; i++) {
> > + ret = rproc_parse_vring(rvdev, rsc, i);
> > + if (ret)
> > + goto free_rvdev;
> > + }
> > +
> > + /* remember the resource offset*/
> > + rvdev->rsc_offset = rvdev_data->rsc_offset;
> > +
> > + /* allocate the vring resources */
> > + for (i = 0; i < rsc->num_of_vrings; i++) {
> > + ret = rproc_alloc_vring(rvdev, i);
> > + if (ret)
> > + goto unwind_vring_allocations;
> > + }
> > +
> > + rproc_add_rvdev(rproc, rvdev);
> > +
> > + rvdev->subdev.start = rproc_vdev_do_start;
> > + rvdev->subdev.stop = rproc_vdev_do_stop;
> > +
> > + rproc_add_subdev(rproc, &rvdev->subdev);
> > +
> > + return rvdev;
> > +
> > +unwind_vring_allocations:
> > + for (i--; i >= 0; i--)
> > + rproc_free_vring(&rvdev->vring[i]);
> > +free_rvdev:
> > + device_unregister(&rvdev->dev);
> > + return ERR_PTR(ret);
> > +}
> > +
> > +void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> > +{
> > + struct rproc *rproc = rvdev->rproc;
> > + struct rproc_vring *rvring;
> > + int id;
> > +
> > + for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> > + rvring = &rvdev->vring[id];
> > + rproc_free_vring(rvring);
> > + }
> > +
> > + rproc_remove_subdev(rproc, &rvdev->subdev);
> > + rproc_remove_rvdev(rvdev);
> > + device_unregister(&rvdev->dev);
> > +}
> > +
> > +void rproc_vdev_release(struct kref *ref)
> > +{
> > + struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> > +
> > + rproc_rvdev_remove_device(rvdev);
> > +}
> > --
> > 2.25.1
> >
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2022-07-05 16:26 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-06 9:54 [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Arnaud Pouliquen
2022-04-06 9:54 ` [RFC PATCH v5 1/4] remoteproc: core: Introduce virtio device add/remove functions Arnaud Pouliquen
2022-06-01 17:29 ` Mathieu Poirier
2022-06-02 17:51 ` Mathieu Poirier
2022-06-02 17:52 ` Mathieu Poirier
2022-04-06 9:54 ` [RFC PATCH v5 2/4] remoteproc: core: Introduce rproc_register_rvdev function Arnaud Pouliquen
2022-06-01 17:41 ` Mathieu Poirier
2022-06-03 11:53 ` Arnaud POULIQUEN
2022-06-06 15:47 ` Mathieu Poirier
2022-06-06 16:20 ` Mathieu Poirier
2022-04-06 9:54 ` [RFC PATCH v5 3/4] remoteproc: Move rproc_vdev management to remoteproc_virtio.c Arnaud Pouliquen
2022-07-05 16:07 ` Mathieu Poirier
2022-07-05 16:26 ` Mathieu Poirier
2022-04-06 9:54 ` [RFC PATCH v5 4/4] remoteproc: virtio: Create platform device for the remoteproc_virtio Arnaud Pouliquen
2022-06-02 17:42 ` Mathieu Poirier
2022-05-31 17:49 ` [RFC PATCH v5 0/4] remoteproc: restructure the remoteproc VirtIO device Mathieu Poirier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).