2021-10-01 12:24:34

by Arnaud Pouliquen

[permalink] [raw]
Subject: [RFC PATCH 0/7] remoteproc: restructure the remoteproc VirtIO device

This series is a part of the work initiate a long time ago in
the series "remoteproc: Decorelate virtio from core"[1]


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 audio, video, ...)
- Keep the legacy working!
- Try to improve the picture about concerns reported by Christoph Hellwing [2][3]

[1] https://lkml.org/lkml/2020/4/16/1817
[2] https://lkml.org/lkml/2021/6/23/607
[3] https://patchwork.kernel.org/project/linux-remoteproc/patch/[email protected]/

In term of device tree this would result in such hiearchy (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 prob 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 (7):
remoteproc: core: Introduce virtio device add/remove functions
remoteproc: Move rvdev management in rproc_virtio
remoteproc: Remove vdev_to_rvdev and vdev_to_rproc from remoteproc API
remoteproc: create the REMOTEPROC_VIRTIO config
remoteproc: virtio: Create platform device for the remoteproc_virtio
remoteproc: virtio: Add helper to create platform device
remoteproc: Instantiate the new remoteproc virtio platform device

drivers/remoteproc/Kconfig | 11 +-
drivers/remoteproc/Makefile | 2 +-
drivers/remoteproc/remoteproc_core.c | 142 +++-------------
drivers/remoteproc/remoteproc_internal.h | 52 +++++-
drivers/remoteproc/remoteproc_virtio.c | 207 +++++++++++++++++++++--
include/linux/remoteproc.h | 18 +-
6 files changed, 282 insertions(+), 150 deletions(-)

--
2.17.1


2021-10-01 12:46:22

by Arnaud Pouliquen

[permalink] [raw]
Subject: [RFC PATCH 6/7] remoteproc: virtio: Add helper to create platform device

Add capability to create platform device for the rproc virtio.
This is a step to move forward the management of the rproc virtio
as an independent device.

Signed-off-by: Arnaud Pouliquen <[email protected]>
---
drivers/remoteproc/remoteproc_internal.h | 15 ++++++++++
drivers/remoteproc/remoteproc_virtio.c | 36 ++++++++++++++++++++++++
2 files changed, 51 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 1b963a8912ed..0bb1b14e5136 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -39,11 +39,26 @@ int rproc_of_parse_firmware(struct device *dev, int index,
#if IS_ENABLED(CONFIG_REMOTEPROC_VIRTIO)

int rproc_rvdev_add_device(struct rproc_vdev *rvdev);
+struct platform_device *
+rproc_virtio_register_device(struct rproc *rproc, struct rproc_vdev_data *vdev_data);
+void rproc_virtio_unregister_device(struct rproc_vdev *rvdev);
irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
void rproc_vdev_release(struct kref *ref);

#else

+static inline struct platform_device *
+rproc_virtio_register_device(struct rproc *rproc, struct rproc_vdev_data *vdev_data)
+{
+ return ERR_PTR(-ENXIO);
+}
+
+static inline void rproc_virtio_unregister_device(struct rproc_vdev *rvdev)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+}
+
int rproc_rvdev_add_device(struct rproc_vdev *rvdev)
{
/* This shouldn't be possible */
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 9b2ab79e4c4c..7188fb8ce40f 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -574,6 +574,42 @@ void rproc_vdev_release(struct kref *ref)
rproc_rvdev_remove_device(rvdev);
}

+/**
+ * rproc_virtio_register_device() - register a remoteproc virtio device
+ * @rproc: rproc handle to add the remoteproc virtio device to
+ * @vdev_data: platform device data
+ *
+ * Return: 0 on success, and an appropriate error value otherwise
+ */
+struct platform_device *
+rproc_virtio_register_device(struct rproc *rproc, struct rproc_vdev_data *vdev_data)
+{
+ struct device *dev = &rproc->dev;
+ struct platform_device *pdev;
+
+ pdev = platform_device_register_data(dev, "rproc-virtio", vdev_data->index, vdev_data,
+ sizeof(*vdev_data));
+ if (PTR_ERR_OR_ZERO(pdev)) {
+ dev_err(rproc->dev.parent,
+ "failed to create rproc-virtio device\n");
+ }
+
+ return pdev;
+}
+EXPORT_SYMBOL(rproc_virtio_register_device);
+
+/**
+ * rproc_virtio_unregister_device() - unregister a remoteproc virtio device
+ * @rvdev: remote proc virtio handle to unregister
+ *
+ */
+void rproc_virtio_unregister_device(struct rproc_vdev *rvdev)
+{
+ if (rvdev->pdev)
+ platform_device_unregister(rvdev->pdev);
+}
+EXPORT_SYMBOL(rproc_virtio_unregister_device);
+
static int rproc_virtio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
--
2.17.1

2021-10-01 12:46:27

by Arnaud Pouliquen

[permalink] [raw]
Subject: [RFC PATCH 2/7] remoteproc: Move rvdev management in rproc_virtio

Move functions related to the management of the rproc_vdev
structure in the remoteproc virtio.
The aim is to decorrelate as possible the virtio management form
the core part.

Due to the strong correlation between the vrings and the resource table
the vrings management is kept in the remoteproc core.

Signed-off-by: Arnaud Pouliquen <[email protected]>
---
drivers/remoteproc/remoteproc_core.c | 127 -----------------------
drivers/remoteproc/remoteproc_internal.h | 19 +++-
drivers/remoteproc/remoteproc_virtio.c | 121 ++++++++++++++++++++-
3 files changed, 134 insertions(+), 133 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 7c783ca291a7..67ccd088db8f 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -434,119 +434,6 @@ 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_register_rvdev(struct rproc_vdev *rvdev)
-{
- if (rvdev && rvdev->rproc)
- list_add_tail(&rvdev->node, &rvdev->rproc->rvdevs);
-}
-
-static void rproc_unregister_rvdev(struct rproc_vdev *rvdev)
-{
- if (rvdev)
- list_del(&rvdev->node);
-}
-
-static int rproc_rvdev_add_device(struct rproc_vdev *rvdev)
-{
- struct rproc *rproc = rvdev->rproc;
- char name[16];
- int ret;
-
- snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
- rvdev->dev.parent = &rproc->dev;
- ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
- if (ret)
- return ret;
-
- 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 ret;
- }
- /* 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... %x\n",
- dma_get_mask(rproc->dev.parent), ret);
- }
-
- rproc_register_rvdev(rvdev);
-
- rvdev->subdev.start = rproc_vdev_do_start;
- rvdev->subdev.stop = rproc_vdev_do_stop;
-
- rproc_add_subdev(rproc, &rvdev->subdev);
-
- return 0;
-}
-
-static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
-{
- struct rproc *rproc = rvdev->rproc;
-
- rproc_remove_subdev(rproc, &rvdev->subdev);
- rproc_unregister_rvdev(rvdev);
- device_unregister(&rvdev->dev);
-}
-
/**
* rproc_handle_vdev() - handle a vdev fw resource
* @rproc: the remote processor
@@ -648,20 +535,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
return ret;
}

-void rproc_vdev_release(struct kref *ref)
-{
- struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
- struct rproc_vring *rvring;
- int id;
-
- for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
- rvring = &rvdev->vring[id];
- rproc_free_vring(rvring);
- }
-
- 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 a328e634b1de..152fe2e8668a 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -26,14 +26,13 @@ struct rproc_debug_trace {

/* 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);
+int rproc_rvdev_add_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);
@@ -196,4 +195,16 @@ bool rproc_u64_fit_in_size_t(u64 val)
return (val <= (size_t) -1);
}

+static inline void rproc_register_rvdev(struct rproc_vdev *rvdev)
+{
+ if (rvdev && rvdev->rproc)
+ list_add_tail(&rvdev->node, &rvdev->rproc->rvdevs);
+}
+
+static inline void rproc_unregister_rvdev(struct rproc_vdev *rvdev)
+{
+ if (rvdev)
+ list_del(&rvdev->node);
+}
+
#endif /* REMOTEPROC_INTERNAL_H */
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index cf4d54e98e6a..5e5a78b3243f 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -9,7 +9,9 @@
* Brian Swetland <[email protected]>
*/

+#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;
+}
+
/* kick the remote processor, and let it know which virtqueue to poke at */
static bool rproc_virtio_notify(struct virtqueue *vq)
{
@@ -327,7 +348,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;
@@ -435,10 +456,106 @@ 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);
+}
+
+int rproc_rvdev_add_device(struct rproc_vdev *rvdev)
+{
+ struct rproc *rproc = rvdev->rproc;
+ char name[16];
+ int ret;
+
+ snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
+ rvdev->dev.parent = &rproc->dev;
+ ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
+ if (ret)
+ return ret;
+
+ 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 ret;
+ }
+ /* 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... %x\n",
+ dma_get_mask(rproc->dev.parent), ret);
+ }
+
+ rproc_register_rvdev(rvdev);
+
+ rvdev->subdev.start = rproc_vdev_do_start;
+ rvdev->subdev.stop = rproc_vdev_do_stop;
+
+ rproc_add_subdev(rproc, &rvdev->subdev);
+
+ return 0;
+}
+
+static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
+{
+ struct rproc *rproc = rvdev->rproc;
+
+ rproc_remove_subdev(rproc, &rvdev->subdev);
+ rproc_unregister_rvdev(rvdev);
+ device_unregister(&rvdev->dev);
+}
+
+void rproc_vdev_release(struct kref *ref)
+{
+ struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
+ struct rproc_vring *rvring;
+ int id;
+
+ for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
+ rvring = &rvdev->vring[id];
+ rproc_free_vring(rvring);
+ }
+
+ rproc_rvdev_remove_device(rvdev);
+}
--
2.17.1

2021-10-01 12:46:45

by Arnaud Pouliquen

[permalink] [raw]
Subject: [RFC PATCH 5/7] remoteproc: virtio: Create platform device for the remoteproc_virtio

Define a platform device for the remoteproc virtio to prepare the
management of the remoteproc virtio as a platform device.

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.

Signed-off-by: Arnaud Pouliquen <[email protected]>
---
drivers/remoteproc/remoteproc_internal.h | 6 +++
drivers/remoteproc/remoteproc_virtio.c | 65 ++++++++++++++++++++++++
include/linux/remoteproc.h | 2 +
3 files changed, 73 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 4ce012c353c0..1b963a8912ed 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -24,6 +24,12 @@ struct rproc_debug_trace {
struct rproc_mem_entry trace_mem;
};

+struct rproc_vdev_data {
+ u32 rsc_offset;
+ unsigned int id;
+ unsigned int index;
+};
+
/* from remoteproc_core.c */
void rproc_release(struct kref *kref);
int rproc_of_parse_firmware(struct device *dev, int index,
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index c9eecd2f9fb2..9b2ab79e4c4c 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2021 STMicroelectronics
*
* Ohad Ben-Cohen <[email protected]>
* Brian Swetland <[email protected]>
@@ -13,6 +14,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>
@@ -571,3 +573,66 @@ void rproc_vdev_release(struct kref *ref)

rproc_rvdev_remove_device(rvdev);
}
+
+static int rproc_virtio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rproc_vdev_data *vdev_data = dev->platform_data;
+ struct rproc_vdev *rvdev;
+ struct rproc *rproc;
+
+ if (!vdev_data)
+ return -EINVAL;
+
+ rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL);
+ if (!rvdev)
+ return -ENOMEM;
+
+ rproc = container_of(dev->parent, struct rproc, dev);
+
+ rvdev->rsc_offset = vdev_data->rsc_offset;
+ rvdev->id = vdev_data->id;
+ rvdev->index = vdev_data->index;
+
+ rvdev->pdev = pdev;
+ rvdev->rproc = rproc;
+
+ platform_set_drvdata(pdev, rvdev);
+
+ return rproc_rvdev_add_device(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;
+
+ for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
+ rvring = &rvdev->vring[id];
+ rproc_free_vring(rvring);
+ }
+
+ rproc_remove_subdev(rproc, &rvdev->subdev);
+ rproc_unregister_rvdev(rvdev);
+ dev_dbg(&pdev->dev, "virtio dev %d removed\n", rvdev->index);
+
+ return 0;
+}
+
+/* Platform driver */
+static const struct of_device_id rproc_virtio_match[] = {
+ { .compatible = "rproc-virtio", },
+ {},
+};
+
+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 e0600e1e5c17..542a3d4664f2 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -616,6 +616,7 @@ 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
+ * @pdev: remoteproc virtio platform device
* @dev: device struct used for reference count semantics
* @id: virtio device id (as in virtio_ids.h)
* @node: list node
@@ -628,6 +629,7 @@ struct rproc_vdev {
struct kref refcount;

struct rproc_subdev subdev;
+ struct platform_device *pdev;
struct device dev;

unsigned int id;
--
2.17.1

2021-10-22 17:30:51

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [RFC PATCH 2/7] remoteproc: Move rvdev management in rproc_virtio

More comments...

The title should probably be:

"remoteproc: Move rproc_vdev management to remoteproc_virtio.c"


On Fri, Oct 01, 2021 at 12:12:29PM +0200, Arnaud Pouliquen wrote:
> Move functions related to the management of the rproc_vdev
> structure in the remoteproc virtio.
> The aim is to decorrelate as possible the virtio management form

s/form/from

> the core part.
>
> Due to the strong correlation between the vrings and the resource table
> the vrings management is kept in the remoteproc core.
>
> Signed-off-by: Arnaud Pouliquen <[email protected]>
> ---
> drivers/remoteproc/remoteproc_core.c | 127 -----------------------
> drivers/remoteproc/remoteproc_internal.h | 19 +++-
> drivers/remoteproc/remoteproc_virtio.c | 121 ++++++++++++++++++++-
> 3 files changed, 134 insertions(+), 133 deletions(-)
>
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 7c783ca291a7..67ccd088db8f 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -434,119 +434,6 @@ 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_register_rvdev(struct rproc_vdev *rvdev)
> -{
> - if (rvdev && rvdev->rproc)
> - list_add_tail(&rvdev->node, &rvdev->rproc->rvdevs);
> -}
> -
> -static void rproc_unregister_rvdev(struct rproc_vdev *rvdev)
> -{
> - if (rvdev)
> - list_del(&rvdev->node);
> -}
> -
> -static int rproc_rvdev_add_device(struct rproc_vdev *rvdev)
> -{
> - struct rproc *rproc = rvdev->rproc;
> - char name[16];
> - int ret;
> -
> - snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> - rvdev->dev.parent = &rproc->dev;
> - ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> - if (ret)
> - return ret;
> -
> - 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 ret;
> - }
> - /* 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... %x\n",
> - dma_get_mask(rproc->dev.parent), ret);
> - }
> -
> - rproc_register_rvdev(rvdev);
> -
> - rvdev->subdev.start = rproc_vdev_do_start;
> - rvdev->subdev.stop = rproc_vdev_do_stop;
> -
> - rproc_add_subdev(rproc, &rvdev->subdev);
> -
> - return 0;
> -}
> -
> -static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> -{
> - struct rproc *rproc = rvdev->rproc;
> -
> - rproc_remove_subdev(rproc, &rvdev->subdev);
> - rproc_unregister_rvdev(rvdev);
> - device_unregister(&rvdev->dev);
> -}
> -
> /**
> * rproc_handle_vdev() - handle a vdev fw resource
> * @rproc: the remote processor
> @@ -648,20 +535,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
> return ret;
> }
>
> -void rproc_vdev_release(struct kref *ref)
> -{
> - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> - struct rproc_vring *rvring;
> - int id;
> -
> - for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> - rvring = &rvdev->vring[id];
> - rproc_free_vring(rvring);
> - }
> -
> - 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 a328e634b1de..152fe2e8668a 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -26,14 +26,13 @@ struct rproc_debug_trace {
>
> /* 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);
> +int rproc_rvdev_add_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);
> @@ -196,4 +195,16 @@ bool rproc_u64_fit_in_size_t(u64 val)
> return (val <= (size_t) -1);
> }
>
> +static inline void rproc_register_rvdev(struct rproc_vdev *rvdev)
> +{
> + if (rvdev && rvdev->rproc)
> + list_add_tail(&rvdev->node, &rvdev->rproc->rvdevs);
> +}
> +
> +static inline void rproc_unregister_rvdev(struct rproc_vdev *rvdev)
> +{
> + if (rvdev)
> + list_del(&rvdev->node);
> +}
> +
> #endif /* REMOTEPROC_INTERNAL_H */
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index cf4d54e98e6a..5e5a78b3243f 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -9,7 +9,9 @@
> * Brian Swetland <[email protected]>
> */
>
> +#include <linux/dma-direct.h>
> #include <linux/dma-map-ops.h>
> +#include <linux/dma-mapping.h>

Please see if either dma-direct.h and dma-mapping.h can be removed from
remoteproc_core.c

> #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;
> +}
> +
> /* kick the remote processor, and let it know which virtqueue to poke at */
> static bool rproc_virtio_notify(struct virtqueue *vq)
> {
> @@ -327,7 +348,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;
> @@ -435,10 +456,106 @@ 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);
> +}
> +
> +int rproc_rvdev_add_device(struct rproc_vdev *rvdev)
> +{
> + struct rproc *rproc = rvdev->rproc;
> + char name[16];
> + int ret;
> +
> + snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
> + rvdev->dev.parent = &rproc->dev;
> + ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent);
> + if (ret)
> + return ret;
> +
> + 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 ret;
> + }
> + /* 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... %x\n",
> + dma_get_mask(rproc->dev.parent), ret);
> + }
> +
> + rproc_register_rvdev(rvdev);
> +
> + rvdev->subdev.start = rproc_vdev_do_start;
> + rvdev->subdev.stop = rproc_vdev_do_stop;
> +
> + rproc_add_subdev(rproc, &rvdev->subdev);
> +
> + return 0;
> +}
> +
> +static void rproc_rvdev_remove_device(struct rproc_vdev *rvdev)
> +{
> + struct rproc *rproc = rvdev->rproc;
> +
> + rproc_remove_subdev(rproc, &rvdev->subdev);
> + rproc_unregister_rvdev(rvdev);
> + device_unregister(&rvdev->dev);
> +}
> +
> +void rproc_vdev_release(struct kref *ref)
> +{
> + struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount);
> + struct rproc_vring *rvring;
> + int id;
> +
> + for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> + rvring = &rvdev->vring[id];
> + rproc_free_vring(rvring);
> + }
> +
> + rproc_rvdev_remove_device(rvdev);
> +}
> --
> 2.17.1
>

2021-10-22 17:42:06

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [RFC PATCH 5/7] remoteproc: virtio: Create platform device for the remoteproc_virtio

The title mentions the creation of a "platform device" but this patch adds a
platform driver interface.

On Fri, Oct 01, 2021 at 12:12:32PM +0200, Arnaud Pouliquen wrote:
> Define a platform device for the remoteproc virtio to prepare the
> management of the remoteproc virtio as a platform device.

The above should be:

"Define a platform driver to prepare for the managemnt of remoteproc virtio
devices as 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.
>
> Signed-off-by: Arnaud Pouliquen <[email protected]>
> ---
> drivers/remoteproc/remoteproc_internal.h | 6 +++
> drivers/remoteproc/remoteproc_virtio.c | 65 ++++++++++++++++++++++++
> include/linux/remoteproc.h | 2 +
> 3 files changed, 73 insertions(+)
>
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index 4ce012c353c0..1b963a8912ed 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -24,6 +24,12 @@ struct rproc_debug_trace {
> struct rproc_mem_entry trace_mem;
> };
>
> +struct rproc_vdev_data {
> + u32 rsc_offset;
> + unsigned int id;
> + unsigned int index;
> +};
> +
> /* from remoteproc_core.c */
> void rproc_release(struct kref *kref);
> int rproc_of_parse_firmware(struct device *dev, int index,
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index c9eecd2f9fb2..9b2ab79e4c4c 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -4,6 +4,7 @@
> *
> * Copyright (C) 2011 Texas Instruments, Inc.
> * Copyright (C) 2011 Google, Inc.
> + * Copyright (C) 2021 STMicroelectronics
> *
> * Ohad Ben-Cohen <[email protected]>
> * Brian Swetland <[email protected]>
> @@ -13,6 +14,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>
> @@ -571,3 +573,66 @@ void rproc_vdev_release(struct kref *ref)
>
> rproc_rvdev_remove_device(rvdev);
> }
> +
> +static int rproc_virtio_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct rproc_vdev_data *vdev_data = dev->platform_data;
> + struct rproc_vdev *rvdev;
> + struct rproc *rproc;
> +
> + if (!vdev_data)
> + return -EINVAL;
> +
> + rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL);
> + if (!rvdev)
> + return -ENOMEM;
> +
> + rproc = container_of(dev->parent, struct rproc, dev);
> +
> + rvdev->rsc_offset = vdev_data->rsc_offset;
> + rvdev->id = vdev_data->id;
> + rvdev->index = vdev_data->index;
> +
> + rvdev->pdev = pdev;
> + rvdev->rproc = rproc;
> +
> + platform_set_drvdata(pdev, rvdev);
> +
> + return rproc_rvdev_add_device(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;
> +
> + for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> + rvring = &rvdev->vring[id];
> + rproc_free_vring(rvring);
> + }
> +
> + rproc_remove_subdev(rproc, &rvdev->subdev);
> + rproc_unregister_rvdev(rvdev);
> + dev_dbg(&pdev->dev, "virtio dev %d removed\n", rvdev->index);
> +
> + return 0;
> +}
> +
> +/* Platform driver */
> +static const struct of_device_id rproc_virtio_match[] = {
> + { .compatible = "rproc-virtio", },
> + {},
> +};
> +
> +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 e0600e1e5c17..542a3d4664f2 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -616,6 +616,7 @@ 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
> + * @pdev: remoteproc virtio platform device
> * @dev: device struct used for reference count semantics
> * @id: virtio device id (as in virtio_ids.h)
> * @node: list node
> @@ -628,6 +629,7 @@ struct rproc_vdev {
> struct kref refcount;
>
> struct rproc_subdev subdev;
> + struct platform_device *pdev;
> struct device dev;
>
> unsigned int id;
> --
> 2.17.1
>

2021-10-22 17:44:19

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [RFC PATCH 5/7] remoteproc: virtio: Create platform device for the remoteproc_virtio

On Fri, Oct 01, 2021 at 12:12:32PM +0200, Arnaud Pouliquen wrote:
> Define a platform device for the remoteproc virtio to prepare the
> management of the remoteproc virtio as a platform device.
>
> 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.
>
> Signed-off-by: Arnaud Pouliquen <[email protected]>
> ---
> drivers/remoteproc/remoteproc_internal.h | 6 +++
> drivers/remoteproc/remoteproc_virtio.c | 65 ++++++++++++++++++++++++
> include/linux/remoteproc.h | 2 +
> 3 files changed, 73 insertions(+)
>
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index 4ce012c353c0..1b963a8912ed 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -24,6 +24,12 @@ struct rproc_debug_trace {
> struct rproc_mem_entry trace_mem;
> };
>
> +struct rproc_vdev_data {

s/rproc_vdev_data/rproc_vdev_pdata

> + u32 rsc_offset;
> + unsigned int id;
> + unsigned int index;
> +};
> +
> /* from remoteproc_core.c */
> void rproc_release(struct kref *kref);
> int rproc_of_parse_firmware(struct device *dev, int index,
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index c9eecd2f9fb2..9b2ab79e4c4c 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -4,6 +4,7 @@
> *
> * Copyright (C) 2011 Texas Instruments, Inc.
> * Copyright (C) 2011 Google, Inc.
> + * Copyright (C) 2021 STMicroelectronics
> *
> * Ohad Ben-Cohen <[email protected]>
> * Brian Swetland <[email protected]>
> @@ -13,6 +14,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>
> @@ -571,3 +573,66 @@ void rproc_vdev_release(struct kref *ref)
>
> rproc_rvdev_remove_device(rvdev);
> }
> +
> +static int rproc_virtio_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct rproc_vdev_data *vdev_data = dev->platform_data;
> + struct rproc_vdev *rvdev;
> + struct rproc *rproc;
> +
> + if (!vdev_data)
> + return -EINVAL;
> +
> + rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL);
> + if (!rvdev)
> + return -ENOMEM;
> +
> + rproc = container_of(dev->parent, struct rproc, dev);
> +
> + rvdev->rsc_offset = vdev_data->rsc_offset;
> + rvdev->id = vdev_data->id;
> + rvdev->index = vdev_data->index;
> +
> + rvdev->pdev = pdev;
> + rvdev->rproc = rproc;
> +
> + platform_set_drvdata(pdev, rvdev);
> +
> + return rproc_rvdev_add_device(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;
> +
> + for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
> + rvring = &rvdev->vring[id];
> + rproc_free_vring(rvring);
> + }
> +
> + rproc_remove_subdev(rproc, &rvdev->subdev);
> + rproc_unregister_rvdev(rvdev);
> + dev_dbg(&pdev->dev, "virtio dev %d removed\n", rvdev->index);
> +
> + return 0;
> +}
> +
> +/* Platform driver */
> +static const struct of_device_id rproc_virtio_match[] = {
> + { .compatible = "rproc-virtio", },
> + {},
> +};
> +
> +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 e0600e1e5c17..542a3d4664f2 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -616,6 +616,7 @@ 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
> + * @pdev: remoteproc virtio platform device
> * @dev: device struct used for reference count semantics
> * @id: virtio device id (as in virtio_ids.h)
> * @node: list node
> @@ -628,6 +629,7 @@ struct rproc_vdev {
> struct kref refcount;
>
> struct rproc_subdev subdev;
> + struct platform_device *pdev;
> struct device dev;
>
> unsigned int id;
> --
> 2.17.1
>