* [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel
@ 2021-04-13 13:44 Arnaud Pouliquen
2021-04-13 13:44 ` [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions Arnaud Pouliquen
` (6 more replies)
0 siblings, 7 replies; 23+ messages in thread
From: Arnaud Pouliquen @ 2021-04-13 13:44 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen
update from V1 [1]
- fix issues reported by Mathieu Poirier
This series is the second step in the division of the series [2]:
"Introducing a Generic IOCTL Interface for RPMsg Channel Management".
The purpose of this patchset is to:
- split the control code related to the control
and the endpoint.
- define the rpmsg-raw channel, associated with the rpmsg char device to
allow it to be instantiated using a name service announcement.
An important point to keep in mind for this patchset is that the concept of
channel is associated with a default endpoint. To facilitate communication
with the remote side, this default endpoint must have a fixed address.
Consequently, for this series, I made a design choice to fix the endpoint
on the "rpmsg-raw" channel probe, and not allow to create/destroy an endpoint
on FS open/close.
This is only applicable for channels probed by the rpmsg bus. The behavior,
using the RPMSG_CREATE_EPT_IOCTL and RPMSG_DESTROY_EPT_IOCTL controls, is
preserved.
The next steps should be to correct this:
Introduce the IOCTLs RPMSG_CREATE_DEV_IOCTL and RPMSG_DESTROY_DEV_IOCTL
to instantiate the rpmsg devices
[1]: https://patchwork.kernel.org/project/linux-remoteproc/list/?series=453805
[2]: https://patchwork.kernel.org/project/linux-remoteproc/list/?series=435523
Arnaud Pouliquen (7):
rpmsg: char: Export eptdev create an destroy functions
rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl
rpmsg: Update rpmsg_chrdev_register_device function
rpmsg: char: Introduce __rpmsg_chrdev_create_eptdev function
rpmsg: char: Introduce a rpmsg driver for the rpmsg char device
rpmsg: char: No dynamic endpoint management for the default one
rpmsg: char: Return error if user tries to destroy a default endpoint.
drivers/rpmsg/Kconfig | 9 ++
drivers/rpmsg/Makefile | 1 +
drivers/rpmsg/qcom_glink_native.c | 2 +-
drivers/rpmsg/qcom_smd.c | 2 +-
drivers/rpmsg/rpmsg_char.c | 222 +++++++++-------------------
drivers/rpmsg/rpmsg_char.h | 52 +++++++
drivers/rpmsg/rpmsg_ctrl.c | 231 ++++++++++++++++++++++++++++++
drivers/rpmsg/rpmsg_internal.h | 8 +-
drivers/rpmsg/virtio_rpmsg_bus.c | 2 +-
9 files changed, 368 insertions(+), 161 deletions(-)
create mode 100644 drivers/rpmsg/rpmsg_char.h
create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
--
2.17.1
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions
2021-04-13 13:44 [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel Arnaud Pouliquen
@ 2021-04-13 13:44 ` Arnaud Pouliquen
2021-04-21 17:52 ` Mathieu Poirier
2021-04-13 13:44 ` [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl Arnaud Pouliquen
` (5 subsequent siblings)
6 siblings, 1 reply; 23+ messages in thread
From: Arnaud Pouliquen @ 2021-04-13 13:44 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen
To prepare the split of the code related to the control (ctrldev)
and the endpoint (eptdev) devices in 2 separate files:
- Rename and export the functions in rpmsg_char.h.
- Suppress the dependency with the rpmsg_ctrldev struct in the
rpmsg_chrdev_create_eptdev function.
- The rpmsg class is provided as parameter in rpmsg_chrdev_create_eptdev,
because the class is associated to the control part.
Suggested-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
drivers/rpmsg/rpmsg_char.c | 19 +++++++++------
drivers/rpmsg/rpmsg_char.h | 50 ++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 8 deletions(-)
create mode 100644 drivers/rpmsg/rpmsg_char.h
diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 2bebc9b2d163..b9df8dc4365f 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
+ * Copyright (C) 2021, STMicroelectronics
* Copyright (c) 2016, Linaro Ltd.
* Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
* Copyright (c) 2012, PetaLogix
@@ -22,6 +23,7 @@
#include <linux/uaccess.h>
#include <uapi/linux/rpmsg.h>
+#include "rpmsg_char.h"
#include "rpmsg_internal.h"
#define RPMSG_DEV_MAX (MINORMASK + 1)
@@ -78,7 +80,7 @@ struct rpmsg_eptdev {
wait_queue_head_t readq;
};
-static int rpmsg_eptdev_destroy(struct device *dev, void *data)
+int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data)
{
struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
@@ -97,6 +99,7 @@ static int rpmsg_eptdev_destroy(struct device *dev, void *data)
return 0;
}
+EXPORT_SYMBOL(rpmsg_chrdev_destroy_eptdev);
static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
void *priv, u32 addr)
@@ -280,7 +283,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
if (cmd != RPMSG_DESTROY_EPT_IOCTL)
return -EINVAL;
- return rpmsg_eptdev_destroy(&eptdev->dev, NULL);
+ return rpmsg_chrdev_destroy_eptdev(&eptdev->dev, NULL);
}
static const struct file_operations rpmsg_eptdev_fops = {
@@ -339,10 +342,9 @@ static void rpmsg_eptdev_release_device(struct device *dev)
kfree(eptdev);
}
-static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
- struct rpmsg_channel_info chinfo)
+int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
+ struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
{
- struct rpmsg_device *rpdev = ctrldev->rpdev;
struct rpmsg_eptdev *eptdev;
struct device *dev;
int ret;
@@ -362,7 +364,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
device_initialize(dev);
dev->class = rpmsg_class;
- dev->parent = &ctrldev->dev;
+ dev->parent = parent;
dev->groups = rpmsg_eptdev_groups;
dev_set_drvdata(dev, eptdev);
@@ -405,6 +407,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
return ret;
}
+EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
{
@@ -444,7 +447,7 @@ static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
chinfo.src = eptinfo.src;
chinfo.dst = eptinfo.dst;
- return rpmsg_eptdev_create(ctrldev, chinfo);
+ return rpmsg_chrdev_create_eptdev(ctrldev->rpdev, &ctrldev->dev, chinfo, rpmsg_class);
};
static const struct file_operations rpmsg_ctrldev_fops = {
@@ -530,7 +533,7 @@ static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
int ret;
/* Destroy all endpoints */
- ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_eptdev_destroy);
+ ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
if (ret)
dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
diff --git a/drivers/rpmsg/rpmsg_char.h b/drivers/rpmsg/rpmsg_char.h
new file mode 100644
index 000000000000..379d2ae2bee8
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_char.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) STMicroelectronics 2021.
+ */
+
+#ifndef __RPMSG_CHRDEV_H__
+#define __RPMSG_CHRDEV_H__
+
+#if IS_REACHABLE(CONFIG_RPMSG_CHAR)
+/**
+ * rpmsg_chrdev_create_eptdev() - register char device based on an endpoint
+ * @rpdev: prepared rpdev to be used for creating endpoints
+ * @parent: parent device
+ * @chinfo: assiated endpoint channel information.
+ *
+ * This function create a new rpmsg char endpoint device to instantiate a new
+ * endpoint based on chinfo information.
+ */
+int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
+ struct rpmsg_channel_info chinfo, struct class *rpmsg_class);
+
+/**
+ * rpmsg_chrdev_destroy_eptdev() - destroy created char device endpoint.
+ * @data: private data associated to the endpoint device
+ *
+ * This function destroys a rpmsg char endpoint device created by the RPMSG_DESTROY_EPT_IOCTL
+ * control.
+ */
+int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data);
+
+#else /*IS_REACHABLE(CONFIG_RPMSG_CHAR) */
+
+static inline int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
+ struct rpmsg_channel_info chinfo,
+ struct class *rpmsg_class)
+{
+ return -EINVAL;
+}
+
+static inline int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data)
+{
+ /* This shouldn't be possible */
+ WARN_ON(1);
+
+ return 0;
+}
+
+#endif /*IS_REACHABLE(CONFIG_RPMSG_CHAR) */
+
+#endif /*__RPMSG_CHRDEV_H__ */
--
2.17.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl
2021-04-13 13:44 [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel Arnaud Pouliquen
2021-04-13 13:44 ` [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions Arnaud Pouliquen
@ 2021-04-13 13:44 ` Arnaud Pouliquen
2021-04-21 18:04 ` Mathieu Poirier
2021-04-13 13:44 ` [PATCH v2 3/7] rpmsg: Update rpmsg_chrdev_register_device function Arnaud Pouliquen
` (4 subsequent siblings)
6 siblings, 1 reply; 23+ messages in thread
From: Arnaud Pouliquen @ 2021-04-13 13:44 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen
Create the rpmsg_ctrl.c module and move the code related to the
rpmsg_ctrldev device in this new module.
Add the dependency between rpmsg_char and rpmsg_ctrl in the
kconfig file.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
update from v1:
- keep "rpmsg_chrdev" driver name in rpmsg_ctrl, driver will be renamed
in next path that renames the rpmsg_chrdev_create_eptdev.
- rename the chardev regions
- move RPMSG_DEV_MAX to rpmsg_char.h
---
drivers/rpmsg/Kconfig | 9 ++
drivers/rpmsg/Makefile | 1 +
drivers/rpmsg/rpmsg_char.c | 181 +----------------------------
drivers/rpmsg/rpmsg_char.h | 2 +
drivers/rpmsg/rpmsg_ctrl.c | 231 +++++++++++++++++++++++++++++++++++++
5 files changed, 245 insertions(+), 179 deletions(-)
create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 0b4407abdf13..d822ec9ec692 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -10,11 +10,20 @@ config RPMSG_CHAR
tristate "RPMSG device interface"
depends on RPMSG
depends on NET
+ select RPMSG_CTRL
help
Say Y here to export rpmsg endpoints as device files, usually found
in /dev. They make it possible for user-space programs to send and
receive rpmsg packets.
+config RPMSG_CTRL
+ tristate "RPMSG control interface"
+ depends on RPMSG
+ help
+ Say Y here to enable the support of the /dev/rpmsg_ctrlX API. This API
+ allows user-space programs to create endpoints with specific service name,
+ source and destination addresses.
+
config RPMSG_NS
tristate "RPMSG name service announcement"
depends on RPMSG
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 8d452656f0ee..58e3b382e316 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_RPMSG) += rpmsg_core.o
obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o
+obj-$(CONFIG_RPMSG_CTRL) += rpmsg_ctrl.o
obj-$(CONFIG_RPMSG_NS) += rpmsg_ns.o
obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o
qcom_glink-objs := qcom_glink_native.o qcom_glink_ssr.o
diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index b9df8dc4365f..21ef9d9eccd7 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -26,33 +26,14 @@
#include "rpmsg_char.h"
#include "rpmsg_internal.h"
-#define RPMSG_DEV_MAX (MINORMASK + 1)
-
static dev_t rpmsg_major;
-static struct class *rpmsg_class;
-static DEFINE_IDA(rpmsg_ctrl_ida);
static DEFINE_IDA(rpmsg_ept_ida);
static DEFINE_IDA(rpmsg_minor_ida);
#define dev_to_eptdev(dev) container_of(dev, struct rpmsg_eptdev, dev)
#define cdev_to_eptdev(i_cdev) container_of(i_cdev, struct rpmsg_eptdev, cdev)
-#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrldev, dev)
-#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrldev, cdev)
-
-/**
- * struct rpmsg_ctrldev - control device for instantiating endpoint devices
- * @rpdev: underlaying rpmsg device
- * @cdev: cdev for the ctrl device
- * @dev: device for the ctrl device
- */
-struct rpmsg_ctrldev {
- struct rpmsg_device *rpdev;
- struct cdev cdev;
- struct device dev;
-};
-
/**
* struct rpmsg_eptdev - endpoint device context
* @dev: endpoint device
@@ -409,169 +390,13 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
}
EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
-static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
-{
- struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
-
- get_device(&ctrldev->dev);
- filp->private_data = ctrldev;
-
- return 0;
-}
-
-static int rpmsg_ctrldev_release(struct inode *inode, struct file *filp)
-{
- struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
-
- put_device(&ctrldev->dev);
-
- return 0;
-}
-
-static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- struct rpmsg_ctrldev *ctrldev = fp->private_data;
- void __user *argp = (void __user *)arg;
- struct rpmsg_endpoint_info eptinfo;
- struct rpmsg_channel_info chinfo;
-
- if (cmd != RPMSG_CREATE_EPT_IOCTL)
- return -EINVAL;
-
- if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
- return -EFAULT;
-
- memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
- chinfo.name[RPMSG_NAME_SIZE-1] = '\0';
- chinfo.src = eptinfo.src;
- chinfo.dst = eptinfo.dst;
-
- return rpmsg_chrdev_create_eptdev(ctrldev->rpdev, &ctrldev->dev, chinfo, rpmsg_class);
-};
-
-static const struct file_operations rpmsg_ctrldev_fops = {
- .owner = THIS_MODULE,
- .open = rpmsg_ctrldev_open,
- .release = rpmsg_ctrldev_release,
- .unlocked_ioctl = rpmsg_ctrldev_ioctl,
- .compat_ioctl = compat_ptr_ioctl,
-};
-
-static void rpmsg_ctrldev_release_device(struct device *dev)
-{
- struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev);
-
- ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
- ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
- cdev_del(&ctrldev->cdev);
- kfree(ctrldev);
-}
-
-static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
-{
- struct rpmsg_ctrldev *ctrldev;
- struct device *dev;
- int ret;
-
- ctrldev = kzalloc(sizeof(*ctrldev), GFP_KERNEL);
- if (!ctrldev)
- return -ENOMEM;
-
- ctrldev->rpdev = rpdev;
-
- dev = &ctrldev->dev;
- device_initialize(dev);
- dev->parent = &rpdev->dev;
- dev->class = rpmsg_class;
-
- cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
- ctrldev->cdev.owner = THIS_MODULE;
-
- ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL);
- if (ret < 0)
- goto free_ctrldev;
- dev->devt = MKDEV(MAJOR(rpmsg_major), ret);
-
- ret = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL);
- if (ret < 0)
- goto free_minor_ida;
- dev->id = ret;
- dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret);
-
- ret = cdev_add(&ctrldev->cdev, dev->devt, 1);
- if (ret)
- goto free_ctrl_ida;
-
- /* We can now rely on the release function for cleanup */
- dev->release = rpmsg_ctrldev_release_device;
-
- ret = device_add(dev);
- if (ret) {
- dev_err(&rpdev->dev, "device_add failed: %d\n", ret);
- put_device(dev);
- }
-
- dev_set_drvdata(&rpdev->dev, ctrldev);
-
- return ret;
-
-free_ctrl_ida:
- ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
-free_minor_ida:
- ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
-free_ctrldev:
- put_device(dev);
- kfree(ctrldev);
-
- return ret;
-}
-
-static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
-{
- struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev);
- int ret;
-
- /* Destroy all endpoints */
- ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
- if (ret)
- dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
-
- device_del(&ctrldev->dev);
- put_device(&ctrldev->dev);
-}
-
-static struct rpmsg_driver rpmsg_chrdev_driver = {
- .probe = rpmsg_chrdev_probe,
- .remove = rpmsg_chrdev_remove,
- .drv = {
- .name = "rpmsg_chrdev",
- },
-};
-
static int rpmsg_chrdev_init(void)
{
int ret;
- ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg");
- if (ret < 0) {
+ ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char");
+ if (ret < 0)
pr_err("rpmsg: failed to allocate char dev region\n");
- return ret;
- }
-
- rpmsg_class = class_create(THIS_MODULE, "rpmsg");
- if (IS_ERR(rpmsg_class)) {
- pr_err("failed to create rpmsg class\n");
- unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
- return PTR_ERR(rpmsg_class);
- }
-
- ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
- if (ret < 0) {
- pr_err("rpmsgchr: failed to register rpmsg driver\n");
- class_destroy(rpmsg_class);
- unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
- }
return ret;
}
@@ -579,8 +404,6 @@ postcore_initcall(rpmsg_chrdev_init);
static void rpmsg_chrdev_exit(void)
{
- unregister_rpmsg_driver(&rpmsg_chrdev_driver);
- class_destroy(rpmsg_class);
unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
}
module_exit(rpmsg_chrdev_exit);
diff --git a/drivers/rpmsg/rpmsg_char.h b/drivers/rpmsg/rpmsg_char.h
index 379d2ae2bee8..f20a215073c3 100644
--- a/drivers/rpmsg/rpmsg_char.h
+++ b/drivers/rpmsg/rpmsg_char.h
@@ -6,6 +6,8 @@
#ifndef __RPMSG_CHRDEV_H__
#define __RPMSG_CHRDEV_H__
+#define RPMSG_DEV_MAX (MINORMASK + 1)
+
#if IS_REACHABLE(CONFIG_RPMSG_CHAR)
/**
* rpmsg_chrdev_create_eptdev() - register char device based on an endpoint
diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
new file mode 100644
index 000000000000..a5bb9ed97f32
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_ctrl.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021, STMicroelectronics
+ * Copyright (c) 2016, Linaro Ltd.
+ * Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2012, PetaLogix
+ * Copyright (c) 2011, Texas Instruments, Inc.
+ * Copyright (c) 2011, Google, Inc.
+ *
+ * Based on rpmsg performance statistics driver by Michal Simek, which in turn
+ * was based on TI & Google OMX rpmsg driver.
+ */
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/slab.h>
+#include <uapi/linux/rpmsg.h>
+
+#include "rpmsg_char.h"
+#include "rpmsg_internal.h"
+
+static dev_t rpmsg_major;
+struct class *rpmsg_class;
+
+static DEFINE_IDA(rpmsg_ctrl_ida);
+static DEFINE_IDA(rpmsg_minor_ida);
+
+#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrldev, dev)
+#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrldev, cdev)
+
+/**
+ * struct rpmsg_ctrldev - control device for instantiating endpoint devices
+ * @rpdev: underlaying rpmsg device
+ * @cdev: cdev for the ctrl device
+ * @dev: device for the ctrl device
+ */
+struct rpmsg_ctrldev {
+ struct rpmsg_device *rpdev;
+ struct cdev cdev;
+ struct device dev;
+};
+
+static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
+{
+ struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
+
+ get_device(&ctrldev->dev);
+ filp->private_data = ctrldev;
+
+ return 0;
+}
+
+static int rpmsg_ctrldev_release(struct inode *inode, struct file *filp)
+{
+ struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
+
+ put_device(&ctrldev->dev);
+
+ return 0;
+}
+
+static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct rpmsg_ctrldev *ctrldev = fp->private_data;
+ void __user *argp = (void __user *)arg;
+ struct rpmsg_endpoint_info eptinfo;
+ struct rpmsg_channel_info chinfo;
+
+ if (cmd != RPMSG_CREATE_EPT_IOCTL)
+ return -EINVAL;
+
+ if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
+ return -EFAULT;
+
+ memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
+ chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
+ chinfo.src = eptinfo.src;
+ chinfo.dst = eptinfo.dst;
+
+ return rpmsg_chrdev_create_eptdev(ctrldev->rpdev, &ctrldev->dev, chinfo, rpmsg_class);
+};
+
+static const struct file_operations rpmsg_ctrldev_fops = {
+ .owner = THIS_MODULE,
+ .open = rpmsg_ctrldev_open,
+ .release = rpmsg_ctrldev_release,
+ .unlocked_ioctl = rpmsg_ctrldev_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+};
+
+static void rpmsg_ctrldev_release_device(struct device *dev)
+{
+ struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev);
+
+ ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
+ ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
+ cdev_del(&ctrldev->cdev);
+ kfree(ctrldev);
+}
+
+static int rpmsg_ctrldev_probe(struct rpmsg_device *rpdev)
+{
+ struct rpmsg_ctrldev *ctrldev;
+ struct device *dev;
+ int ret;
+
+ ctrldev = kzalloc(sizeof(*ctrldev), GFP_KERNEL);
+ if (!ctrldev)
+ return -ENOMEM;
+
+ ctrldev->rpdev = rpdev;
+
+ dev = &ctrldev->dev;
+ device_initialize(dev);
+ dev->parent = &rpdev->dev;
+ dev->class = rpmsg_class;
+
+ cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
+ ctrldev->cdev.owner = THIS_MODULE;
+
+ ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL);
+ if (ret < 0)
+ goto free_ctrldev;
+ dev->devt = MKDEV(MAJOR(rpmsg_major), ret);
+
+ ret = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL);
+ if (ret < 0)
+ goto free_minor_ida;
+ dev->id = ret;
+ dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret);
+
+ ret = cdev_add(&ctrldev->cdev, dev->devt, 1);
+ if (ret)
+ goto free_ctrl_ida;
+
+ /* We can now rely on the release function for cleanup */
+ dev->release = rpmsg_ctrldev_release_device;
+
+ ret = device_add(dev);
+ if (ret) {
+ dev_err(&rpdev->dev, "device_add failed: %d\n", ret);
+ put_device(dev);
+ }
+
+ dev_set_drvdata(&rpdev->dev, ctrldev);
+
+ return ret;
+
+free_ctrl_ida:
+ ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
+free_minor_ida:
+ ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
+free_ctrldev:
+ put_device(dev);
+ kfree(ctrldev);
+
+ return ret;
+}
+
+static void rpmsg_ctrldev_remove(struct rpmsg_device *rpdev)
+{
+ struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev);
+ int ret;
+
+ /* Destroy all endpoints */
+ ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
+ if (ret)
+ dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
+
+ device_del(&ctrldev->dev);
+ put_device(&ctrldev->dev);
+}
+
+static struct rpmsg_driver rpmsg_ctrldev_driver = {
+ .probe = rpmsg_ctrldev_probe,
+ .remove = rpmsg_ctrldev_remove,
+ .drv = {
+ .name = "rpmsg_chrdev",
+ },
+};
+
+static int rpmsg_ctrldev_init(void)
+{
+ int ret;
+
+ ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_ctrl");
+ if (ret < 0) {
+ pr_err("rpmsg: failed to allocate char dev region\n");
+ return ret;
+ }
+
+ rpmsg_class = class_create(THIS_MODULE, "rpmsg");
+ if (IS_ERR(rpmsg_class)) {
+ pr_err("failed to create rpmsg class\n");
+ ret = PTR_ERR(rpmsg_class);
+ goto free_region;
+ }
+
+ ret = register_rpmsg_driver(&rpmsg_ctrldev_driver);
+ if (ret < 0) {
+ pr_err("rpmsg ctrl: failed to register rpmsg driver\n");
+ goto free_class;
+ }
+
+ return 0;
+
+free_class:
+ class_destroy(rpmsg_class);
+free_region:
+ unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
+
+ return ret;
+}
+postcore_initcall(rpmsg_ctrldev_init);
+
+static void rpmsg_ctrldev_exit(void)
+{
+ unregister_rpmsg_driver(&rpmsg_ctrldev_driver);
+ class_destroy(rpmsg_class);
+ unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
+}
+module_exit(rpmsg_ctrldev_exit);
+
+MODULE_DESCRIPTION("rpmsg control interface");
+MODULE_ALIAS("rpmsg:" KBUILD_MODNAME);
+MODULE_LICENSE("GPL v2");
--
2.17.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 3/7] rpmsg: Update rpmsg_chrdev_register_device function
2021-04-13 13:44 [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel Arnaud Pouliquen
2021-04-13 13:44 ` [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions Arnaud Pouliquen
2021-04-13 13:44 ` [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl Arnaud Pouliquen
@ 2021-04-13 13:44 ` Arnaud Pouliquen
2021-04-21 18:06 ` Mathieu Poirier
2021-04-13 13:44 ` [PATCH v2 4/7] rpmsg: char: Introduce __rpmsg_chrdev_create_eptdev function Arnaud Pouliquen
` (3 subsequent siblings)
6 siblings, 1 reply; 23+ messages in thread
From: Arnaud Pouliquen @ 2021-04-13 13:44 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen
The rpmsg_chrdev driver has been replaced by the rpmsg_ctrl driver
for the /dev/rpmsg_ctrlX devices management. The reference for the
driver override is now the rpmsg_ctrl.
Update the rpmsg_chrdev_register_device function to reflect the update,
and rename the function to use the rpmsg_ctrldev prefix.
The platform drivers are updated accordingly.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
update from v1
- move the rename of the rpmsg_ctrl driver from previous patch to
this one.
---
drivers/rpmsg/qcom_glink_native.c | 2 +-
drivers/rpmsg/qcom_smd.c | 2 +-
drivers/rpmsg/rpmsg_ctrl.c | 2 +-
drivers/rpmsg/rpmsg_internal.h | 8 ++++----
drivers/rpmsg/virtio_rpmsg_bus.c | 2 +-
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
index 05533c71b10e..7d7e809800ec 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1642,7 +1642,7 @@ static int qcom_glink_create_chrdev(struct qcom_glink *glink)
rpdev->dev.parent = glink->dev;
rpdev->dev.release = qcom_glink_device_release;
- return rpmsg_chrdev_register_device(rpdev);
+ return rpmsg_ctrldev_register_device(rpdev);
}
struct qcom_glink *qcom_glink_native_probe(struct device *dev,
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index 8da1b5cb31b3..d223e438d17c 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -1113,7 +1113,7 @@ static int qcom_smd_create_chrdev(struct qcom_smd_edge *edge)
qsdev->rpdev.dev.parent = &edge->dev;
qsdev->rpdev.dev.release = qcom_smd_release_device;
- return rpmsg_chrdev_register_device(&qsdev->rpdev);
+ return rpmsg_ctrldev_register_device(&qsdev->rpdev);
}
/*
diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
index a5bb9ed97f32..059c228d0045 100644
--- a/drivers/rpmsg/rpmsg_ctrl.c
+++ b/drivers/rpmsg/rpmsg_ctrl.c
@@ -180,7 +180,7 @@ static struct rpmsg_driver rpmsg_ctrldev_driver = {
.probe = rpmsg_ctrldev_probe,
.remove = rpmsg_ctrldev_remove,
.drv = {
- .name = "rpmsg_chrdev",
+ .name = "rpmsg_ctrl",
},
};
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index a76c344253bf..8c500a8f29aa 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -82,16 +82,16 @@ struct rpmsg_device *rpmsg_create_channel(struct rpmsg_device *rpdev,
int rpmsg_release_channel(struct rpmsg_device *rpdev,
struct rpmsg_channel_info *chinfo);
/**
- * rpmsg_chrdev_register_device() - register chrdev device based on rpdev
+ * rpmsg_ctrl_register_device() - register a char device for control based on rpdev
* @rpdev: prepared rpdev to be used for creating endpoints
*
* This function wraps rpmsg_register_device() preparing the rpdev for use as
* basis for the rpmsg chrdev.
*/
-static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev)
+static inline int rpmsg_ctrldev_register_device(struct rpmsg_device *rpdev)
{
- strcpy(rpdev->id.name, "rpmsg_chrdev");
- rpdev->driver_override = "rpmsg_chrdev";
+ strcpy(rpdev->id.name, "rpmsg_ctrl");
+ rpdev->driver_override = "rpmsg_ctrl";
return rpmsg_register_device(rpdev);
}
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 8e49a3bacfc7..e42234a3e2ab 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -840,7 +840,7 @@ static struct rpmsg_device *rpmsg_virtio_add_ctrl_dev(struct virtio_device *vdev
rpdev_ctrl->dev.release = virtio_rpmsg_release_device;
rpdev_ctrl->little_endian = virtio_is_little_endian(vrp->vdev);
- err = rpmsg_chrdev_register_device(rpdev_ctrl);
+ err = rpmsg_ctrldev_register_device(rpdev_ctrl);
if (err) {
kfree(vch);
return ERR_PTR(err);
--
2.17.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 4/7] rpmsg: char: Introduce __rpmsg_chrdev_create_eptdev function
2021-04-13 13:44 [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel Arnaud Pouliquen
` (2 preceding siblings ...)
2021-04-13 13:44 ` [PATCH v2 3/7] rpmsg: Update rpmsg_chrdev_register_device function Arnaud Pouliquen
@ 2021-04-13 13:44 ` Arnaud Pouliquen
2021-04-21 17:43 ` Mathieu Poirier
2021-04-13 13:44 ` [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device Arnaud Pouliquen
` (2 subsequent siblings)
6 siblings, 1 reply; 23+ messages in thread
From: Arnaud Pouliquen @ 2021-04-13 13:44 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen
Introduce the __rpmsg_chrdev_create_eptdev internal function that returns
the rpmsg_eptdev context structure.
This patch prepares the introduction of a rpmsg channel device for the
char device. The rpmsg device will need a reference to the context.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
update from V1
- fix __rpmsg_chrdev_create_eptdev function header indentation.
---
drivers/rpmsg/rpmsg_char.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 21ef9d9eccd7..a64249d83172 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -323,8 +323,9 @@ static void rpmsg_eptdev_release_device(struct device *dev)
kfree(eptdev);
}
-int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
- struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
+static struct rpmsg_eptdev *
+__rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
+ struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
{
struct rpmsg_eptdev *eptdev;
struct device *dev;
@@ -332,7 +333,7 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
eptdev = kzalloc(sizeof(*eptdev), GFP_KERNEL);
if (!eptdev)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
dev = &eptdev->dev;
eptdev->rpdev = rpdev;
@@ -376,7 +377,7 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
put_device(dev);
}
- return ret;
+ return eptdev;
free_ept_ida:
ida_simple_remove(&rpmsg_ept_ida, dev->id);
@@ -386,7 +387,19 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
put_device(dev);
kfree(eptdev);
- return ret;
+ return ERR_PTR(ret);
+}
+
+int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
+ struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
+{
+ struct rpmsg_eptdev *eptdev;
+
+ eptdev = __rpmsg_chrdev_create_eptdev(rpdev, parent, chinfo, rpmsg_class);
+ if (IS_ERR(eptdev))
+ return PTR_ERR(eptdev);
+
+ return 0;
}
EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
--
2.17.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device
2021-04-13 13:44 [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel Arnaud Pouliquen
` (3 preceding siblings ...)
2021-04-13 13:44 ` [PATCH v2 4/7] rpmsg: char: Introduce __rpmsg_chrdev_create_eptdev function Arnaud Pouliquen
@ 2021-04-13 13:44 ` Arnaud Pouliquen
2021-04-21 17:40 ` Mathieu Poirier
2021-04-13 13:44 ` [PATCH v2 6/7] rpmsg: char: No dynamic endpoint management for the default one Arnaud Pouliquen
2021-04-13 13:44 ` [PATCH v2 7/7] rpmsg: char: Return error if user tries to destroy a default endpoint Arnaud Pouliquen
6 siblings, 1 reply; 23+ messages in thread
From: Arnaud Pouliquen @ 2021-04-13 13:44 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen
A rpmsg char device allows to probe the endpoint device on a remote name
service announcement.
With this patch the /dev/rpmsgX interface is created either by a user
application or by the remote firmware.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
update from V1:
- add missing unregister_rpmsg_driver call on module exit.
---
drivers/rpmsg/rpmsg_char.c | 59 +++++++++++++++++++++++++++++++++++++-
1 file changed, 58 insertions(+), 1 deletion(-)
diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a64249d83172..4606787b7011 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -26,6 +26,8 @@
#include "rpmsg_char.h"
#include "rpmsg_internal.h"
+#define RPMSG_CHAR_DEVNAME "rpmsg-raw"
+
static dev_t rpmsg_major;
static DEFINE_IDA(rpmsg_ept_ida);
@@ -403,13 +405,67 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
}
EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
+static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
+{
+ struct rpmsg_channel_info chinfo;
+ struct rpmsg_eptdev *eptdev;
+
+ if (!rpdev->ept)
+ return -EINVAL;
+
+ memcpy(chinfo.name, RPMSG_CHAR_DEVNAME, sizeof(RPMSG_CHAR_DEVNAME));
+ chinfo.src = rpdev->src;
+ chinfo.dst = rpdev->dst;
+
+ eptdev = __rpmsg_chrdev_create_eptdev(rpdev, &rpdev->dev, chinfo, NULL);
+ if (IS_ERR(eptdev))
+ return PTR_ERR(eptdev);
+
+ /* Set the private field of the default endpoint to retrieve context on callback. */
+ rpdev->ept->priv = eptdev;
+
+ return 0;
+}
+
+static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
+{
+ int ret;
+
+ ret = device_for_each_child(&rpdev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
+ if (ret)
+ dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret);
+}
+
+static struct rpmsg_device_id rpmsg_chrdev_id_table[] = {
+ { .name = RPMSG_CHAR_DEVNAME },
+ { },
+};
+
+static struct rpmsg_driver rpmsg_chrdev_driver = {
+ .probe = rpmsg_chrdev_probe,
+ .remove = rpmsg_chrdev_remove,
+ .id_table = rpmsg_chrdev_id_table,
+ .callback = rpmsg_ept_cb,
+ .drv = {
+ .name = "rpmsg_chrdev",
+ },
+};
+
static int rpmsg_chrdev_init(void)
{
int ret;
ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char");
- if (ret < 0)
+ if (ret < 0) {
pr_err("rpmsg: failed to allocate char dev region\n");
+ return ret;
+ }
+
+ ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
+ if (ret < 0) {
+ pr_err("rpmsg: failed to register rpmsg raw driver\n");
+ unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
+ }
return ret;
}
@@ -417,6 +473,7 @@ postcore_initcall(rpmsg_chrdev_init);
static void rpmsg_chrdev_exit(void)
{
+ unregister_rpmsg_driver(&rpmsg_chrdev_driver);
unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
}
module_exit(rpmsg_chrdev_exit);
--
2.17.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 6/7] rpmsg: char: No dynamic endpoint management for the default one
2021-04-13 13:44 [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel Arnaud Pouliquen
` (4 preceding siblings ...)
2021-04-13 13:44 ` [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device Arnaud Pouliquen
@ 2021-04-13 13:44 ` Arnaud Pouliquen
2021-04-13 13:44 ` [PATCH v2 7/7] rpmsg: char: Return error if user tries to destroy a default endpoint Arnaud Pouliquen
6 siblings, 0 replies; 23+ messages in thread
From: Arnaud Pouliquen @ 2021-04-13 13:44 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen
Do not dynamically manage the default endpoint associated to the rpmsg
device. The ept address must not change.
This update is needed to manage the rpmsg-raw channel. In this
case a default endpoint is used and its address must not change or
been reused by another service.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
drivers/rpmsg/rpmsg_char.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 4606787b7011..fa59abfa8878 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -112,17 +112,26 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
struct rpmsg_endpoint *ept;
struct rpmsg_device *rpdev = eptdev->rpdev;
struct device *dev = &eptdev->dev;
+ u32 addr = eptdev->chinfo.src;
if (eptdev->ept)
return -EBUSY;
get_device(dev);
- ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo);
- if (!ept) {
- dev_err(dev, "failed to open %s\n", eptdev->chinfo.name);
- put_device(dev);
- return -EINVAL;
+ /*
+ * The RPMsg device can has been created by a ns announcement. In this
+ * case a default endpoint has been created. Reuse it to avoid to manage
+ * a new address on each open/close.
+ */
+ ept = rpdev->ept;
+ if (!ept || addr != ept->addr) {
+ ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo);
+ if (!ept) {
+ dev_err(dev, "failed to open %s\n", eptdev->chinfo.name);
+ put_device(dev);
+ return -EINVAL;
+ }
}
eptdev->ept = ept;
@@ -134,12 +143,17 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
{
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
+ struct rpmsg_device *rpdev = eptdev->rpdev;
struct device *dev = &eptdev->dev;
- /* Close the endpoint, if it's not already destroyed by the parent */
+ /*
+ * Close the endpoint, if it's not already destroyed by the parent and it is not the
+ * default one.
+ */
mutex_lock(&eptdev->ept_lock);
if (eptdev->ept) {
- rpmsg_destroy_ept(eptdev->ept);
+ if (eptdev->ept != rpdev->ept)
+ rpmsg_destroy_ept(eptdev->ept);
eptdev->ept = NULL;
}
mutex_unlock(&eptdev->ept_lock);
--
2.17.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 7/7] rpmsg: char: Return error if user tries to destroy a default endpoint.
2021-04-13 13:44 [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel Arnaud Pouliquen
` (5 preceding siblings ...)
2021-04-13 13:44 ` [PATCH v2 6/7] rpmsg: char: No dynamic endpoint management for the default one Arnaud Pouliquen
@ 2021-04-13 13:44 ` Arnaud Pouliquen
6 siblings, 0 replies; 23+ messages in thread
From: Arnaud Pouliquen @ 2021-04-13 13:44 UTC (permalink / raw)
To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen
Using the RPMSG_DESTROY_EPT_IOCTL control, user application can
destroy an endpoint. This patch prevents to destroy a default endpoint
associated to a channel.
This update is needed to manage the "rpmsg-raw" channel. In this
case a default endpoint is used and destroying it without the
channel does not make sense.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
drivers/rpmsg/rpmsg_char.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index fa59abfa8878..d4316bb904f2 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -280,6 +280,10 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
if (cmd != RPMSG_DESTROY_EPT_IOCTL)
return -EINVAL;
+ /* Don't allow to destroy a default endpoint. */
+ if (!eptdev->rpdev || eptdev->ept == eptdev->rpdev->ept)
+ return -EPERM;
+
return rpmsg_chrdev_destroy_eptdev(&eptdev->dev, NULL);
}
--
2.17.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device
2021-04-13 13:44 ` [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device Arnaud Pouliquen
@ 2021-04-21 17:40 ` Mathieu Poirier
2021-04-22 7:58 ` Arnaud POULIQUEN
0 siblings, 1 reply; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-21 17:40 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
Good day Arnaud,
On Tue, Apr 13, 2021 at 03:44:56PM +0200, Arnaud Pouliquen wrote:
> A rpmsg char device allows to probe the endpoint device on a remote name
> service announcement.
>
> With this patch the /dev/rpmsgX interface is created either by a user
> application or by the remote firmware.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>
> ---
> update from V1:
> - add missing unregister_rpmsg_driver call on module exit.
>
> ---
> drivers/rpmsg/rpmsg_char.c | 59 +++++++++++++++++++++++++++++++++++++-
> 1 file changed, 58 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> index a64249d83172..4606787b7011 100644
> --- a/drivers/rpmsg/rpmsg_char.c
> +++ b/drivers/rpmsg/rpmsg_char.c
> @@ -26,6 +26,8 @@
> #include "rpmsg_char.h"
> #include "rpmsg_internal.h"
>
> +#define RPMSG_CHAR_DEVNAME "rpmsg-raw"
> +
Why not simply call it rpmsg-char?
> static dev_t rpmsg_major;
>
> static DEFINE_IDA(rpmsg_ept_ida);
> @@ -403,13 +405,67 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
> }
> EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>
> +static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
> +{
> + struct rpmsg_channel_info chinfo;
> + struct rpmsg_eptdev *eptdev;
> +
> + if (!rpdev->ept)
> + return -EINVAL;
> +
> + memcpy(chinfo.name, RPMSG_CHAR_DEVNAME, sizeof(RPMSG_CHAR_DEVNAME));
> + chinfo.src = rpdev->src;
> + chinfo.dst = rpdev->dst;
> +
> + eptdev = __rpmsg_chrdev_create_eptdev(rpdev, &rpdev->dev, chinfo, NULL);
> + if (IS_ERR(eptdev))
> + return PTR_ERR(eptdev);
> +
> + /* Set the private field of the default endpoint to retrieve context on callback. */
> + rpdev->ept->priv = eptdev;
This is already done in rpmsg_create_ept() when rpmsg_eptdev_open() is called.
> +
> + return 0;
> +}
> +
> +static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
> +{
> + int ret;
> +
> + ret = device_for_each_child(&rpdev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
> + if (ret)
> + dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret);
> +}
> +
> +static struct rpmsg_device_id rpmsg_chrdev_id_table[] = {
> + { .name = RPMSG_CHAR_DEVNAME },
> + { },
> +};
> +
> +static struct rpmsg_driver rpmsg_chrdev_driver = {
> + .probe = rpmsg_chrdev_probe,
> + .remove = rpmsg_chrdev_remove,
> + .id_table = rpmsg_chrdev_id_table,
> + .callback = rpmsg_ept_cb,
Not sure why we need a callback associated to this driver when
rpmsg_eptdev_open() already creates and rpmsg_endpoint. To me the only thing
having a callback provides is the association between the rpmsg_device and the
rpmsg_endpoint[1] that happens in rpmsg_dev_probe(). The QC folks already do
this association in their platform code[2]. Since this is not done in
__rpmsg_create_ept() a check for rpdev->ept == NULL could be done in
rpmsg_eptdev_open() and do the assignment there.
[1]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/rpmsg_core.c#L513
[2]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/qcom_glink_native.c#L1623
> + .drv = {
> + .name = "rpmsg_chrdev",
> + },
> +};
> +
> static int rpmsg_chrdev_init(void)
> {
> int ret;
>
> ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char");
> - if (ret < 0)
> + if (ret < 0) {
> pr_err("rpmsg: failed to allocate char dev region\n");
> + return ret;
> + }
> +
> + ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
> + if (ret < 0) {
> + pr_err("rpmsg: failed to register rpmsg raw driver\n");
> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> + }
>
> return ret;
> }
> @@ -417,6 +473,7 @@ postcore_initcall(rpmsg_chrdev_init);
>
> static void rpmsg_chrdev_exit(void)
> {
> + unregister_rpmsg_driver(&rpmsg_chrdev_driver);
> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> }
> module_exit(rpmsg_chrdev_exit);
> --
> 2.17.1
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 4/7] rpmsg: char: Introduce __rpmsg_chrdev_create_eptdev function
2021-04-13 13:44 ` [PATCH v2 4/7] rpmsg: char: Introduce __rpmsg_chrdev_create_eptdev function Arnaud Pouliquen
@ 2021-04-21 17:43 ` Mathieu Poirier
2021-04-21 17:45 ` Mathieu Poirier
0 siblings, 1 reply; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-21 17:43 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On Tue, Apr 13, 2021 at 03:44:55PM +0200, Arnaud Pouliquen wrote:
> Introduce the __rpmsg_chrdev_create_eptdev internal function that returns
> the rpmsg_eptdev context structure.
>
> This patch prepares the introduction of a rpmsg channel device for the
> char device. The rpmsg device will need a reference to the context.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>
> ---
> update from V1
> - fix __rpmsg_chrdev_create_eptdev function header indentation.
>
> ---
> drivers/rpmsg/rpmsg_char.c | 23 ++++++++++++++++++-----
> 1 file changed, 18 insertions(+), 5 deletions(-)
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> index 21ef9d9eccd7..a64249d83172 100644
> --- a/drivers/rpmsg/rpmsg_char.c
> +++ b/drivers/rpmsg/rpmsg_char.c
> @@ -323,8 +323,9 @@ static void rpmsg_eptdev_release_device(struct device *dev)
> kfree(eptdev);
> }
>
> -int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> - struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
> +static struct rpmsg_eptdev *
> +__rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> + struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
> {
> struct rpmsg_eptdev *eptdev;
> struct device *dev;
> @@ -332,7 +333,7 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
>
> eptdev = kzalloc(sizeof(*eptdev), GFP_KERNEL);
> if (!eptdev)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> dev = &eptdev->dev;
> eptdev->rpdev = rpdev;
> @@ -376,7 +377,7 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
> put_device(dev);
> }
>
> - return ret;
> + return eptdev;
>
> free_ept_ida:
> ida_simple_remove(&rpmsg_ept_ida, dev->id);
> @@ -386,7 +387,19 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
> put_device(dev);
> kfree(eptdev);
>
> - return ret;
> + return ERR_PTR(ret);
> +}
> +
> +int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> + struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
> +{
> + struct rpmsg_eptdev *eptdev;
> +
> + eptdev = __rpmsg_chrdev_create_eptdev(rpdev, parent, chinfo, rpmsg_class);
> + if (IS_ERR(eptdev))
> + return PTR_ERR(eptdev);
> +
> + return 0;
> }
> EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>
> --
> 2.17.1
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 4/7] rpmsg: char: Introduce __rpmsg_chrdev_create_eptdev function
2021-04-21 17:43 ` Mathieu Poirier
@ 2021-04-21 17:45 ` Mathieu Poirier
0 siblings, 0 replies; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-21 17:45 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On Wed, Apr 21, 2021 at 11:43:29AM -0600, Mathieu Poirier wrote:
> On Tue, Apr 13, 2021 at 03:44:55PM +0200, Arnaud Pouliquen wrote:
> > Introduce the __rpmsg_chrdev_create_eptdev internal function that returns
> > the rpmsg_eptdev context structure.
> >
> > This patch prepares the introduction of a rpmsg channel device for the
> > char device. The rpmsg device will need a reference to the context.
> >
> > Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> >
> > ---
> > update from V1
> > - fix __rpmsg_chrdev_create_eptdev function header indentation.
> >
> > ---
> > drivers/rpmsg/rpmsg_char.c | 23 ++++++++++++++++++-----
> > 1 file changed, 18 insertions(+), 5 deletions(-)
>
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
Please excuse the brain-bug here - this RB was destined to patch 3/7. I am not sure
about this patch yet (see comment in 5/7).
> >
> > diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> > index 21ef9d9eccd7..a64249d83172 100644
> > --- a/drivers/rpmsg/rpmsg_char.c
> > +++ b/drivers/rpmsg/rpmsg_char.c
> > @@ -323,8 +323,9 @@ static void rpmsg_eptdev_release_device(struct device *dev)
> > kfree(eptdev);
> > }
> >
> > -int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> > - struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
> > +static struct rpmsg_eptdev *
> > +__rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> > + struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
> > {
> > struct rpmsg_eptdev *eptdev;
> > struct device *dev;
> > @@ -332,7 +333,7 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
> >
> > eptdev = kzalloc(sizeof(*eptdev), GFP_KERNEL);
> > if (!eptdev)
> > - return -ENOMEM;
> > + return ERR_PTR(-ENOMEM);
> >
> > dev = &eptdev->dev;
> > eptdev->rpdev = rpdev;
> > @@ -376,7 +377,7 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
> > put_device(dev);
> > }
> >
> > - return ret;
> > + return eptdev;
> >
> > free_ept_ida:
> > ida_simple_remove(&rpmsg_ept_ida, dev->id);
> > @@ -386,7 +387,19 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
> > put_device(dev);
> > kfree(eptdev);
> >
> > - return ret;
> > + return ERR_PTR(ret);
> > +}
> > +
> > +int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> > + struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
> > +{
> > + struct rpmsg_eptdev *eptdev;
> > +
> > + eptdev = __rpmsg_chrdev_create_eptdev(rpdev, parent, chinfo, rpmsg_class);
> > + if (IS_ERR(eptdev))
> > + return PTR_ERR(eptdev);
> > +
> > + return 0;
> > }
> > EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
> >
> > --
> > 2.17.1
> >
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions
2021-04-13 13:44 ` [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions Arnaud Pouliquen
@ 2021-04-21 17:52 ` Mathieu Poirier
2021-04-22 7:55 ` Arnaud POULIQUEN
0 siblings, 1 reply; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-21 17:52 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On Tue, Apr 13, 2021 at 03:44:52PM +0200, Arnaud Pouliquen wrote:
> To prepare the split of the code related to the control (ctrldev)
> and the endpoint (eptdev) devices in 2 separate files:
>
> - Rename and export the functions in rpmsg_char.h.
>
> - Suppress the dependency with the rpmsg_ctrldev struct in the
> rpmsg_chrdev_create_eptdev function.
>
> - The rpmsg class is provided as parameter in rpmsg_chrdev_create_eptdev,
> because the class is associated to the control part.
>
> Suggested-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> ---
> drivers/rpmsg/rpmsg_char.c | 19 +++++++++------
> drivers/rpmsg/rpmsg_char.h | 50 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 61 insertions(+), 8 deletions(-)
> create mode 100644 drivers/rpmsg/rpmsg_char.h
>
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> index 2bebc9b2d163..b9df8dc4365f 100644
> --- a/drivers/rpmsg/rpmsg_char.c
> +++ b/drivers/rpmsg/rpmsg_char.c
> @@ -1,5 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
> /*
> + * Copyright (C) 2021, STMicroelectronics
> * Copyright (c) 2016, Linaro Ltd.
> * Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
> * Copyright (c) 2012, PetaLogix
> @@ -22,6 +23,7 @@
> #include <linux/uaccess.h>
> #include <uapi/linux/rpmsg.h>
>
> +#include "rpmsg_char.h"
> #include "rpmsg_internal.h"
>
> #define RPMSG_DEV_MAX (MINORMASK + 1)
> @@ -78,7 +80,7 @@ struct rpmsg_eptdev {
> wait_queue_head_t readq;
> };
>
> -static int rpmsg_eptdev_destroy(struct device *dev, void *data)
> +int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data)
Shouldn't this be rpmsg_chrdev_eptdev_destroy()? I've been wondering about the
flipping of destroy and eptdev... The same for rpmsg_chrdev_create_eptdev().
With that:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> {
> struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
>
> @@ -97,6 +99,7 @@ static int rpmsg_eptdev_destroy(struct device *dev, void *data)
>
> return 0;
> }
> +EXPORT_SYMBOL(rpmsg_chrdev_destroy_eptdev);
>
> static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
> void *priv, u32 addr)
> @@ -280,7 +283,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
> if (cmd != RPMSG_DESTROY_EPT_IOCTL)
> return -EINVAL;
>
> - return rpmsg_eptdev_destroy(&eptdev->dev, NULL);
> + return rpmsg_chrdev_destroy_eptdev(&eptdev->dev, NULL);
> }
>
> static const struct file_operations rpmsg_eptdev_fops = {
> @@ -339,10 +342,9 @@ static void rpmsg_eptdev_release_device(struct device *dev)
> kfree(eptdev);
> }
>
> -static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
> - struct rpmsg_channel_info chinfo)
> +int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> + struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
> {
> - struct rpmsg_device *rpdev = ctrldev->rpdev;
> struct rpmsg_eptdev *eptdev;
> struct device *dev;
> int ret;
> @@ -362,7 +364,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
>
> device_initialize(dev);
> dev->class = rpmsg_class;
> - dev->parent = &ctrldev->dev;
> + dev->parent = parent;
> dev->groups = rpmsg_eptdev_groups;
> dev_set_drvdata(dev, eptdev);
>
> @@ -405,6 +407,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
>
> return ret;
> }
> +EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>
> static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
> {
> @@ -444,7 +447,7 @@ static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
> chinfo.src = eptinfo.src;
> chinfo.dst = eptinfo.dst;
>
> - return rpmsg_eptdev_create(ctrldev, chinfo);
> + return rpmsg_chrdev_create_eptdev(ctrldev->rpdev, &ctrldev->dev, chinfo, rpmsg_class);
> };
>
> static const struct file_operations rpmsg_ctrldev_fops = {
> @@ -530,7 +533,7 @@ static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
> int ret;
>
> /* Destroy all endpoints */
> - ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_eptdev_destroy);
> + ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
> if (ret)
> dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
>
> diff --git a/drivers/rpmsg/rpmsg_char.h b/drivers/rpmsg/rpmsg_char.h
> new file mode 100644
> index 000000000000..379d2ae2bee8
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_char.h
> @@ -0,0 +1,50 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * Copyright (C) STMicroelectronics 2021.
> + */
> +
> +#ifndef __RPMSG_CHRDEV_H__
> +#define __RPMSG_CHRDEV_H__
> +
> +#if IS_REACHABLE(CONFIG_RPMSG_CHAR)
> +/**
> + * rpmsg_chrdev_create_eptdev() - register char device based on an endpoint
> + * @rpdev: prepared rpdev to be used for creating endpoints
> + * @parent: parent device
> + * @chinfo: assiated endpoint channel information.
> + *
> + * This function create a new rpmsg char endpoint device to instantiate a new
> + * endpoint based on chinfo information.
> + */
> +int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> + struct rpmsg_channel_info chinfo, struct class *rpmsg_class);
> +
> +/**
> + * rpmsg_chrdev_destroy_eptdev() - destroy created char device endpoint.
> + * @data: private data associated to the endpoint device
> + *
> + * This function destroys a rpmsg char endpoint device created by the RPMSG_DESTROY_EPT_IOCTL
> + * control.
> + */
> +int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data);
> +
> +#else /*IS_REACHABLE(CONFIG_RPMSG_CHAR) */
> +
> +static inline int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> + struct rpmsg_channel_info chinfo,
> + struct class *rpmsg_class)
> +{
> + return -EINVAL;
> +}
> +
> +static inline int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data)
> +{
> + /* This shouldn't be possible */
> + WARN_ON(1);
> +
> + return 0;
> +}
> +
> +#endif /*IS_REACHABLE(CONFIG_RPMSG_CHAR) */
> +
> +#endif /*__RPMSG_CHRDEV_H__ */
> --
> 2.17.1
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl
2021-04-13 13:44 ` [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl Arnaud Pouliquen
@ 2021-04-21 18:04 ` Mathieu Poirier
2021-04-22 7:56 ` Arnaud POULIQUEN
0 siblings, 1 reply; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-21 18:04 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On Tue, Apr 13, 2021 at 03:44:53PM +0200, Arnaud Pouliquen wrote:
> Create the rpmsg_ctrl.c module and move the code related to the
> rpmsg_ctrldev device in this new module.
>
> Add the dependency between rpmsg_char and rpmsg_ctrl in the
> kconfig file.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> ---
> update from v1:
> - keep "rpmsg_chrdev" driver name in rpmsg_ctrl, driver will be renamed
> in next path that renames the rpmsg_chrdev_create_eptdev.
> - rename the chardev regions
> - move RPMSG_DEV_MAX to rpmsg_char.h
> ---
> drivers/rpmsg/Kconfig | 9 ++
> drivers/rpmsg/Makefile | 1 +
> drivers/rpmsg/rpmsg_char.c | 181 +----------------------------
> drivers/rpmsg/rpmsg_char.h | 2 +
> drivers/rpmsg/rpmsg_ctrl.c | 231 +++++++++++++++++++++++++++++++++++++
> 5 files changed, 245 insertions(+), 179 deletions(-)
> create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
>
> diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> index 0b4407abdf13..d822ec9ec692 100644
> --- a/drivers/rpmsg/Kconfig
> +++ b/drivers/rpmsg/Kconfig
> @@ -10,11 +10,20 @@ config RPMSG_CHAR
> tristate "RPMSG device interface"
> depends on RPMSG
> depends on NET
> + select RPMSG_CTRL
> help
> Say Y here to export rpmsg endpoints as device files, usually found
> in /dev. They make it possible for user-space programs to send and
> receive rpmsg packets.
>
> +config RPMSG_CTRL
> + tristate "RPMSG control interface"
> + depends on RPMSG
> + help
> + Say Y here to enable the support of the /dev/rpmsg_ctrlX API. This API
> + allows user-space programs to create endpoints with specific service name,
> + source and destination addresses.
> +
> config RPMSG_NS
> tristate "RPMSG name service announcement"
> depends on RPMSG
> diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
> index 8d452656f0ee..58e3b382e316 100644
> --- a/drivers/rpmsg/Makefile
> +++ b/drivers/rpmsg/Makefile
> @@ -1,6 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0
> obj-$(CONFIG_RPMSG) += rpmsg_core.o
> obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o
> +obj-$(CONFIG_RPMSG_CTRL) += rpmsg_ctrl.o
> obj-$(CONFIG_RPMSG_NS) += rpmsg_ns.o
> obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o
> qcom_glink-objs := qcom_glink_native.o qcom_glink_ssr.o
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> index b9df8dc4365f..21ef9d9eccd7 100644
> --- a/drivers/rpmsg/rpmsg_char.c
> +++ b/drivers/rpmsg/rpmsg_char.c
> @@ -26,33 +26,14 @@
> #include "rpmsg_char.h"
> #include "rpmsg_internal.h"
>
> -#define RPMSG_DEV_MAX (MINORMASK + 1)
> -
> static dev_t rpmsg_major;
> -static struct class *rpmsg_class;
>
> -static DEFINE_IDA(rpmsg_ctrl_ida);
> static DEFINE_IDA(rpmsg_ept_ida);
> static DEFINE_IDA(rpmsg_minor_ida);
>
> #define dev_to_eptdev(dev) container_of(dev, struct rpmsg_eptdev, dev)
> #define cdev_to_eptdev(i_cdev) container_of(i_cdev, struct rpmsg_eptdev, cdev)
>
> -#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrldev, dev)
> -#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrldev, cdev)
> -
> -/**
> - * struct rpmsg_ctrldev - control device for instantiating endpoint devices
> - * @rpdev: underlaying rpmsg device
> - * @cdev: cdev for the ctrl device
> - * @dev: device for the ctrl device
> - */
> -struct rpmsg_ctrldev {
> - struct rpmsg_device *rpdev;
> - struct cdev cdev;
> - struct device dev;
> -};
> -
> /**
> * struct rpmsg_eptdev - endpoint device context
> * @dev: endpoint device
> @@ -409,169 +390,13 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
> }
> EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>
> -static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
> -{
> - struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
> -
> - get_device(&ctrldev->dev);
> - filp->private_data = ctrldev;
> -
> - return 0;
> -}
> -
> -static int rpmsg_ctrldev_release(struct inode *inode, struct file *filp)
> -{
> - struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
> -
> - put_device(&ctrldev->dev);
> -
> - return 0;
> -}
> -
> -static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
> - unsigned long arg)
> -{
> - struct rpmsg_ctrldev *ctrldev = fp->private_data;
> - void __user *argp = (void __user *)arg;
> - struct rpmsg_endpoint_info eptinfo;
> - struct rpmsg_channel_info chinfo;
> -
> - if (cmd != RPMSG_CREATE_EPT_IOCTL)
> - return -EINVAL;
> -
> - if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
> - return -EFAULT;
> -
> - memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
> - chinfo.name[RPMSG_NAME_SIZE-1] = '\0';
> - chinfo.src = eptinfo.src;
> - chinfo.dst = eptinfo.dst;
> -
> - return rpmsg_chrdev_create_eptdev(ctrldev->rpdev, &ctrldev->dev, chinfo, rpmsg_class);
> -};
> -
> -static const struct file_operations rpmsg_ctrldev_fops = {
> - .owner = THIS_MODULE,
> - .open = rpmsg_ctrldev_open,
> - .release = rpmsg_ctrldev_release,
> - .unlocked_ioctl = rpmsg_ctrldev_ioctl,
> - .compat_ioctl = compat_ptr_ioctl,
> -};
> -
> -static void rpmsg_ctrldev_release_device(struct device *dev)
> -{
> - struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev);
> -
> - ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
> - ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
> - cdev_del(&ctrldev->cdev);
> - kfree(ctrldev);
> -}
> -
> -static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
> -{
> - struct rpmsg_ctrldev *ctrldev;
> - struct device *dev;
> - int ret;
> -
> - ctrldev = kzalloc(sizeof(*ctrldev), GFP_KERNEL);
> - if (!ctrldev)
> - return -ENOMEM;
> -
> - ctrldev->rpdev = rpdev;
> -
> - dev = &ctrldev->dev;
> - device_initialize(dev);
> - dev->parent = &rpdev->dev;
> - dev->class = rpmsg_class;
> -
> - cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
> - ctrldev->cdev.owner = THIS_MODULE;
> -
> - ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL);
> - if (ret < 0)
> - goto free_ctrldev;
> - dev->devt = MKDEV(MAJOR(rpmsg_major), ret);
> -
> - ret = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL);
> - if (ret < 0)
> - goto free_minor_ida;
> - dev->id = ret;
> - dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret);
> -
> - ret = cdev_add(&ctrldev->cdev, dev->devt, 1);
> - if (ret)
> - goto free_ctrl_ida;
> -
> - /* We can now rely on the release function for cleanup */
> - dev->release = rpmsg_ctrldev_release_device;
> -
> - ret = device_add(dev);
> - if (ret) {
> - dev_err(&rpdev->dev, "device_add failed: %d\n", ret);
> - put_device(dev);
> - }
> -
> - dev_set_drvdata(&rpdev->dev, ctrldev);
> -
> - return ret;
> -
> -free_ctrl_ida:
> - ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
> -free_minor_ida:
> - ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
> -free_ctrldev:
> - put_device(dev);
> - kfree(ctrldev);
> -
> - return ret;
> -}
> -
> -static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
> -{
> - struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev);
> - int ret;
> -
> - /* Destroy all endpoints */
> - ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
> - if (ret)
> - dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
> -
> - device_del(&ctrldev->dev);
> - put_device(&ctrldev->dev);
> -}
> -
> -static struct rpmsg_driver rpmsg_chrdev_driver = {
> - .probe = rpmsg_chrdev_probe,
> - .remove = rpmsg_chrdev_remove,
> - .drv = {
> - .name = "rpmsg_chrdev",
> - },
> -};
> -
> static int rpmsg_chrdev_init(void)
> {
> int ret;
>
> - ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg");
> - if (ret < 0) {
> + ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char");
> + if (ret < 0)
> pr_err("rpmsg: failed to allocate char dev region\n");
> - return ret;
> - }
> -
> - rpmsg_class = class_create(THIS_MODULE, "rpmsg");
> - if (IS_ERR(rpmsg_class)) {
> - pr_err("failed to create rpmsg class\n");
> - unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> - return PTR_ERR(rpmsg_class);
> - }
> -
> - ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
> - if (ret < 0) {
> - pr_err("rpmsgchr: failed to register rpmsg driver\n");
> - class_destroy(rpmsg_class);
> - unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> - }
>
> return ret;
> }
> @@ -579,8 +404,6 @@ postcore_initcall(rpmsg_chrdev_init);
>
> static void rpmsg_chrdev_exit(void)
> {
> - unregister_rpmsg_driver(&rpmsg_chrdev_driver);
> - class_destroy(rpmsg_class);
> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> }
> module_exit(rpmsg_chrdev_exit);
> diff --git a/drivers/rpmsg/rpmsg_char.h b/drivers/rpmsg/rpmsg_char.h
> index 379d2ae2bee8..f20a215073c3 100644
> --- a/drivers/rpmsg/rpmsg_char.h
> +++ b/drivers/rpmsg/rpmsg_char.h
> @@ -6,6 +6,8 @@
> #ifndef __RPMSG_CHRDEV_H__
> #define __RPMSG_CHRDEV_H__
>
> +#define RPMSG_DEV_MAX (MINORMASK + 1)
> +
> #if IS_REACHABLE(CONFIG_RPMSG_CHAR)
> /**
> * rpmsg_chrdev_create_eptdev() - register char device based on an endpoint
> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
> new file mode 100644
> index 000000000000..a5bb9ed97f32
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_ctrl.c
> @@ -0,0 +1,231 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2021, STMicroelectronics
> + * Copyright (c) 2016, Linaro Ltd.
> + * Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
> + * Copyright (c) 2012, PetaLogix
> + * Copyright (c) 2011, Texas Instruments, Inc.
> + * Copyright (c) 2011, Google, Inc.
> + *
> + * Based on rpmsg performance statistics driver by Michal Simek, which in turn
> + * was based on TI & Google OMX rpmsg driver.
> + */
> +#include <linux/cdev.h>
> +#include <linux/device.h>
> +#include <linux/fs.h>
> +#include <linux/idr.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/rpmsg.h>
> +#include <linux/slab.h>
> +#include <uapi/linux/rpmsg.h>
> +
> +#include "rpmsg_char.h"
> +#include "rpmsg_internal.h"
> +
> +static dev_t rpmsg_major;
> +struct class *rpmsg_class;
> +
> +static DEFINE_IDA(rpmsg_ctrl_ida);
> +static DEFINE_IDA(rpmsg_minor_ida);
> +
> +#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrldev, dev)
> +#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrldev, cdev)
> +
> +/**
> + * struct rpmsg_ctrldev - control device for instantiating endpoint devices
> + * @rpdev: underlaying rpmsg device
> + * @cdev: cdev for the ctrl device
> + * @dev: device for the ctrl device
> + */
> +struct rpmsg_ctrldev {
> + struct rpmsg_device *rpdev;
> + struct cdev cdev;
> + struct device dev;
> +};
> +
> +static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
> +{
> + struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
> +
> + get_device(&ctrldev->dev);
> + filp->private_data = ctrldev;
> +
> + return 0;
> +}
> +
> +static int rpmsg_ctrldev_release(struct inode *inode, struct file *filp)
> +{
> + struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
> +
> + put_device(&ctrldev->dev);
> +
> + return 0;
> +}
> +
> +static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
> + unsigned long arg)
> +{
> + struct rpmsg_ctrldev *ctrldev = fp->private_data;
> + void __user *argp = (void __user *)arg;
> + struct rpmsg_endpoint_info eptinfo;
> + struct rpmsg_channel_info chinfo;
> +
> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
> + return -EINVAL;
> +
> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
> + return -EFAULT;
> +
> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
> + chinfo.src = eptinfo.src;
> + chinfo.dst = eptinfo.dst;
> +
> + return rpmsg_chrdev_create_eptdev(ctrldev->rpdev, &ctrldev->dev, chinfo, rpmsg_class);
> +};
> +
> +static const struct file_operations rpmsg_ctrldev_fops = {
> + .owner = THIS_MODULE,
> + .open = rpmsg_ctrldev_open,
> + .release = rpmsg_ctrldev_release,
> + .unlocked_ioctl = rpmsg_ctrldev_ioctl,
> + .compat_ioctl = compat_ptr_ioctl,
> +};
> +
> +static void rpmsg_ctrldev_release_device(struct device *dev)
> +{
> + struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev);
> +
> + ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
> + ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
> + cdev_del(&ctrldev->cdev);
> + kfree(ctrldev);
> +}
> +
> +static int rpmsg_ctrldev_probe(struct rpmsg_device *rpdev)
> +{
> + struct rpmsg_ctrldev *ctrldev;
> + struct device *dev;
> + int ret;
> +
> + ctrldev = kzalloc(sizeof(*ctrldev), GFP_KERNEL);
> + if (!ctrldev)
> + return -ENOMEM;
> +
> + ctrldev->rpdev = rpdev;
> +
> + dev = &ctrldev->dev;
> + device_initialize(dev);
> + dev->parent = &rpdev->dev;
> + dev->class = rpmsg_class;
> +
> + cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
> + ctrldev->cdev.owner = THIS_MODULE;
> +
> + ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL);
> + if (ret < 0)
> + goto free_ctrldev;
> + dev->devt = MKDEV(MAJOR(rpmsg_major), ret);
> +
> + ret = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL);
> + if (ret < 0)
> + goto free_minor_ida;
> + dev->id = ret;
> + dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret);
> +
> + ret = cdev_add(&ctrldev->cdev, dev->devt, 1);
> + if (ret)
> + goto free_ctrl_ida;
> +
> + /* We can now rely on the release function for cleanup */
> + dev->release = rpmsg_ctrldev_release_device;
> +
> + ret = device_add(dev);
> + if (ret) {
> + dev_err(&rpdev->dev, "device_add failed: %d\n", ret);
> + put_device(dev);
> + }
> +
> + dev_set_drvdata(&rpdev->dev, ctrldev);
> +
> + return ret;
> +
> +free_ctrl_ida:
> + ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
> +free_minor_ida:
> + ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
> +free_ctrldev:
> + put_device(dev);
> + kfree(ctrldev);
> +
> + return ret;
> +}
> +
> +static void rpmsg_ctrldev_remove(struct rpmsg_device *rpdev)
> +{
> + struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev);
> + int ret;
> +
> + /* Destroy all endpoints */
> + ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
> + if (ret)
> + dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
> +
> + device_del(&ctrldev->dev);
> + put_device(&ctrldev->dev);
> +}
> +
> +static struct rpmsg_driver rpmsg_ctrldev_driver = {
> + .probe = rpmsg_ctrldev_probe,
> + .remove = rpmsg_ctrldev_remove,
> + .drv = {
> + .name = "rpmsg_chrdev",
> + },
> +};
> +
> +static int rpmsg_ctrldev_init(void)
> +{
> + int ret;
> +
> + ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_ctrl");
> + if (ret < 0) {
> + pr_err("rpmsg: failed to allocate char dev region\n");
> + return ret;
> + }
> +
> + rpmsg_class = class_create(THIS_MODULE, "rpmsg");
This class thing really bothers me. Keeping this here means that rpmsg_eptdevs
created from user space will be associated to this rpmsg_class but those created
from the name service won't. As such I propose to move this to rpmsg_char and
simply not associate the control device to the class.
Otherwise we'd have to introduce some mechanic only to deal with the creation of
the class and I don't think it is worth. We can revise that approach if someone
complains we broke their user space.
> + if (IS_ERR(rpmsg_class)) {
> + pr_err("failed to create rpmsg class\n");
> + ret = PTR_ERR(rpmsg_class);
> + goto free_region;
> + }
> +
> + ret = register_rpmsg_driver(&rpmsg_ctrldev_driver);
> + if (ret < 0) {
> + pr_err("rpmsg ctrl: failed to register rpmsg driver\n");
> + goto free_class;
> + }
> +
> + return 0;
> +
> +free_class:
> + class_destroy(rpmsg_class);
> +free_region:
> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> +
> + return ret;
> +}
> +postcore_initcall(rpmsg_ctrldev_init);
> +
> +static void rpmsg_ctrldev_exit(void)
> +{
> + unregister_rpmsg_driver(&rpmsg_ctrldev_driver);
> + class_destroy(rpmsg_class);
> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> +}
> +module_exit(rpmsg_ctrldev_exit);
> +
> +MODULE_DESCRIPTION("rpmsg control interface");
> +MODULE_ALIAS("rpmsg:" KBUILD_MODNAME);
> +MODULE_LICENSE("GPL v2");
> --
> 2.17.1
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/7] rpmsg: Update rpmsg_chrdev_register_device function
2021-04-13 13:44 ` [PATCH v2 3/7] rpmsg: Update rpmsg_chrdev_register_device function Arnaud Pouliquen
@ 2021-04-21 18:06 ` Mathieu Poirier
0 siblings, 0 replies; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-21 18:06 UTC (permalink / raw)
To: Arnaud Pouliquen
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On Tue, Apr 13, 2021 at 03:44:54PM +0200, Arnaud Pouliquen wrote:
> The rpmsg_chrdev driver has been replaced by the rpmsg_ctrl driver
> for the /dev/rpmsg_ctrlX devices management. The reference for the
> driver override is now the rpmsg_ctrl.
>
> Update the rpmsg_chrdev_register_device function to reflect the update,
> and rename the function to use the rpmsg_ctrldev prefix.
>
> The platform drivers are updated accordingly.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>
> ---
> update from v1
> - move the rename of the rpmsg_ctrl driver from previous patch to
> this one.
> ---
> drivers/rpmsg/qcom_glink_native.c | 2 +-
> drivers/rpmsg/qcom_smd.c | 2 +-
> drivers/rpmsg/rpmsg_ctrl.c | 2 +-
> drivers/rpmsg/rpmsg_internal.h | 8 ++++----
> drivers/rpmsg/virtio_rpmsg_bus.c | 2 +-
> 5 files changed, 8 insertions(+), 8 deletions(-)
>
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
> index 05533c71b10e..7d7e809800ec 100644
> --- a/drivers/rpmsg/qcom_glink_native.c
> +++ b/drivers/rpmsg/qcom_glink_native.c
> @@ -1642,7 +1642,7 @@ static int qcom_glink_create_chrdev(struct qcom_glink *glink)
> rpdev->dev.parent = glink->dev;
> rpdev->dev.release = qcom_glink_device_release;
>
> - return rpmsg_chrdev_register_device(rpdev);
> + return rpmsg_ctrldev_register_device(rpdev);
> }
>
> struct qcom_glink *qcom_glink_native_probe(struct device *dev,
> diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
> index 8da1b5cb31b3..d223e438d17c 100644
> --- a/drivers/rpmsg/qcom_smd.c
> +++ b/drivers/rpmsg/qcom_smd.c
> @@ -1113,7 +1113,7 @@ static int qcom_smd_create_chrdev(struct qcom_smd_edge *edge)
> qsdev->rpdev.dev.parent = &edge->dev;
> qsdev->rpdev.dev.release = qcom_smd_release_device;
>
> - return rpmsg_chrdev_register_device(&qsdev->rpdev);
> + return rpmsg_ctrldev_register_device(&qsdev->rpdev);
> }
>
> /*
> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
> index a5bb9ed97f32..059c228d0045 100644
> --- a/drivers/rpmsg/rpmsg_ctrl.c
> +++ b/drivers/rpmsg/rpmsg_ctrl.c
> @@ -180,7 +180,7 @@ static struct rpmsg_driver rpmsg_ctrldev_driver = {
> .probe = rpmsg_ctrldev_probe,
> .remove = rpmsg_ctrldev_remove,
> .drv = {
> - .name = "rpmsg_chrdev",
> + .name = "rpmsg_ctrl",
> },
> };
>
> diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
> index a76c344253bf..8c500a8f29aa 100644
> --- a/drivers/rpmsg/rpmsg_internal.h
> +++ b/drivers/rpmsg/rpmsg_internal.h
> @@ -82,16 +82,16 @@ struct rpmsg_device *rpmsg_create_channel(struct rpmsg_device *rpdev,
> int rpmsg_release_channel(struct rpmsg_device *rpdev,
> struct rpmsg_channel_info *chinfo);
> /**
> - * rpmsg_chrdev_register_device() - register chrdev device based on rpdev
> + * rpmsg_ctrl_register_device() - register a char device for control based on rpdev
> * @rpdev: prepared rpdev to be used for creating endpoints
> *
> * This function wraps rpmsg_register_device() preparing the rpdev for use as
> * basis for the rpmsg chrdev.
> */
> -static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev)
> +static inline int rpmsg_ctrldev_register_device(struct rpmsg_device *rpdev)
> {
> - strcpy(rpdev->id.name, "rpmsg_chrdev");
> - rpdev->driver_override = "rpmsg_chrdev";
> + strcpy(rpdev->id.name, "rpmsg_ctrl");
> + rpdev->driver_override = "rpmsg_ctrl";
>
> return rpmsg_register_device(rpdev);
> }
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
> index 8e49a3bacfc7..e42234a3e2ab 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -840,7 +840,7 @@ static struct rpmsg_device *rpmsg_virtio_add_ctrl_dev(struct virtio_device *vdev
> rpdev_ctrl->dev.release = virtio_rpmsg_release_device;
> rpdev_ctrl->little_endian = virtio_is_little_endian(vrp->vdev);
>
> - err = rpmsg_chrdev_register_device(rpdev_ctrl);
> + err = rpmsg_ctrldev_register_device(rpdev_ctrl);
> if (err) {
> kfree(vch);
> return ERR_PTR(err);
> --
> 2.17.1
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions
2021-04-21 17:52 ` Mathieu Poirier
@ 2021-04-22 7:55 ` Arnaud POULIQUEN
2021-04-22 16:29 ` Mathieu Poirier
0 siblings, 1 reply; 23+ messages in thread
From: Arnaud POULIQUEN @ 2021-04-22 7:55 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
hello Mathieu
On 4/21/21 7:52 PM, Mathieu Poirier wrote:
> On Tue, Apr 13, 2021 at 03:44:52PM +0200, Arnaud Pouliquen wrote:
>> To prepare the split of the code related to the control (ctrldev)
>> and the endpoint (eptdev) devices in 2 separate files:
>>
>> - Rename and export the functions in rpmsg_char.h.
>>
>> - Suppress the dependency with the rpmsg_ctrldev struct in the
>> rpmsg_chrdev_create_eptdev function.
>>
>> - The rpmsg class is provided as parameter in rpmsg_chrdev_create_eptdev,
>> because the class is associated to the control part.
>>
>> Suggested-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>> ---
>> drivers/rpmsg/rpmsg_char.c | 19 +++++++++------
>> drivers/rpmsg/rpmsg_char.h | 50 ++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 61 insertions(+), 8 deletions(-)
>> create mode 100644 drivers/rpmsg/rpmsg_char.h
>>
>> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
>> index 2bebc9b2d163..b9df8dc4365f 100644
>> --- a/drivers/rpmsg/rpmsg_char.c
>> +++ b/drivers/rpmsg/rpmsg_char.c
>> @@ -1,5 +1,6 @@
>> // SPDX-License-Identifier: GPL-2.0
>> /*
>> + * Copyright (C) 2021, STMicroelectronics
>> * Copyright (c) 2016, Linaro Ltd.
>> * Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
>> * Copyright (c) 2012, PetaLogix
>> @@ -22,6 +23,7 @@
>> #include <linux/uaccess.h>
>> #include <uapi/linux/rpmsg.h>
>>
>> +#include "rpmsg_char.h"
>> #include "rpmsg_internal.h"
>>
>> #define RPMSG_DEV_MAX (MINORMASK + 1)
>> @@ -78,7 +80,7 @@ struct rpmsg_eptdev {
>> wait_queue_head_t readq;
>> };
>>
>> -static int rpmsg_eptdev_destroy(struct device *dev, void *data)
>> +int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data)
>
> Shouldn't this be rpmsg_chrdev_eptdev_destroy()? I've been wondering about the
> flipping of destroy and eptdev... The same for rpmsg_chrdev_create_eptdev().
As the function is exported i prefered to follow name srtructure that is
commonly used: <module>_<action>_<object>
But it is not a rule, so please just tell me if you prefer that i rename the
functions rpmsg_chrdev_eptdev_xxxx?
Thanks,
Arnaud
>
> With that:
>
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
>> {
>> struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
>>
>> @@ -97,6 +99,7 @@ static int rpmsg_eptdev_destroy(struct device *dev, void *data)
>>
>> return 0;
>> }
>> +EXPORT_SYMBOL(rpmsg_chrdev_destroy_eptdev);
>>
>> static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
>> void *priv, u32 addr)
>> @@ -280,7 +283,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
>> if (cmd != RPMSG_DESTROY_EPT_IOCTL)
>> return -EINVAL;
>>
>> - return rpmsg_eptdev_destroy(&eptdev->dev, NULL);
>> + return rpmsg_chrdev_destroy_eptdev(&eptdev->dev, NULL);
>> }
>>
>> static const struct file_operations rpmsg_eptdev_fops = {
>> @@ -339,10 +342,9 @@ static void rpmsg_eptdev_release_device(struct device *dev)
>> kfree(eptdev);
>> }
>>
>> -static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
>> - struct rpmsg_channel_info chinfo)
>> +int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
>> + struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
>> {
>> - struct rpmsg_device *rpdev = ctrldev->rpdev;
>> struct rpmsg_eptdev *eptdev;
>> struct device *dev;
>> int ret;
>> @@ -362,7 +364,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
>>
>> device_initialize(dev);
>> dev->class = rpmsg_class;
>> - dev->parent = &ctrldev->dev;
>> + dev->parent = parent;
>> dev->groups = rpmsg_eptdev_groups;
>> dev_set_drvdata(dev, eptdev);
>>
>> @@ -405,6 +407,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
>>
>> return ret;
>> }
>> +EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>>
>> static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
>> {
>> @@ -444,7 +447,7 @@ static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
>> chinfo.src = eptinfo.src;
>> chinfo.dst = eptinfo.dst;
>>
>> - return rpmsg_eptdev_create(ctrldev, chinfo);
>> + return rpmsg_chrdev_create_eptdev(ctrldev->rpdev, &ctrldev->dev, chinfo, rpmsg_class);
>> };
>>
>> static const struct file_operations rpmsg_ctrldev_fops = {
>> @@ -530,7 +533,7 @@ static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
>> int ret;
>>
>> /* Destroy all endpoints */
>> - ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_eptdev_destroy);
>> + ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
>> if (ret)
>> dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
>>
>> diff --git a/drivers/rpmsg/rpmsg_char.h b/drivers/rpmsg/rpmsg_char.h
>> new file mode 100644
>> index 000000000000..379d2ae2bee8
>> --- /dev/null
>> +++ b/drivers/rpmsg/rpmsg_char.h
>> @@ -0,0 +1,50 @@
>> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> +/*
>> + * Copyright (C) STMicroelectronics 2021.
>> + */
>> +
>> +#ifndef __RPMSG_CHRDEV_H__
>> +#define __RPMSG_CHRDEV_H__
>> +
>> +#if IS_REACHABLE(CONFIG_RPMSG_CHAR)
>> +/**
>> + * rpmsg_chrdev_create_eptdev() - register char device based on an endpoint
>> + * @rpdev: prepared rpdev to be used for creating endpoints
>> + * @parent: parent device
>> + * @chinfo: assiated endpoint channel information.
>> + *
>> + * This function create a new rpmsg char endpoint device to instantiate a new
>> + * endpoint based on chinfo information.
>> + */
>> +int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
>> + struct rpmsg_channel_info chinfo, struct class *rpmsg_class);
>> +
>> +/**
>> + * rpmsg_chrdev_destroy_eptdev() - destroy created char device endpoint.
>> + * @data: private data associated to the endpoint device
>> + *
>> + * This function destroys a rpmsg char endpoint device created by the RPMSG_DESTROY_EPT_IOCTL
>> + * control.
>> + */
>> +int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data);
>> +
>> +#else /*IS_REACHABLE(CONFIG_RPMSG_CHAR) */
>> +
>> +static inline int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
>> + struct rpmsg_channel_info chinfo,
>> + struct class *rpmsg_class)
>> +{
>> + return -EINVAL;
>> +}
>> +
>> +static inline int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data)
>> +{
>> + /* This shouldn't be possible */
>> + WARN_ON(1);
>> +
>> + return 0;
>> +}
>> +
>> +#endif /*IS_REACHABLE(CONFIG_RPMSG_CHAR) */
>> +
>> +#endif /*__RPMSG_CHRDEV_H__ */
>> --
>> 2.17.1
>>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl
2021-04-21 18:04 ` Mathieu Poirier
@ 2021-04-22 7:56 ` Arnaud POULIQUEN
2021-04-22 16:32 ` Mathieu Poirier
0 siblings, 1 reply; 23+ messages in thread
From: Arnaud POULIQUEN @ 2021-04-22 7:56 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On 4/21/21 8:04 PM, Mathieu Poirier wrote:
> On Tue, Apr 13, 2021 at 03:44:53PM +0200, Arnaud Pouliquen wrote:
>> Create the rpmsg_ctrl.c module and move the code related to the
>> rpmsg_ctrldev device in this new module.
>>
>> Add the dependency between rpmsg_char and rpmsg_ctrl in the
>> kconfig file.
>>
>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>> ---
>> update from v1:
>> - keep "rpmsg_chrdev" driver name in rpmsg_ctrl, driver will be renamed
>> in next path that renames the rpmsg_chrdev_create_eptdev.
>> - rename the chardev regions
>> - move RPMSG_DEV_MAX to rpmsg_char.h
>> ---
>> drivers/rpmsg/Kconfig | 9 ++
>> drivers/rpmsg/Makefile | 1 +
>> drivers/rpmsg/rpmsg_char.c | 181 +----------------------------
>> drivers/rpmsg/rpmsg_char.h | 2 +
>> drivers/rpmsg/rpmsg_ctrl.c | 231 +++++++++++++++++++++++++++++++++++++
>> 5 files changed, 245 insertions(+), 179 deletions(-)
>> create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
>>
>> diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
>> index 0b4407abdf13..d822ec9ec692 100644
>> --- a/drivers/rpmsg/Kconfig
snip[...]
>> +static int rpmsg_ctrldev_init(void)
>> +{
>> + int ret;
>> +
>> + ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_ctrl");
>> + if (ret < 0) {
>> + pr_err("rpmsg: failed to allocate char dev region\n");
>> + return ret;
>> + }
>> +
>> + rpmsg_class = class_create(THIS_MODULE, "rpmsg");
>
> This class thing really bothers me. Keeping this here means that rpmsg_eptdevs
> created from user space will be associated to this rpmsg_class but those created
> from the name service won't. As such I propose to move this to rpmsg_char and
> simply not associate the control device to the class.
>
> Otherwise we'd have to introduce some mechanic only to deal with the creation of
> the class and I don't think it is worth. We can revise that approach if someone
> complains we broke their user space.
I agree with that as it was my first proposed approach here [1]
[1] https://www.spinics.net/lists/linux-arm-msm/msg81194.html
Thanks,
Arnaud
>
>
>> + if (IS_ERR(rpmsg_class)) {
>> + pr_err("failed to create rpmsg class\n");
>> + ret = PTR_ERR(rpmsg_class);
>> + goto free_region;
>> + }
>> +
>> + ret = register_rpmsg_driver(&rpmsg_ctrldev_driver);
>> + if (ret < 0) {
>> + pr_err("rpmsg ctrl: failed to register rpmsg driver\n");
>> + goto free_class;
>> + }
>> +
>> + return 0;
>> +
>> +free_class:
>> + class_destroy(rpmsg_class);
>> +free_region:
>> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>> +
>> + return ret;
>> +}
>> +postcore_initcall(rpmsg_ctrldev_init);
>> +
>> +static void rpmsg_ctrldev_exit(void)
>> +{
>> + unregister_rpmsg_driver(&rpmsg_ctrldev_driver);
>> + class_destroy(rpmsg_class);
>> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>> +}
>> +module_exit(rpmsg_ctrldev_exit);
>> +
>> +MODULE_DESCRIPTION("rpmsg control interface");
>> +MODULE_ALIAS("rpmsg:" KBUILD_MODNAME);
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.17.1
>>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device
2021-04-21 17:40 ` Mathieu Poirier
@ 2021-04-22 7:58 ` Arnaud POULIQUEN
2021-04-22 16:36 ` Mathieu Poirier
0 siblings, 1 reply; 23+ messages in thread
From: Arnaud POULIQUEN @ 2021-04-22 7:58 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On 4/21/21 7:40 PM, Mathieu Poirier wrote:
> Good day Arnaud,
>
> On Tue, Apr 13, 2021 at 03:44:56PM +0200, Arnaud Pouliquen wrote:
>> A rpmsg char device allows to probe the endpoint device on a remote name
>> service announcement.
>>
>> With this patch the /dev/rpmsgX interface is created either by a user
>> application or by the remote firmware.
>>
>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>>
>> ---
>> update from V1:
>> - add missing unregister_rpmsg_driver call on module exit.
>>
>> ---
>> drivers/rpmsg/rpmsg_char.c | 59 +++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 58 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
>> index a64249d83172..4606787b7011 100644
>> --- a/drivers/rpmsg/rpmsg_char.c
>> +++ b/drivers/rpmsg/rpmsg_char.c
>> @@ -26,6 +26,8 @@
>> #include "rpmsg_char.h"
>> #include "rpmsg_internal.h"
>>
>> +#define RPMSG_CHAR_DEVNAME "rpmsg-raw"
>> +
>
> Why not simply call it rpmsg-char?
I would avoid to link the rpmsg name service to the Linux Kernel device.
>
>> static dev_t rpmsg_major;
>>
>> static DEFINE_IDA(rpmsg_ept_ida);
>> @@ -403,13 +405,67 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
>> }
>> EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>>
>> +static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
>> +{
>> + struct rpmsg_channel_info chinfo;
>> + struct rpmsg_eptdev *eptdev;
>> +
>> + if (!rpdev->ept)
>> + return -EINVAL;
>> +
>> + memcpy(chinfo.name, RPMSG_CHAR_DEVNAME, sizeof(RPMSG_CHAR_DEVNAME));
>> + chinfo.src = rpdev->src;
>> + chinfo.dst = rpdev->dst;
>> +
>> + eptdev = __rpmsg_chrdev_create_eptdev(rpdev, &rpdev->dev, chinfo, NULL);
>> + if (IS_ERR(eptdev))
>> + return PTR_ERR(eptdev);
>> +
>> + /* Set the private field of the default endpoint to retrieve context on callback. */
>> + rpdev->ept->priv = eptdev;
>
> This is already done in rpmsg_create_ept() when rpmsg_eptdev_open() is called.
>
>> +
>> + return 0;
>> +}
>> +
>> +static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
>> +{
>> + int ret;
>> +
>> + ret = device_for_each_child(&rpdev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
>> + if (ret)
>> + dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret);
>> +}
>> +
>> +static struct rpmsg_device_id rpmsg_chrdev_id_table[] = {
>> + { .name = RPMSG_CHAR_DEVNAME },
>> + { },
>> +};
>> +
>> +static struct rpmsg_driver rpmsg_chrdev_driver = {
>> + .probe = rpmsg_chrdev_probe,
>> + .remove = rpmsg_chrdev_remove,
>> + .id_table = rpmsg_chrdev_id_table,
>> + .callback = rpmsg_ept_cb,
>
> Not sure why we need a callback associated to this driver when
> rpmsg_eptdev_open() already creates and rpmsg_endpoint. To me the only thing
> having a callback provides is the association between the rpmsg_device and the
> rpmsg_endpoint[1] that happens in rpmsg_dev_probe(). The QC folks already do
> this association in their platform code[2]. Since this is not done in
> __rpmsg_create_ept() a check for rpdev->ept == NULL could be done in
> rpmsg_eptdev_open() and do the assignment there.
>
> [1]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/rpmsg_core.c#L513
> [2]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/qcom_glink_native.c#L1623
>
That's a good point! When I started the redesign, I faced some issues with the
approach you propose. But as I can not remember the reason and because the code
has evolved, i need to re-think about this.
Thanks,
Arnaud
>> + .drv = {
>> + .name = "rpmsg_chrdev",
>> + },
>> +};
>> +
>> static int rpmsg_chrdev_init(void)
>> {
>> int ret;
>>
>> ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char");
>> - if (ret < 0)
>> + if (ret < 0) {
>> pr_err("rpmsg: failed to allocate char dev region\n");
>> + return ret;
>> + }
>> +
>> + ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
>> + if (ret < 0) {
>> + pr_err("rpmsg: failed to register rpmsg raw driver\n");
>> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>> + }
>>
>> return ret;
>> }
>> @@ -417,6 +473,7 @@ postcore_initcall(rpmsg_chrdev_init);
>>
>> static void rpmsg_chrdev_exit(void)
>> {
>> + unregister_rpmsg_driver(&rpmsg_chrdev_driver);
>> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>> }
>> module_exit(rpmsg_chrdev_exit);
>> --
>> 2.17.1
>>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions
2021-04-22 7:55 ` Arnaud POULIQUEN
@ 2021-04-22 16:29 ` Mathieu Poirier
0 siblings, 0 replies; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-22 16:29 UTC (permalink / raw)
To: Arnaud POULIQUEN
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On Thu, Apr 22, 2021 at 09:55:47AM +0200, Arnaud POULIQUEN wrote:
> hello Mathieu
>
> On 4/21/21 7:52 PM, Mathieu Poirier wrote:
> > On Tue, Apr 13, 2021 at 03:44:52PM +0200, Arnaud Pouliquen wrote:
> >> To prepare the split of the code related to the control (ctrldev)
> >> and the endpoint (eptdev) devices in 2 separate files:
> >>
> >> - Rename and export the functions in rpmsg_char.h.
> >>
> >> - Suppress the dependency with the rpmsg_ctrldev struct in the
> >> rpmsg_chrdev_create_eptdev function.
> >>
> >> - The rpmsg class is provided as parameter in rpmsg_chrdev_create_eptdev,
> >> because the class is associated to the control part.
> >>
> >> Suggested-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> >> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> >> ---
> >> drivers/rpmsg/rpmsg_char.c | 19 +++++++++------
> >> drivers/rpmsg/rpmsg_char.h | 50 ++++++++++++++++++++++++++++++++++++++
> >> 2 files changed, 61 insertions(+), 8 deletions(-)
> >> create mode 100644 drivers/rpmsg/rpmsg_char.h
> >>
> >> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> >> index 2bebc9b2d163..b9df8dc4365f 100644
> >> --- a/drivers/rpmsg/rpmsg_char.c
> >> +++ b/drivers/rpmsg/rpmsg_char.c
> >> @@ -1,5 +1,6 @@
> >> // SPDX-License-Identifier: GPL-2.0
> >> /*
> >> + * Copyright (C) 2021, STMicroelectronics
> >> * Copyright (c) 2016, Linaro Ltd.
> >> * Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
> >> * Copyright (c) 2012, PetaLogix
> >> @@ -22,6 +23,7 @@
> >> #include <linux/uaccess.h>
> >> #include <uapi/linux/rpmsg.h>
> >>
> >> +#include "rpmsg_char.h"
> >> #include "rpmsg_internal.h"
> >>
> >> #define RPMSG_DEV_MAX (MINORMASK + 1)
> >> @@ -78,7 +80,7 @@ struct rpmsg_eptdev {
> >> wait_queue_head_t readq;
> >> };
> >>
> >> -static int rpmsg_eptdev_destroy(struct device *dev, void *data)
> >> +int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data)
> >
> > Shouldn't this be rpmsg_chrdev_eptdev_destroy()? I've been wondering about the
> > flipping of destroy and eptdev... The same for rpmsg_chrdev_create_eptdev().
>
> As the function is exported i prefered to follow name srtructure that is
> commonly used: <module>_<action>_<object>
>
> But it is not a rule, so please just tell me if you prefer that i rename the
> functions rpmsg_chrdev_eptdev_xxxx?
I'd prefer rpmsg_chrdev_eptdev_create/destroy() since we are already familiar
with that terminology.
>
> Thanks,
> Arnaud
>
> >
> > With that:
> >
> > Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> >
> >> {
> >> struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
> >>
> >> @@ -97,6 +99,7 @@ static int rpmsg_eptdev_destroy(struct device *dev, void *data)
> >>
> >> return 0;
> >> }
> >> +EXPORT_SYMBOL(rpmsg_chrdev_destroy_eptdev);
> >>
> >> static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
> >> void *priv, u32 addr)
> >> @@ -280,7 +283,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
> >> if (cmd != RPMSG_DESTROY_EPT_IOCTL)
> >> return -EINVAL;
> >>
> >> - return rpmsg_eptdev_destroy(&eptdev->dev, NULL);
> >> + return rpmsg_chrdev_destroy_eptdev(&eptdev->dev, NULL);
> >> }
> >>
> >> static const struct file_operations rpmsg_eptdev_fops = {
> >> @@ -339,10 +342,9 @@ static void rpmsg_eptdev_release_device(struct device *dev)
> >> kfree(eptdev);
> >> }
> >>
> >> -static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
> >> - struct rpmsg_channel_info chinfo)
> >> +int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> >> + struct rpmsg_channel_info chinfo, struct class *rpmsg_class)
> >> {
> >> - struct rpmsg_device *rpdev = ctrldev->rpdev;
> >> struct rpmsg_eptdev *eptdev;
> >> struct device *dev;
> >> int ret;
> >> @@ -362,7 +364,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
> >>
> >> device_initialize(dev);
> >> dev->class = rpmsg_class;
> >> - dev->parent = &ctrldev->dev;
> >> + dev->parent = parent;
> >> dev->groups = rpmsg_eptdev_groups;
> >> dev_set_drvdata(dev, eptdev);
> >>
> >> @@ -405,6 +407,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
> >>
> >> return ret;
> >> }
> >> +EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
> >>
> >> static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
> >> {
> >> @@ -444,7 +447,7 @@ static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
> >> chinfo.src = eptinfo.src;
> >> chinfo.dst = eptinfo.dst;
> >>
> >> - return rpmsg_eptdev_create(ctrldev, chinfo);
> >> + return rpmsg_chrdev_create_eptdev(ctrldev->rpdev, &ctrldev->dev, chinfo, rpmsg_class);
> >> };
> >>
> >> static const struct file_operations rpmsg_ctrldev_fops = {
> >> @@ -530,7 +533,7 @@ static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
> >> int ret;
> >>
> >> /* Destroy all endpoints */
> >> - ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_eptdev_destroy);
> >> + ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
> >> if (ret)
> >> dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
> >>
> >> diff --git a/drivers/rpmsg/rpmsg_char.h b/drivers/rpmsg/rpmsg_char.h
> >> new file mode 100644
> >> index 000000000000..379d2ae2bee8
> >> --- /dev/null
> >> +++ b/drivers/rpmsg/rpmsg_char.h
> >> @@ -0,0 +1,50 @@
> >> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> >> +/*
> >> + * Copyright (C) STMicroelectronics 2021.
> >> + */
> >> +
> >> +#ifndef __RPMSG_CHRDEV_H__
> >> +#define __RPMSG_CHRDEV_H__
> >> +
> >> +#if IS_REACHABLE(CONFIG_RPMSG_CHAR)
> >> +/**
> >> + * rpmsg_chrdev_create_eptdev() - register char device based on an endpoint
> >> + * @rpdev: prepared rpdev to be used for creating endpoints
> >> + * @parent: parent device
> >> + * @chinfo: assiated endpoint channel information.
> >> + *
> >> + * This function create a new rpmsg char endpoint device to instantiate a new
> >> + * endpoint based on chinfo information.
> >> + */
> >> +int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> >> + struct rpmsg_channel_info chinfo, struct class *rpmsg_class);
> >> +
> >> +/**
> >> + * rpmsg_chrdev_destroy_eptdev() - destroy created char device endpoint.
> >> + * @data: private data associated to the endpoint device
> >> + *
> >> + * This function destroys a rpmsg char endpoint device created by the RPMSG_DESTROY_EPT_IOCTL
> >> + * control.
> >> + */
> >> +int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data);
> >> +
> >> +#else /*IS_REACHABLE(CONFIG_RPMSG_CHAR) */
> >> +
> >> +static inline int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent,
> >> + struct rpmsg_channel_info chinfo,
> >> + struct class *rpmsg_class)
> >> +{
> >> + return -EINVAL;
> >> +}
> >> +
> >> +static inline int rpmsg_chrdev_destroy_eptdev(struct device *dev, void *data)
> >> +{
> >> + /* This shouldn't be possible */
> >> + WARN_ON(1);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +#endif /*IS_REACHABLE(CONFIG_RPMSG_CHAR) */
> >> +
> >> +#endif /*__RPMSG_CHRDEV_H__ */
> >> --
> >> 2.17.1
> >>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl
2021-04-22 7:56 ` Arnaud POULIQUEN
@ 2021-04-22 16:32 ` Mathieu Poirier
2021-04-22 16:41 ` Arnaud POULIQUEN
0 siblings, 1 reply; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-22 16:32 UTC (permalink / raw)
To: Arnaud POULIQUEN
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On Thu, Apr 22, 2021 at 09:56:41AM +0200, Arnaud POULIQUEN wrote:
>
>
> On 4/21/21 8:04 PM, Mathieu Poirier wrote:
> > On Tue, Apr 13, 2021 at 03:44:53PM +0200, Arnaud Pouliquen wrote:
> >> Create the rpmsg_ctrl.c module and move the code related to the
> >> rpmsg_ctrldev device in this new module.
> >>
> >> Add the dependency between rpmsg_char and rpmsg_ctrl in the
> >> kconfig file.
> >>
> >> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> >> ---
> >> update from v1:
> >> - keep "rpmsg_chrdev" driver name in rpmsg_ctrl, driver will be renamed
> >> in next path that renames the rpmsg_chrdev_create_eptdev.
> >> - rename the chardev regions
> >> - move RPMSG_DEV_MAX to rpmsg_char.h
> >> ---
> >> drivers/rpmsg/Kconfig | 9 ++
> >> drivers/rpmsg/Makefile | 1 +
> >> drivers/rpmsg/rpmsg_char.c | 181 +----------------------------
> >> drivers/rpmsg/rpmsg_char.h | 2 +
> >> drivers/rpmsg/rpmsg_ctrl.c | 231 +++++++++++++++++++++++++++++++++++++
> >> 5 files changed, 245 insertions(+), 179 deletions(-)
> >> create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
> >>
> >> diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> >> index 0b4407abdf13..d822ec9ec692 100644
> >> --- a/drivers/rpmsg/Kconfig
>
> snip[...]
>
> >> +static int rpmsg_ctrldev_init(void)
> >> +{
> >> + int ret;
> >> +
> >> + ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_ctrl");
> >> + if (ret < 0) {
> >> + pr_err("rpmsg: failed to allocate char dev region\n");
> >> + return ret;
> >> + }
> >> +
> >> + rpmsg_class = class_create(THIS_MODULE, "rpmsg");
> >
> > This class thing really bothers me. Keeping this here means that rpmsg_eptdevs
> > created from user space will be associated to this rpmsg_class but those created
> > from the name service won't. As such I propose to move this to rpmsg_char and
> > simply not associate the control device to the class.
> >
> > Otherwise we'd have to introduce some mechanic only to deal with the creation of
> > the class and I don't think it is worth. We can revise that approach if someone
> > complains we broke their user space.
>
> I agree with that as it was my first proposed approach here [1]
Yeah, sorry about that. This patch review process is not an exact science...
>
> [1] https://www.spinics.net/lists/linux-arm-msm/msg81194.html
>
> Thanks,
> Arnaud
>
> >
> >
> >> + if (IS_ERR(rpmsg_class)) {
> >> + pr_err("failed to create rpmsg class\n");
> >> + ret = PTR_ERR(rpmsg_class);
> >> + goto free_region;
> >> + }
> >> +
> >> + ret = register_rpmsg_driver(&rpmsg_ctrldev_driver);
> >> + if (ret < 0) {
> >> + pr_err("rpmsg ctrl: failed to register rpmsg driver\n");
> >> + goto free_class;
> >> + }
> >> +
> >> + return 0;
> >> +
> >> +free_class:
> >> + class_destroy(rpmsg_class);
> >> +free_region:
> >> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> >> +
> >> + return ret;
> >> +}
> >> +postcore_initcall(rpmsg_ctrldev_init);
> >> +
> >> +static void rpmsg_ctrldev_exit(void)
> >> +{
> >> + unregister_rpmsg_driver(&rpmsg_ctrldev_driver);
> >> + class_destroy(rpmsg_class);
> >> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> >> +}
> >> +module_exit(rpmsg_ctrldev_exit);
> >> +
> >> +MODULE_DESCRIPTION("rpmsg control interface");
> >> +MODULE_ALIAS("rpmsg:" KBUILD_MODNAME);
> >> +MODULE_LICENSE("GPL v2");
> >> --
> >> 2.17.1
> >>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device
2021-04-22 7:58 ` Arnaud POULIQUEN
@ 2021-04-22 16:36 ` Mathieu Poirier
2021-04-22 16:53 ` Arnaud POULIQUEN
2021-04-28 13:05 ` Arnaud POULIQUEN
0 siblings, 2 replies; 23+ messages in thread
From: Mathieu Poirier @ 2021-04-22 16:36 UTC (permalink / raw)
To: Arnaud POULIQUEN
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On Thu, Apr 22, 2021 at 09:58:27AM +0200, Arnaud POULIQUEN wrote:
> On 4/21/21 7:40 PM, Mathieu Poirier wrote:
> > Good day Arnaud,
> >
> > On Tue, Apr 13, 2021 at 03:44:56PM +0200, Arnaud Pouliquen wrote:
> >> A rpmsg char device allows to probe the endpoint device on a remote name
> >> service announcement.
> >>
> >> With this patch the /dev/rpmsgX interface is created either by a user
> >> application or by the remote firmware.
> >>
> >> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
> >>
> >> ---
> >> update from V1:
> >> - add missing unregister_rpmsg_driver call on module exit.
> >>
> >> ---
> >> drivers/rpmsg/rpmsg_char.c | 59 +++++++++++++++++++++++++++++++++++++-
> >> 1 file changed, 58 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> >> index a64249d83172..4606787b7011 100644
> >> --- a/drivers/rpmsg/rpmsg_char.c
> >> +++ b/drivers/rpmsg/rpmsg_char.c
> >> @@ -26,6 +26,8 @@
> >> #include "rpmsg_char.h"
> >> #include "rpmsg_internal.h"
> >>
> >> +#define RPMSG_CHAR_DEVNAME "rpmsg-raw"
> >> +
> >
> > Why not simply call it rpmsg-char?
>
> I would avoid to link the rpmsg name service to the Linux Kernel device.
To me that's exactly what we want to do... Am I missing something?
>
> >
> >> static dev_t rpmsg_major;
> >>
> >> static DEFINE_IDA(rpmsg_ept_ida);
> >> @@ -403,13 +405,67 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
> >> }
> >> EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
> >>
> >> +static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
> >> +{
> >> + struct rpmsg_channel_info chinfo;
> >> + struct rpmsg_eptdev *eptdev;
> >> +
> >> + if (!rpdev->ept)
> >> + return -EINVAL;
> >> +
> >> + memcpy(chinfo.name, RPMSG_CHAR_DEVNAME, sizeof(RPMSG_CHAR_DEVNAME));
> >> + chinfo.src = rpdev->src;
> >> + chinfo.dst = rpdev->dst;
> >> +
> >> + eptdev = __rpmsg_chrdev_create_eptdev(rpdev, &rpdev->dev, chinfo, NULL);
> >> + if (IS_ERR(eptdev))
> >> + return PTR_ERR(eptdev);
> >> +
> >> + /* Set the private field of the default endpoint to retrieve context on callback. */
> >> + rpdev->ept->priv = eptdev;
> >
> > This is already done in rpmsg_create_ept() when rpmsg_eptdev_open() is called.
> >
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
> >> +{
> >> + int ret;
> >> +
> >> + ret = device_for_each_child(&rpdev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
> >> + if (ret)
> >> + dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret);
> >> +}
> >> +
> >> +static struct rpmsg_device_id rpmsg_chrdev_id_table[] = {
> >> + { .name = RPMSG_CHAR_DEVNAME },
> >> + { },
> >> +};
> >> +
> >> +static struct rpmsg_driver rpmsg_chrdev_driver = {
> >> + .probe = rpmsg_chrdev_probe,
> >> + .remove = rpmsg_chrdev_remove,
> >> + .id_table = rpmsg_chrdev_id_table,
> >> + .callback = rpmsg_ept_cb,
> >
> > Not sure why we need a callback associated to this driver when
> > rpmsg_eptdev_open() already creates and rpmsg_endpoint. To me the only thing
> > having a callback provides is the association between the rpmsg_device and the
> > rpmsg_endpoint[1] that happens in rpmsg_dev_probe(). The QC folks already do
> > this association in their platform code[2]. Since this is not done in
> > __rpmsg_create_ept() a check for rpdev->ept == NULL could be done in
> > rpmsg_eptdev_open() and do the assignment there.
> >
> > [1]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/rpmsg_core.c#L513
> > [2]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/qcom_glink_native.c#L1623
> >
>
> That's a good point! When I started the redesign, I faced some issues with the
> approach you propose. But as I can not remember the reason and because the code
> has evolved, i need to re-think about this.
>
Glad to see we're on the same page. I stared at this code for a very long time,
thinking there was some kind of bigger picture I wasn't getting.
> Thanks,
> Arnaud
>
>
> >> + .drv = {
> >> + .name = "rpmsg_chrdev",
> >> + },
> >> +};
> >> +
> >> static int rpmsg_chrdev_init(void)
> >> {
> >> int ret;
> >>
> >> ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char");
> >> - if (ret < 0)
> >> + if (ret < 0) {
> >> pr_err("rpmsg: failed to allocate char dev region\n");
> >> + return ret;
> >> + }
> >> +
> >> + ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
> >> + if (ret < 0) {
> >> + pr_err("rpmsg: failed to register rpmsg raw driver\n");
> >> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> >> + }
> >>
> >> return ret;
> >> }
> >> @@ -417,6 +473,7 @@ postcore_initcall(rpmsg_chrdev_init);
> >>
> >> static void rpmsg_chrdev_exit(void)
> >> {
> >> + unregister_rpmsg_driver(&rpmsg_chrdev_driver);
> >> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> >> }
> >> module_exit(rpmsg_chrdev_exit);
> >> --
> >> 2.17.1
> >>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl
2021-04-22 16:32 ` Mathieu Poirier
@ 2021-04-22 16:41 ` Arnaud POULIQUEN
0 siblings, 0 replies; 23+ messages in thread
From: Arnaud POULIQUEN @ 2021-04-22 16:41 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On 4/22/21 6:32 PM, Mathieu Poirier wrote:
> On Thu, Apr 22, 2021 at 09:56:41AM +0200, Arnaud POULIQUEN wrote:
>>
>>
>> On 4/21/21 8:04 PM, Mathieu Poirier wrote:
>>> On Tue, Apr 13, 2021 at 03:44:53PM +0200, Arnaud Pouliquen wrote:
>>>> Create the rpmsg_ctrl.c module and move the code related to the
>>>> rpmsg_ctrldev device in this new module.
>>>>
>>>> Add the dependency between rpmsg_char and rpmsg_ctrl in the
>>>> kconfig file.
>>>>
>>>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>>>> ---
>>>> update from v1:
>>>> - keep "rpmsg_chrdev" driver name in rpmsg_ctrl, driver will be renamed
>>>> in next path that renames the rpmsg_chrdev_create_eptdev.
>>>> - rename the chardev regions
>>>> - move RPMSG_DEV_MAX to rpmsg_char.h
>>>> ---
>>>> drivers/rpmsg/Kconfig | 9 ++
>>>> drivers/rpmsg/Makefile | 1 +
>>>> drivers/rpmsg/rpmsg_char.c | 181 +----------------------------
>>>> drivers/rpmsg/rpmsg_char.h | 2 +
>>>> drivers/rpmsg/rpmsg_ctrl.c | 231 +++++++++++++++++++++++++++++++++++++
>>>> 5 files changed, 245 insertions(+), 179 deletions(-)
>>>> create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
>>>>
>>>> diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
>>>> index 0b4407abdf13..d822ec9ec692 100644
>>>> --- a/drivers/rpmsg/Kconfig
>>
>> snip[...]
>>
>>>> +static int rpmsg_ctrldev_init(void)
>>>> +{
>>>> + int ret;
>>>> +
>>>> + ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_ctrl");
>>>> + if (ret < 0) {
>>>> + pr_err("rpmsg: failed to allocate char dev region\n");
>>>> + return ret;
>>>> + }
>>>> +
>>>> + rpmsg_class = class_create(THIS_MODULE, "rpmsg");
>>>
>>> This class thing really bothers me. Keeping this here means that rpmsg_eptdevs
>>> created from user space will be associated to this rpmsg_class but those created
>>> from the name service won't. As such I propose to move this to rpmsg_char and
>>> simply not associate the control device to the class.
>>>
>>> Otherwise we'd have to introduce some mechanic only to deal with the creation of
>>> the class and I don't think it is worth. We can revise that approach if someone
>>> complains we broke their user space.
>>
>> I agree with that as it was my first proposed approach here [1]
>
> Yeah, sorry about that. This patch review process is not an exact science...
No worries, exploring alternatives is part of the upstream process :)
>
>>
>> [1] https://www.spinics.net/lists/linux-arm-msm/msg81194.html
>>
>> Thanks,
>> Arnaud
>>
>>>
>>>
>>>> + if (IS_ERR(rpmsg_class)) {
>>>> + pr_err("failed to create rpmsg class\n");
>>>> + ret = PTR_ERR(rpmsg_class);
>>>> + goto free_region;
>>>> + }
>>>> +
>>>> + ret = register_rpmsg_driver(&rpmsg_ctrldev_driver);
>>>> + if (ret < 0) {
>>>> + pr_err("rpmsg ctrl: failed to register rpmsg driver\n");
>>>> + goto free_class;
>>>> + }
>>>> +
>>>> + return 0;
>>>> +
>>>> +free_class:
>>>> + class_destroy(rpmsg_class);
>>>> +free_region:
>>>> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>>> +
>>>> + return ret;
>>>> +}
>>>> +postcore_initcall(rpmsg_ctrldev_init);
>>>> +
>>>> +static void rpmsg_ctrldev_exit(void)
>>>> +{
>>>> + unregister_rpmsg_driver(&rpmsg_ctrldev_driver);
>>>> + class_destroy(rpmsg_class);
>>>> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>>> +}
>>>> +module_exit(rpmsg_ctrldev_exit);
>>>> +
>>>> +MODULE_DESCRIPTION("rpmsg control interface");
>>>> +MODULE_ALIAS("rpmsg:" KBUILD_MODNAME);
>>>> +MODULE_LICENSE("GPL v2");
>>>> --
>>>> 2.17.1
>>>>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device
2021-04-22 16:36 ` Mathieu Poirier
@ 2021-04-22 16:53 ` Arnaud POULIQUEN
2021-04-28 13:05 ` Arnaud POULIQUEN
1 sibling, 0 replies; 23+ messages in thread
From: Arnaud POULIQUEN @ 2021-04-22 16:53 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
On 4/22/21 6:36 PM, Mathieu Poirier wrote:
> On Thu, Apr 22, 2021 at 09:58:27AM +0200, Arnaud POULIQUEN wrote:
>> On 4/21/21 7:40 PM, Mathieu Poirier wrote:
>>> Good day Arnaud,
>>>
>>> On Tue, Apr 13, 2021 at 03:44:56PM +0200, Arnaud Pouliquen wrote:
>>>> A rpmsg char device allows to probe the endpoint device on a remote name
>>>> service announcement.
>>>>
>>>> With this patch the /dev/rpmsgX interface is created either by a user
>>>> application or by the remote firmware.
>>>>
>>>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>>>>
>>>> ---
>>>> update from V1:
>>>> - add missing unregister_rpmsg_driver call on module exit.
>>>>
>>>> ---
>>>> drivers/rpmsg/rpmsg_char.c | 59 +++++++++++++++++++++++++++++++++++++-
>>>> 1 file changed, 58 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
>>>> index a64249d83172..4606787b7011 100644
>>>> --- a/drivers/rpmsg/rpmsg_char.c
>>>> +++ b/drivers/rpmsg/rpmsg_char.c
>>>> @@ -26,6 +26,8 @@
>>>> #include "rpmsg_char.h"
>>>> #include "rpmsg_internal.h"
>>>>
>>>> +#define RPMSG_CHAR_DEVNAME "rpmsg-raw"
>>>> +
>>>
>>> Why not simply call it rpmsg-char?
>>
>> I would avoid to link the rpmsg name service to the Linux Kernel device.
>
> To me that's exactly what we want to do... Am I missing something?
A discussion started about a service layer in the OpenAMP library.
"rpmsg-char" doesn't really make sense in OpenAMP, especially for
OpenAMP<->openAMP communication.
That's why I think a generic name would be more suitable.
Regards,
Arnaud
>
>>
>>>
>>>> static dev_t rpmsg_major;
>>>>
>>>> static DEFINE_IDA(rpmsg_ept_ida);
>>>> @@ -403,13 +405,67 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
>>>> }
>>>> EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>>>>
>>>> +static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
>>>> +{
>>>> + struct rpmsg_channel_info chinfo;
>>>> + struct rpmsg_eptdev *eptdev;
>>>> +
>>>> + if (!rpdev->ept)
>>>> + return -EINVAL;
>>>> +
>>>> + memcpy(chinfo.name, RPMSG_CHAR_DEVNAME, sizeof(RPMSG_CHAR_DEVNAME));
>>>> + chinfo.src = rpdev->src;
>>>> + chinfo.dst = rpdev->dst;
>>>> +
>>>> + eptdev = __rpmsg_chrdev_create_eptdev(rpdev, &rpdev->dev, chinfo, NULL);
>>>> + if (IS_ERR(eptdev))
>>>> + return PTR_ERR(eptdev);
>>>> +
>>>> + /* Set the private field of the default endpoint to retrieve context on callback. */
>>>> + rpdev->ept->priv = eptdev;
>>>
>>> This is already done in rpmsg_create_ept() when rpmsg_eptdev_open() is called.
>>>
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
>>>> +{
>>>> + int ret;
>>>> +
>>>> + ret = device_for_each_child(&rpdev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
>>>> + if (ret)
>>>> + dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret);
>>>> +}
>>>> +
>>>> +static struct rpmsg_device_id rpmsg_chrdev_id_table[] = {
>>>> + { .name = RPMSG_CHAR_DEVNAME },
>>>> + { },
>>>> +};
>>>> +
>>>> +static struct rpmsg_driver rpmsg_chrdev_driver = {
>>>> + .probe = rpmsg_chrdev_probe,
>>>> + .remove = rpmsg_chrdev_remove,
>>>> + .id_table = rpmsg_chrdev_id_table,
>>>> + .callback = rpmsg_ept_cb,
>>>
>>> Not sure why we need a callback associated to this driver when
>>> rpmsg_eptdev_open() already creates and rpmsg_endpoint. To me the only thing
>>> having a callback provides is the association between the rpmsg_device and the
>>> rpmsg_endpoint[1] that happens in rpmsg_dev_probe(). The QC folks already do
>>> this association in their platform code[2]. Since this is not done in
>>> __rpmsg_create_ept() a check for rpdev->ept == NULL could be done in
>>> rpmsg_eptdev_open() and do the assignment there.
>>>
>>> [1]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/rpmsg_core.c#L513
>>> [2]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/qcom_glink_native.c#L1623
>>>
>>
>> That's a good point! When I started the redesign, I faced some issues with the
>> approach you propose. But as I can not remember the reason and because the code
>> has evolved, i need to re-think about this.
>>
>
> Glad to see we're on the same page. I stared at this code for a very long time,
> thinking there was some kind of bigger picture I wasn't getting.
>
>
>> Thanks,
>> Arnaud
>>
>>
>>>> + .drv = {
>>>> + .name = "rpmsg_chrdev",
>>>> + },
>>>> +};
>>>> +
>>>> static int rpmsg_chrdev_init(void)
>>>> {
>>>> int ret;
>>>>
>>>> ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char");
>>>> - if (ret < 0)
>>>> + if (ret < 0) {
>>>> pr_err("rpmsg: failed to allocate char dev region\n");
>>>> + return ret;
>>>> + }
>>>> +
>>>> + ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
>>>> + if (ret < 0) {
>>>> + pr_err("rpmsg: failed to register rpmsg raw driver\n");
>>>> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>>> + }
>>>>
>>>> return ret;
>>>> }
>>>> @@ -417,6 +473,7 @@ postcore_initcall(rpmsg_chrdev_init);
>>>>
>>>> static void rpmsg_chrdev_exit(void)
>>>> {
>>>> + unregister_rpmsg_driver(&rpmsg_chrdev_driver);
>>>> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>>> }
>>>> module_exit(rpmsg_chrdev_exit);
>>>> --
>>>> 2.17.1
>>>>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device
2021-04-22 16:36 ` Mathieu Poirier
2021-04-22 16:53 ` Arnaud POULIQUEN
@ 2021-04-28 13:05 ` Arnaud POULIQUEN
1 sibling, 0 replies; 23+ messages in thread
From: Arnaud POULIQUEN @ 2021-04-28 13:05 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Bjorn Andersson, Ohad Ben-Cohen, linux-remoteproc, linux-kernel,
linux-stm32
Hi,
On 4/22/21 6:36 PM, Mathieu Poirier wrote:
> On Thu, Apr 22, 2021 at 09:58:27AM +0200, Arnaud POULIQUEN wrote:
>> On 4/21/21 7:40 PM, Mathieu Poirier wrote:
>>> Good day Arnaud,
>>>
>>> On Tue, Apr 13, 2021 at 03:44:56PM +0200, Arnaud Pouliquen wrote:
>>>> A rpmsg char device allows to probe the endpoint device on a remote name
>>>> service announcement.
>>>>
>>>> With this patch the /dev/rpmsgX interface is created either by a user
>>>> application or by the remote firmware.
>>>>
>>>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>>>>
>>>> ---
>>>> update from V1:
>>>> - add missing unregister_rpmsg_driver call on module exit.
>>>>
>>>> ---
>>>> drivers/rpmsg/rpmsg_char.c | 59 +++++++++++++++++++++++++++++++++++++-
>>>> 1 file changed, 58 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
>>>> index a64249d83172..4606787b7011 100644
>>>> --- a/drivers/rpmsg/rpmsg_char.c
>>>> +++ b/drivers/rpmsg/rpmsg_char.c
>>>> @@ -26,6 +26,8 @@
>>>> #include "rpmsg_char.h"
>>>> #include "rpmsg_internal.h"
>>>>
>>>> +#define RPMSG_CHAR_DEVNAME "rpmsg-raw"
>>>> +
>>>
>>> Why not simply call it rpmsg-char?
>>
>> I would avoid to link the rpmsg name service to the Linux Kernel device.
>
> To me that's exactly what we want to do... Am I missing something?
>
>>
>>>
>>>> static dev_t rpmsg_major;
>>>>
>>>> static DEFINE_IDA(rpmsg_ept_ida);
>>>> @@ -403,13 +405,67 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device *rpdev, struct device *parent
>>>> }
>>>> EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>>>>
>>>> +static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
>>>> +{
>>>> + struct rpmsg_channel_info chinfo;
>>>> + struct rpmsg_eptdev *eptdev;
>>>> +
>>>> + if (!rpdev->ept)
>>>> + return -EINVAL;
>>>> +
>>>> + memcpy(chinfo.name, RPMSG_CHAR_DEVNAME, sizeof(RPMSG_CHAR_DEVNAME));
>>>> + chinfo.src = rpdev->src;
>>>> + chinfo.dst = rpdev->dst;
>>>> +
>>>> + eptdev = __rpmsg_chrdev_create_eptdev(rpdev, &rpdev->dev, chinfo, NULL);
>>>> + if (IS_ERR(eptdev))
>>>> + return PTR_ERR(eptdev);
>>>> +
>>>> + /* Set the private field of the default endpoint to retrieve context on callback. */
>>>> + rpdev->ept->priv = eptdev;
>>>
>>> This is already done in rpmsg_create_ept() when rpmsg_eptdev_open() is called.
>>>
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
>>>> +{
>>>> + int ret;
>>>> +
>>>> + ret = device_for_each_child(&rpdev->dev, NULL, rpmsg_chrdev_destroy_eptdev);
>>>> + if (ret)
>>>> + dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret);
>>>> +}
>>>> +
>>>> +static struct rpmsg_device_id rpmsg_chrdev_id_table[] = {
>>>> + { .name = RPMSG_CHAR_DEVNAME },
>>>> + { },
>>>> +};
>>>> +
>>>> +static struct rpmsg_driver rpmsg_chrdev_driver = {
>>>> + .probe = rpmsg_chrdev_probe,
>>>> + .remove = rpmsg_chrdev_remove,
>>>> + .id_table = rpmsg_chrdev_id_table,
>>>> + .callback = rpmsg_ept_cb,
>>>
>>> Not sure why we need a callback associated to this driver when
>>> rpmsg_eptdev_open() already creates and rpmsg_endpoint. To me the only thing
>>> having a callback provides is the association between the rpmsg_device and the
>>> rpmsg_endpoint[1] that happens in rpmsg_dev_probe(). The QC folks already do
>>> this association in their platform code[2]. Since this is not done in
>>> __rpmsg_create_ept() a check for rpdev->ept == NULL could be done in
>>> rpmsg_eptdev_open() and do the assignment there.
>>>
>>> [1]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/rpmsg_core.c#L513
>>> [2]. https://elixir.bootlin.com/linux/v5.12-rc6/source/drivers/rpmsg/qcom_glink_native.c#L1623
>>>
>>
>> That's a good point! When I started the redesign, I faced some issues with the
>> approach you propose. But as I can not remember the reason and because the code
>> has evolved, i need to re-think about this.
>>
>
> Glad to see we're on the same page. I stared at this code for a very long time,
> thinking there was some kind of bigger picture I wasn't getting.
I finally found the time to investigate this. If I remember now why I used this
approach, I also saw that my patchset does not work with the QCOM platform driver.
As a first step of explanation, let's ignore the QC platform.
rpdev->ept is null for the rpmsg ctrldev device created by the virtio rpmsg bus.
If no default endpoint is created on rpmsg_chrdev_probe, it is not possible to
differentiate the two in rpmsg_eptdev_open based on rpdev->ept == NULL.
Now let's add the QC implementation
As you mentioned, QC sets the rpdev->ept to a default endpoint before
registering the rpmsg ctrldev. This shows that it is not reasonable to expect to
handle all use cases based on the rpdev->ept value.
So, to summarize, I need to rework this, probably by adding a new field in the
rpmsg_eptdev structure, to properly handle the endpoint creation in the
rpmsg_eptdev_open function.
Regards,
Arnaud
>
>
>> Thanks,
>> Arnaud
>>
>>
>>>> + .drv = {
>>>> + .name = "rpmsg_chrdev",
>>>> + },
>>>> +};
>>>> +
>>>> static int rpmsg_chrdev_init(void)
>>>> {
>>>> int ret;
>>>>
>>>> ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_char");
>>>> - if (ret < 0)
>>>> + if (ret < 0) {
>>>> pr_err("rpmsg: failed to allocate char dev region\n");
>>>> + return ret;
>>>> + }
>>>> +
>>>> + ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
>>>> + if (ret < 0) {
>>>> + pr_err("rpmsg: failed to register rpmsg raw driver\n");
>>>> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>>> + }
>>>>
>>>> return ret;
>>>> }
>>>> @@ -417,6 +473,7 @@ postcore_initcall(rpmsg_chrdev_init);
>>>>
>>>> static void rpmsg_chrdev_exit(void)
>>>> {
>>>> + unregister_rpmsg_driver(&rpmsg_chrdev_driver);
>>>> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>>> }
>>>> module_exit(rpmsg_chrdev_exit);
>>>> --
>>>> 2.17.1
>>>>
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2021-04-28 13:05 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-13 13:44 [PATCH v2 0/7] Restructure the rpmsg char and introduce the rpmsg-raw channel Arnaud Pouliquen
2021-04-13 13:44 ` [PATCH v2 1/7] rpmsg: char: Export eptdev create an destroy functions Arnaud Pouliquen
2021-04-21 17:52 ` Mathieu Poirier
2021-04-22 7:55 ` Arnaud POULIQUEN
2021-04-22 16:29 ` Mathieu Poirier
2021-04-13 13:44 ` [PATCH v2 2/7] rpmsg: Move the rpmsg control device from rpmsg_char to rpmsg_ctrl Arnaud Pouliquen
2021-04-21 18:04 ` Mathieu Poirier
2021-04-22 7:56 ` Arnaud POULIQUEN
2021-04-22 16:32 ` Mathieu Poirier
2021-04-22 16:41 ` Arnaud POULIQUEN
2021-04-13 13:44 ` [PATCH v2 3/7] rpmsg: Update rpmsg_chrdev_register_device function Arnaud Pouliquen
2021-04-21 18:06 ` Mathieu Poirier
2021-04-13 13:44 ` [PATCH v2 4/7] rpmsg: char: Introduce __rpmsg_chrdev_create_eptdev function Arnaud Pouliquen
2021-04-21 17:43 ` Mathieu Poirier
2021-04-21 17:45 ` Mathieu Poirier
2021-04-13 13:44 ` [PATCH v2 5/7] rpmsg: char: Introduce a rpmsg driver for the rpmsg char device Arnaud Pouliquen
2021-04-21 17:40 ` Mathieu Poirier
2021-04-22 7:58 ` Arnaud POULIQUEN
2021-04-22 16:36 ` Mathieu Poirier
2021-04-22 16:53 ` Arnaud POULIQUEN
2021-04-28 13:05 ` Arnaud POULIQUEN
2021-04-13 13:44 ` [PATCH v2 6/7] rpmsg: char: No dynamic endpoint management for the default one Arnaud Pouliquen
2021-04-13 13:44 ` [PATCH v2 7/7] rpmsg: char: Return error if user tries to destroy a default endpoint Arnaud Pouliquen
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).