linux-remoteproc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/13] introduce IOCTL interface for RPMsg channel management
@ 2020-07-31 12:10 Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 01/13] rpmsg: introduce rpmsg raw driver Arnaud Pouliquen
                   ` (12 more replies)
  0 siblings, 13 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

This serie is inspired by the RPMsg char driver. The RPMsg char driver
provides interfaces that:
- expose a char RPMsg device for communication with the remote processor
- expose controls interface for applications to create and release channels

The purpose of this series is to decorrelate the two interfaces:
 - provide a char device for a RPMsg raw service similar to the rpmsg_char
   but that can be probed by a RPMsg bus on a ns announcement
 - generalize the use of the ioctl for all RPMsg services.

1) rpmsg raw driver: rpmsg_raw.c
For legacy reason, I created a new file instead of modifying the rpmsg_char
driver. But the rework of the rpmsg_char driver to only support the RPMsg
raw service could be an alternative
Few differences can be found:
    - The rpmsg class has not been implemented. The associated attributes
      are already available in /sys/bus/rpmsg/.
    - The eptdev device is now an RPMsg device probed by a RPMsg bus driver
      (probed only by the ioctl in rpmsg_char driver).
    - The associated endpoint is now created by the bus no more on the
      devfs open.

2) RPMsg control driver: rpmsg_ctrl.c
  This driver is based on the control part of the RPMsg_char driver. 
  On probe a /dev/rpmsg_ctrl<X> interface is created to allow to manage the
  channels.
  The principles are the following:
  - The RPMsg service driver registers it's name and the associated service
    using the rpmsg_ctrl_unregister_ctl API. The list of supported services
    is defined in  include/uapi/linux/rpmsg.h and exposed to the
    application thanks to a new field in rpmsg_endpoint_info struct.
  - On the RPMsg bus probe(e.g virtio bus) an rpmsg_ctrl device is
    registered that creates the control interface.
  - The application can then create or release a channel by specifying:
       - the name service
       - the source address (default: RPMSG_ADDR_ANY)
       - the destination address ( default: RPMSG_ADDR_ANY)
       - the associated service (new)
  - The rpmsg_ctrl uses the same interface than the ns announcement to
    create and release the channel but using the driver_override field to
    force the service name.
    The  "driver_override" allows to force the name service associated to
    an RPMsg driver, bypassing the rpmsg_device_id based match check.
  - At least for virtio bus, an associated ns announcement is sent to the
    remote side.  

Know current Limitations:
- Tested only with virtio RPMsg bus and for one vdev instance.
- rpmsg_device_match does not allow to match a local endpoint created by
  ioctl with a same service requested by the ns announcement callback.
- Current implementation of the release makes it possible to release any
  endpoint, even not created by the ioctl. Should we limit the release to
  the RPMsg channel created with the ioctl? 

This serie can be applied in Bjorn's rpmsg-next branch on top of the
RPMsg_ns series.

This series can be tested using rpmsgexport tools updated according to the
ioctl update and available here: https://github.com/arnopo/rpmsgexport. 

Arnaud Pouliquen (13):
  rpmsg: introduce rpmsg raw driver
  rpmsg: introduce rpmsg_control driver for channel creation
  rpmsg: add helper to create the rpmsg ctrl device
  rpmsg: virtio: probe the rpmsg_ctrl device
  rpmsg: uapi: add service param for create destroy ioctls
  rpmsg: add RPMsg control info structure
  rpmsg: control: add driver registration API
  rpmsg: raw: register service to the rpmsg control
  rpmsg: add override field in channel info
  rpmsg: ns: initialize channel info override field
  rpmsg: virtio: use the driver_override in channel creation
  rpmsg: control: implement the ioctrl function to create device
  rpmsg: ctrl: add support of the endpoints release

 drivers/rpmsg/Kconfig            |  17 ++
 drivers/rpmsg/Makefile           |   2 +
 drivers/rpmsg/rpmsg_ctrl.c       | 314 ++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   |  18 ++
 drivers/rpmsg/rpmsg_ns.c         |   1 +
 drivers/rpmsg/rpmsg_raw.c        | 364 +++++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c |  37 +++-
 include/linux/rpmsg.h            |  15 ++
 include/uapi/linux/rpmsg.h       |  17 ++
 9 files changed, 784 insertions(+), 1 deletion(-)
 create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
 create mode 100644 drivers/rpmsg/rpmsg_raw.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 01/13] rpmsg: introduce rpmsg raw driver
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 02/13] rpmsg: introduce rpmsg_control driver for channel creation Arnaud Pouliquen
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

This driver is a copy past of the rpmsg_char driver with following
update:
- The control part has been removed.
- The rpmsg class has been removed because the information already
  available in /sys/bus.
- The device is now an RPMsg device probed by a RPMsg bus driver.
- The associated endpoint is now created by the bus not on the fs open.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/Kconfig     |   9 +
 drivers/rpmsg/Makefile    |   1 +
 drivers/rpmsg/rpmsg_raw.c | 347 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 357 insertions(+)
 create mode 100644 drivers/rpmsg/rpmsg_raw.c

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 0143c9864c45..900ec8f54081 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -23,6 +23,15 @@ config RPMSG_NS
 	  channel that probes the associate RPMsg device on remote endpoint
 	  service announcement.
 
+config RPMSG_RAW
+	tristate "RPMSG raw service driver"
+	depends on RPMSG
+	depends on NET
+	help
+	  Say Y here to export rpmsg endpoints as char device files, found
+	  in /dev. They make it possible for user-space programs to send and
+	  receive rpmsg packets through a basic char device.
+
 config RPMSG_MTK_SCP
 	tristate "MediaTek SCP"
 	depends on MTK_SCP
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 8d452656f0ee..d75f0a65e71d 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
 obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o
 obj-$(CONFIG_RPMSG_QCOM_SMD)	+= qcom_smd.o
 obj-$(CONFIG_RPMSG_VIRTIO)	+= virtio_rpmsg_bus.o
+obj-$(CONFIG_RPMSG_RAW)	+= rpmsg_raw.o
diff --git a/drivers/rpmsg/rpmsg_raw.c b/drivers/rpmsg/rpmsg_raw.c
new file mode 100644
index 000000000000..8684a78ab4d1
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_raw.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved
+ *
+ * Based on rpmsg_char 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/poll.h>
+#include <linux/rpmsg.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <uapi/linux/rpmsg.h>
+
+#include "rpmsg_internal.h"
+
+#define RPMSG_DEV_MAX	(MINORMASK + 1)
+
+#define dev_to_eptdev(dev) container_of(dev, struct rpmsg_raw, dev)
+#define cdev_to_eptdev(i_cdev) container_of(i_cdev, struct rpmsg_raw, cdev)
+
+static dev_t rpmsg_raw_major;
+
+static DEFINE_IDA(rpmsg_minor_ida);
+static DEFINE_IDA(rpmsg_ept_ida);
+
+/**
+ * struct rpmsg_raw - endpoint device context
+ * @dev:	endpoint device
+ * @cdev:	cdev for the endpoint device
+ * @rpdev:	underlaying rpmsg device
+ * @ept_lock:	synchronization of @ept modifications
+ * @queue_lock:	synchronization of @queue operations
+ * @queue:	incoming message queue
+ * @readq:	wait object for incoming queue
+ */
+struct rpmsg_raw {
+	struct device dev;
+	struct cdev cdev;
+	struct rpmsg_device *rpdev;
+	struct mutex ept_lock;
+	spinlock_t queue_lock;
+	struct sk_buff_head queue;
+	wait_queue_head_t readq;
+};
+
+static int rpmsg_raw_cb(struct rpmsg_device *rpdev, void *buf, int len,
+			void *priv, u32 addr)
+{
+	struct rpmsg_raw *eptdev = dev_get_drvdata(&rpdev->dev);
+	struct sk_buff *skb;
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put_data(skb, buf, len);
+
+	spin_lock(&eptdev->queue_lock);
+	skb_queue_tail(&eptdev->queue, skb);
+	spin_unlock(&eptdev->queue_lock);
+
+	/* wake up any blocking processes, waiting for new data */
+	wake_up_interruptible(&eptdev->readq);
+
+	return 0;
+}
+
+static int rpmsg_raw_open(struct inode *inode, struct file *filp)
+{
+	struct rpmsg_raw *eptdev = cdev_to_eptdev(inode->i_cdev);
+	struct device *dev = &eptdev->dev;
+
+	get_device(dev);
+
+	filp->private_data = eptdev;
+
+	return 0;
+}
+
+static int rpmsg_raw_release(struct inode *inode, struct file *filp)
+{
+	struct rpmsg_raw *eptdev = cdev_to_eptdev(inode->i_cdev);
+
+	/* Discard all SKBs */
+	skb_queue_purge(&eptdev->queue);
+
+	put_device(&eptdev->dev);
+
+	return 0;
+}
+
+static ssize_t rpmsg_raw_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+	struct file *filp = iocb->ki_filp;
+	struct rpmsg_raw *eptdev = filp->private_data;
+	unsigned long flags;
+	struct sk_buff *skb;
+	int use;
+
+	if (!eptdev->rpdev->ept)
+		return -EPIPE;
+
+	spin_lock_irqsave(&eptdev->queue_lock, flags);
+
+	/* Wait for data in the queue */
+	if (skb_queue_empty(&eptdev->queue)) {
+		spin_unlock_irqrestore(&eptdev->queue_lock, flags);
+
+		if (filp->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		/* Wait until we get data or the endpoint goes away */
+		if (wait_event_interruptible(eptdev->readq,
+					     !skb_queue_empty(&eptdev->queue) ||
+					     !eptdev->rpdev->ept))
+			return -ERESTARTSYS;
+
+		/* We lost the endpoint while waiting */
+		if (!eptdev->rpdev->ept)
+			return -EPIPE;
+
+		spin_lock_irqsave(&eptdev->queue_lock, flags);
+	}
+
+	skb = skb_dequeue(&eptdev->queue);
+	spin_unlock_irqrestore(&eptdev->queue_lock, flags);
+	if (!skb)
+		return -EFAULT;
+
+	use = min_t(size_t, iov_iter_count(to), skb->len);
+	if (copy_to_iter(skb->data, use, to) != use)
+		use = -EFAULT;
+
+	kfree_skb(skb);
+
+	return use;
+}
+
+static ssize_t rpmsg_raw_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+	struct file *filp = iocb->ki_filp;
+	struct rpmsg_raw *eptdev = filp->private_data;
+	size_t len = iov_iter_count(from);
+	void *kbuf;
+	int ret;
+
+	kbuf = kzalloc(len, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	if (!copy_from_iter_full(kbuf, len, from)) {
+		ret = -EFAULT;
+		goto free_kbuf;
+	}
+
+	if (mutex_lock_interruptible(&eptdev->ept_lock)) {
+		ret = -ERESTARTSYS;
+		goto free_kbuf;
+	}
+
+	if (!eptdev->rpdev->ept) {
+		ret = -EPIPE;
+		goto unlock_eptdev;
+	}
+
+	if (filp->f_flags & O_NONBLOCK)
+		ret = rpmsg_trysend(eptdev->rpdev->ept, kbuf, len);
+	else
+		ret = rpmsg_send(eptdev->rpdev->ept, kbuf, len);
+
+unlock_eptdev:
+	mutex_unlock(&eptdev->ept_lock);
+
+free_kbuf:
+	kfree(kbuf);
+	return ret < 0 ? ret : len;
+}
+
+static __poll_t rpmsg_raw_poll(struct file *filp, poll_table *wait)
+{
+	struct rpmsg_raw *eptdev = filp->private_data;
+	__poll_t mask = 0;
+
+	if (!eptdev->rpdev->ept)
+		return EPOLLERR;
+
+	poll_wait(filp, &eptdev->readq, wait);
+
+	if (!skb_queue_empty(&eptdev->queue))
+		mask |= EPOLLIN | EPOLLRDNORM;
+
+	mask |= rpmsg_poll(eptdev->rpdev->ept, filp, wait);
+
+	return mask;
+}
+
+static void rpmsg_raw_release_device(struct device *dev)
+{
+	struct rpmsg_raw *eptdev = dev_to_eptdev(dev);
+
+	ida_simple_remove(&rpmsg_ept_ida, dev->id);
+	ida_simple_remove(&rpmsg_minor_ida, MINOR(eptdev->dev.devt));
+	cdev_del(&eptdev->cdev);
+	kfree(eptdev);
+}
+
+static const struct file_operations rpmsg_raw_fops = {
+	.owner = THIS_MODULE,
+	.open = rpmsg_raw_open,
+	.release = rpmsg_raw_release,
+	.read_iter = rpmsg_raw_read_iter,
+	.write_iter = rpmsg_raw_write_iter,
+	.poll = rpmsg_raw_poll,
+};
+
+static int rpmsg_raw_probe(struct rpmsg_device *rpdev)
+{
+	struct rpmsg_raw *eptdev;
+	struct device *dev;
+	int ret;
+
+	eptdev = kzalloc(sizeof(*eptdev), GFP_KERNEL);
+	if (!eptdev)
+		return -ENOMEM;
+
+	dev = &eptdev->dev;
+	eptdev->rpdev = rpdev;
+
+	mutex_init(&eptdev->ept_lock);
+	spin_lock_init(&eptdev->queue_lock);
+	skb_queue_head_init(&eptdev->queue);
+	init_waitqueue_head(&eptdev->readq);
+
+	device_initialize(dev);
+	dev->parent = &rpdev->dev;
+	dev_set_drvdata(dev, eptdev);
+
+	cdev_init(&eptdev->cdev, &rpmsg_raw_fops);
+	eptdev->cdev.owner = THIS_MODULE;
+
+	ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL);
+	if (ret < 0) {
+		dev_err(dev, "failed to get IDA (%d)\n", ret);
+		goto free_eptdev;
+	}
+
+	dev->devt = MKDEV(MAJOR(rpmsg_raw_major), ret);
+
+	ret = ida_simple_get(&rpmsg_ept_ida, 0, 0, GFP_KERNEL);
+	if (ret < 0)
+		goto free_minor_ida;
+	dev->id = ret;
+	dev_set_name(dev, "rpmsg%d", dev->id);
+
+	ret = cdev_add(&eptdev->cdev, dev->devt, 1);
+	if (ret) {
+		ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
+		dev_err(&rpdev->dev, "failed to add char device(%d)\n", ret);
+		goto free_ept_ida;
+	}
+
+	/* We can now rely on the release function for cleanup */
+	dev->release = rpmsg_raw_release_device;
+
+	ret = device_add(dev);
+	if (ret) {
+		dev_err(dev, "device_add failed: %d\n", ret);
+		put_device(dev);
+	}
+
+	dev_set_drvdata(&rpdev->dev, eptdev);
+
+	return ret;
+
+free_ept_ida:
+	ida_simple_remove(&rpmsg_ept_ida, dev->id);
+free_minor_ida:
+	ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
+free_eptdev:
+	put_device(dev);
+	kfree(eptdev);
+
+	return ret;
+}
+
+static void rpmsg_raw_remove(struct rpmsg_device *rpdev)
+{
+	struct rpmsg_raw *eptdev = dev_get_drvdata(&rpdev->dev);
+
+	/* wake up any blocked readers */
+	wake_up_interruptible(&eptdev->readq);
+
+	device_del(&eptdev->dev);
+
+	put_device(&eptdev->dev);
+}
+
+static struct rpmsg_device_id rpmsg_driver_sample_id_table[] = {
+	{ .name	= "rpmsg-raw" },
+	{ },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table);
+
+static struct rpmsg_driver rpmsg_raw_client = {
+	.drv.name	= KBUILD_MODNAME,
+	.id_table	= rpmsg_driver_sample_id_table,
+	.probe		= rpmsg_raw_probe,
+	.callback	= rpmsg_raw_cb,
+	.remove		= rpmsg_raw_remove,
+};
+
+static int rpmsg_raw_init(void)
+{
+	int ret;
+
+	ret = alloc_chrdev_region(&rpmsg_raw_major, 0, RPMSG_DEV_MAX,
+				  "rpmsg");
+	if (ret < 0) {
+		pr_err("rpmsg: failed to allocate char dev region\n");
+		return ret;
+	}
+
+	ret = register_rpmsg_driver(&rpmsg_raw_client);
+	if (ret < 0)
+		unregister_chrdev_region(rpmsg_raw_major, RPMSG_DEV_MAX);
+
+	return ret;
+}
+module_init(rpmsg_raw_init);
+
+static void rpmsg_raw_exit(void)
+{
+	unregister_rpmsg_driver(&rpmsg_raw_client);
+	unregister_chrdev_region(rpmsg_raw_major, RPMSG_DEV_MAX);
+}
+module_exit(rpmsg_raw_exit);
+
+MODULE_DESCRIPTION("RPMSG raw service driver");
+MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
+MODULE_ALIAS("rpmsg_raw");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 02/13] rpmsg: introduce rpmsg_control driver for channel creation
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 01/13] rpmsg: introduce rpmsg raw driver Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 15:56   ` Randy Dunlap
  2020-07-31 12:10 ` [PATCH 03/13] rpmsg: add helper to create the rpmsg ctrl device Arnaud Pouliquen
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

Create a RPMsg driver that will offer to the userspace applications an
ioctl to manage channels.
As a first step, this driver just creates the /dev/rpmsg_ctl<x>
( <x> is the instance value). The ioctl is not implemented.

Notice that this driver is associated to a RPMsg device with no endpoint.
Instantiating this device as an RPMsg device allows to retrieve the
associated RPMsg backend.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/Kconfig      |   8 ++
 drivers/rpmsg/Makefile     |   1 +
 drivers/rpmsg/rpmsg_ctrl.c | 209 +++++++++++++++++++++++++++++++++++++
 3 files changed, 218 insertions(+)
 create mode 100644 drivers/rpmsg/rpmsg_ctrl.c

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 900ec8f54081..c5afbf24e793 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -23,6 +23,14 @@ config RPMSG_NS
 	  channel that probes the associate RPMsg device on remote endpoint
 	  service announcement.
 
+config RPMSG_CTRL
+	tristate "RPMSG control interface"
+	depends on RPMSG
+	help
+	  Say Y here to enable the support of the name service announcement
+	  channel that probe the associate RPMsg device on remote endpoint
+	  service announcement.
+
 config RPMSG_RAW
 	tristate "RPMSG raw service driver"
 	depends on RPMSG
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index d75f0a65e71d..dc5228022dac 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -2,6 +2,7 @@
 obj-$(CONFIG_RPMSG)		+= rpmsg_core.o
 obj-$(CONFIG_RPMSG_CHAR)	+= rpmsg_char.o
 obj-$(CONFIG_RPMSG_NS)		+= rpmsg_ns.o
+obj-$(CONFIG_RPMSG_CTRL)	+= rpmsg_ctrl.o
 obj-$(CONFIG_RPMSG_MTK_SCP)	+= mtk_rpmsg.o
 qcom_glink-objs			:= qcom_glink_native.o qcom_glink_ssr.o
 obj-$(CONFIG_RPMSG_QCOM_GLINK) += qcom_glink.o
diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
new file mode 100644
index 000000000000..d31b1ba51fa7
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_ctrl.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2020
+ */
+#include <linux/cdev.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "rpmsg_internal.h"
+#include <uapi/linux/rpmsg.h>
+
+#define RPMSG_DEV_MAX	(MINORMASK + 1)
+
+#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrl_dev, dev)
+#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrl_dev, cdev)
+
+/**
+ * struct rpmsg_ctrl_dev - control device for instantiating endpoint devices
+ * @rpdev:	underlaying rpmsg device
+ * @cdev:	cdev for the ctrl device
+ * @dev:	device for the ctrl device
+ */
+struct rpmsg_ctrl_dev {
+	struct rpmsg_device *rpdev;
+	struct cdev cdev;
+	struct device dev;
+};
+
+static DEFINE_IDA(rpmsg_ctrl_ida);
+static DEFINE_IDA(rpmsg_minor_ida);
+
+static dev_t rpmsg_major;
+
+static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
+{
+	struct rpmsg_ctrl_dev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
+
+	get_device(&ctrldev->dev);
+	filp->private_data = ctrldev;
+
+	return 0;
+}
+
+static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
+				 unsigned long arg)
+{
+	struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
+
+	dev_info(&ctrldev->dev, "Control not yet implemented\n");
+
+	return 0;
+};
+
+static int rpmsg_ctrl_dev_release(struct inode *inode, struct file *filp)
+{
+	struct rpmsg_ctrl_dev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
+
+	put_device(&ctrldev->dev);
+
+	return 0;
+}
+
+static void rpmsg_ctrl_dev_release_device(struct device *dev)
+{
+	struct rpmsg_ctrl_dev *ctrldev = dev_to_ctrldev(dev);
+
+	dev_err(dev, "%s\n", __func__);
+
+	ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
+	ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
+	cdev_del(&ctrldev->cdev);
+	kfree(ctrldev);
+}
+
+static const struct file_operations rpmsg_ctrl_fops = {
+	.owner = THIS_MODULE,
+	.open = rpmsg_ctrl_dev_open,
+	.release = rpmsg_ctrl_dev_release,
+	.unlocked_ioctl = rpmsg_ctrl_dev_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
+};
+
+static int rpmsg_ctrl_add_control(struct rpmsg_ctrl_dev *ctrldev)
+{
+	struct device *dev = &ctrldev->dev;
+	int ret;
+
+	cdev_init(&ctrldev->cdev, &rpmsg_ctrl_fops);
+	ctrldev->cdev.owner = THIS_MODULE;
+
+	ret = ida_simple_get(&rpmsg_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL);
+	if (ret < 0)
+		return ret;
+	dev->devt = MKDEV(MAJOR(rpmsg_major), ret);
+
+	dev_set_name(dev, "rpmsg_ctrl%d", dev->id);
+
+	ret = cdev_add(&ctrldev->cdev, dev->devt, 1);
+	if (ret)
+		goto free_minor_ida;
+
+	dev_info(dev, "add %s control for %s driver\n",
+		 dev_name(dev),  dev_name(dev->parent));
+
+	return 0;
+
+free_minor_ida:
+	ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
+
+	return ret;
+}
+
+static int rpmsg_ctrl_probe(struct rpmsg_device *rpdev)
+{
+	struct rpmsg_ctrl_dev *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;
+
+	ret = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL);
+	if (ret < 0)
+		goto free_ctrldev;
+
+	dev->id = ret;
+
+	ret = rpmsg_ctrl_add_control(ctrldev);
+	if (ret < 0)
+		goto free_ctrl_ida;
+
+	/* We can now rely on the release function for cleanup */
+	dev->release = rpmsg_ctrl_dev_release_device;
+
+	ret = device_add(dev);
+	if (ret) {
+		dev_err(&rpdev->dev, "device_add failed: %d\n", ret);
+		put_device(dev);
+		goto free_ctrl_ida;
+	}
+
+	dev_set_drvdata(dev, ctrldev);
+	dev_set_drvdata(&rpdev->dev, ctrldev);
+
+	return 0;
+
+free_ctrl_ida:
+	ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
+free_ctrldev:
+	put_device(dev);
+	kfree(ctrldev);
+
+	return ret;
+}
+
+static void rpmsg_ctrl_remove(struct rpmsg_device *rpdev)
+{
+	struct rpmsg_ctrl_dev *ctrldev = dev_get_drvdata(&rpdev->dev);
+
+	device_del(&ctrldev->dev);
+	put_device(&ctrldev->dev);
+}
+
+static struct rpmsg_driver rpmsg_ctrl_driver = {
+	.probe = rpmsg_ctrl_probe,
+	.remove = rpmsg_ctrl_remove,
+	.drv = {
+		.name = "rpmsg_ctrl",
+	},
+};
+
+static int rpmsg_ctrl_init(void)
+{
+	int ret;
+
+	ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg");
+	if (ret < 0) {
+		pr_err("rpmsg: failed to allocate char dev region\n");
+		return ret;
+	}
+
+	ret = register_rpmsg_driver(&rpmsg_ctrl_driver);
+	if (ret < 0) {
+		pr_err("rpmsgchr: failed to register rpmsg driver\n");
+		unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
+	}
+
+	return ret;
+}
+postcore_initcall(rpmsg_ctrl_init);
+
+static void rpmsg_ctrl_exit(void)
+{
+	unregister_rpmsg_driver(&rpmsg_ctrl_driver);
+	unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
+}
+module_exit(rpmsg_ctrl_exit);
+
+MODULE_DESCRIPTION("Ioctl rpmsg driver");
+MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
+MODULE_ALIAS("rpmsg_ctl");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 03/13] rpmsg: add helper to create the rpmsg ctrl device
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 01/13] rpmsg: introduce rpmsg raw driver Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 02/13] rpmsg: introduce rpmsg_control driver for channel creation Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 04/13] rpmsg: virtio: probe the rpmsg_ctrl device Arnaud Pouliquen
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

This function creates the rpmsg_ctl device using the
driver_override to link device to the driver.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/rpmsg_internal.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index d1549e5cb607..811d6e27a720 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -119,6 +119,21 @@ static inline int rpmsg_ns_register_device(struct rpmsg_device *rpdev)
 	return rpmsg_register_device(rpdev);
 }
 
+/**
+ * rpmsg_ctl_register_device() - register control device based on rpdev
+ * @rpdev:	prepared rpdev to be used for creating endpoints
+ *
+ * This function wraps rpmsg_register_device() preparing the rpdev for use as
+ * a control rpmsg driver forcing the channel name.
+ */
+static inline int rpmsg_ctl_register_device(struct rpmsg_device *rpdev)
+{
+	strcpy(rpdev->id.name, "rpmsg_ctrl");
+	rpdev->driver_override = "rpmsg_ctrl";
+
+	return rpmsg_register_device(rpdev);
+}
+
 int rpmsg_ns_announce_create(struct rpmsg_device *rpdev);
 int rpmsg_ns_announce_destroy(struct rpmsg_device *rpdev);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 04/13] rpmsg: virtio: probe the rpmsg_ctrl device
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (2 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 03/13] rpmsg: add helper to create the rpmsg ctrl device Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 05/13] rpmsg: uapi: add service param for create destroy ioctls Arnaud Pouliquen
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

Probe the rpmsg_ctrl driver on virtio rpmsg bus creation.
This provides the possibility to expose an ioctrl to create
RPMsg channels.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 36 +++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 3c771a6392be..eaeaefdabf18 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -771,6 +771,36 @@ static void rpmsg_xmit_done(struct virtqueue *svq)
 	wake_up_interruptible(&vrp->sendq);
 }
 
+static struct rpmsg_device *rpmsg_virtio_add_ctrl_dev(struct virtio_device *vdev)
+{
+	struct virtproc_info *vrp = vdev->priv;
+	struct virtio_rpmsg_channel *vch;
+	struct rpmsg_device *rpdev_ctrl;
+	int err = 0;
+
+	vch = kzalloc(sizeof(*vch), GFP_KERNEL);
+	if (!vch)
+		return ERR_PTR(-ENOMEM);
+
+	/* Link the channel to our vrp */
+	vch->vrp = vrp;
+
+	/* Assign public information to the rpmsg_device */
+	rpdev_ctrl = &vch->rpdev;
+	rpdev_ctrl->ops = &virtio_rpmsg_w_nsa_ops;
+
+	rpdev_ctrl->dev.parent = &vrp->vdev->dev;
+	rpdev_ctrl->dev.release = virtio_rpmsg_release_device;
+
+	err = rpmsg_ctl_register_device(rpdev_ctrl);
+	if (err) {
+		kfree(vch);
+		return ERR_PTR(err);
+	}
+
+	return rpdev_ctrl;
+}
+
 static int rpmsg_probe(struct virtio_device *vdev)
 {
 	vq_callback_t *vq_cbs[] = { rpmsg_recv_done, rpmsg_xmit_done };
@@ -778,7 +808,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
 	struct virtqueue *vqs[2];
 	struct virtproc_info *vrp;
 	struct virtio_rpmsg_channel *vch;
-	struct rpmsg_device *rpdev_ns;
+	struct rpmsg_device *rpdev_ns, *rpdev_ctrl;
 	void *bufs_va;
 	int err = 0, i;
 	size_t total_buf_space;
@@ -852,6 +882,10 @@ static int rpmsg_probe(struct virtio_device *vdev)
 
 	vdev->priv = vrp;
 
+	rpdev_ctrl = rpmsg_virtio_add_ctrl_dev(vdev);
+	if (IS_ERR(rpdev_ctrl))
+		goto free_coherent;
+
 	/* if supported by the remote processor, enable the name service */
 	if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)) {
 		vch = kzalloc(sizeof(*vch), GFP_KERNEL);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 05/13] rpmsg: uapi: add service param for create destroy ioctls
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (3 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 04/13] rpmsg: virtio: probe the rpmsg_ctrl device Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 06/13] rpmsg: add RPMsg control info structure Arnaud Pouliquen
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

To allow to associate an endpoint creation to a service, add
a new parameter in rpmsg_endpoint_info struct.
For each RPMsg service driver that want to support the ioctl interface
a new service will have to be added.
The  RPMSG_START_PRIVATE_SERVICES is used to allow developer to add is
own services with ID higher or equal to 1024.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 include/uapi/linux/rpmsg.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
index e14c6dab4223..2ccc10ffacd4 100644
--- a/include/uapi/linux/rpmsg.h
+++ b/include/uapi/linux/rpmsg.h
@@ -9,16 +9,32 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
+/**
+ * enum rpmsg_services - list of supported RPMsg services
+ *
+ * @RPMSG_RAW_SERVICE: char device RPMSG service
+ * @RPMSG_START_PRIVATE_SERVICES: private services have to be declared after.
+ */
+enum rpmsg_services {
+	/* Reserved services */
+	RPMSG_RAW_SERVICE =  0,
+
+	/* Private services */
+	RPMSG_START_PRIVATE_SERVICES =  1024,
+};
+
 /**
  * struct rpmsg_endpoint_info - endpoint info representation
  * @name: name of service
  * @src: local address
  * @dst: destination address
+ * @service: associated RPMsg service
  */
 struct rpmsg_endpoint_info {
 	char name[32];
 	__u32 src;
 	__u32 dst;
+	__u32 service;
 };
 
 #define RPMSG_CREATE_EPT_IOCTL	_IOW(0xb5, 0x1, struct rpmsg_endpoint_info)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 06/13] rpmsg: add RPMsg control info structure
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (4 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 05/13] rpmsg: uapi: add service param for create destroy ioctls Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 07/13] rpmsg: control: add driver registration API Arnaud Pouliquen
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

Add new structure for RPMsg driver registration.
This structure will be used to link a service to its driver.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 include/linux/rpmsg.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 5496d27c6f8c..ef8d1b987d38 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -34,6 +34,19 @@ struct rpmsg_endpoint;
 struct rpmsg_device_ops;
 struct rpmsg_endpoint_ops;
 
+/**
+ * struct rpmsg_drv_ctrl_info - rpmsg ctrl structure
+ * @drv_name:	name of the associated driver
+ * @service:	the associated rpmsg service listed in @rpmsg_services
+ *
+ * This structure is used by rpmsg_ctl to link the endpoint creation to the
+ * service rpmsg driver.
+ */
+struct rpmsg_drv_ctrl_info {
+	const char *drv_name;
+	u32  service;
+};
+
 /**
  * struct rpmsg_channel_info - channel info representation
  * @name: name of service
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 07/13] rpmsg: control: add driver registration API
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (5 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 06/13] rpmsg: add RPMsg control info structure Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 08/13] rpmsg: raw: register service to the rpmsg control Arnaud Pouliquen
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

Add API for RPMsg driver to register the supported service.
This API has to be called during RPMsg driver init to declare the
service. Then the RPMsg control will be able to instantiate
associated device.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/rpmsg_ctrl.c     | 57 ++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h |  3 ++
 2 files changed, 60 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
index d31b1ba51fa7..8773c8395401 100644
--- a/drivers/rpmsg/rpmsg_ctrl.c
+++ b/drivers/rpmsg/rpmsg_ctrl.c
@@ -26,6 +26,20 @@ struct rpmsg_ctrl_dev {
 	struct device dev;
 };
 
+/**
+ * struct rpmsg_ctl_info - control info list node
+ * @ctrl:	control driver info
+ * @node:	list node
+ *
+ * This structure is used by rpmsg_ctl to list the registered drivers services
+ */
+struct rpmsg_ctl_info {
+	const struct rpmsg_drv_ctrl_info *ctrl;
+	struct list_head node;
+};
+
+static LIST_HEAD(rpmsg_drv_list);
+
 static DEFINE_IDA(rpmsg_ctrl_ida);
 static DEFINE_IDA(rpmsg_minor_ida);
 
@@ -176,6 +190,49 @@ static struct rpmsg_driver rpmsg_ctrl_driver = {
 	},
 };
 
+/**
+ * rpmsg_ctrl_register_ctl() -register control for the associated service
+ * @ctrl: rpmsg driver information
+ *
+ * This function is called by the rpmsg driver to register a service that will
+ * be exposed to be instantiate by the application.
+ */
+int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)
+{
+	struct rpmsg_ctl_info *drv_info;
+
+	drv_info =  kzalloc(sizeof(*drv_info), GFP_KERNEL);
+	if (!drv_info)
+		return -ENOMEM;
+
+	drv_info->ctrl = ctrl;
+
+	list_add_tail(&drv_info->node, &rpmsg_drv_list);
+
+	return 0;
+}
+EXPORT_SYMBOL(rpmsg_ctrl_register_ctl);
+
+/**
+ * rpmsg_ctrl_unregister_ctl() -unregister control for the associated service
+ * @ctrl: the rpmsg control information
+ *
+ * This function is called by the rpmsg driver to unregister the associated
+ * service.
+ */
+void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)
+{
+	struct rpmsg_ctl_info *drv_info, *tmp;
+
+	list_for_each_entry_safe(drv_info, tmp, &rpmsg_drv_list, node) {
+		if (drv_info->ctrl == ctrl) {
+			list_del(&drv_info->node);
+			kfree(drv_info);
+		}
+	}
+}
+EXPORT_SYMBOL(rpmsg_ctrl_unregister_ctl);
+
 static int rpmsg_ctrl_init(void)
 {
 	int ret;
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 811d6e27a720..2f22ad45cb18 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -137,4 +137,7 @@ static inline int rpmsg_ctl_register_device(struct rpmsg_device *rpdev)
 int rpmsg_ns_announce_create(struct rpmsg_device *rpdev);
 int rpmsg_ns_announce_destroy(struct rpmsg_device *rpdev);
 
+int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl);
+void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl);
+
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 08/13] rpmsg: raw: register service to the rpmsg control
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (6 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 07/13] rpmsg: control: add driver registration API Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 09/13] rpmsg: add override field in channel info Arnaud Pouliquen
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

Register the RPMSG_RAW_SERVICE service to the RPMsg control

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/rpmsg_raw.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/rpmsg_raw.c b/drivers/rpmsg/rpmsg_raw.c
index 8684a78ab4d1..117da0c566ed 100644
--- a/drivers/rpmsg/rpmsg_raw.c
+++ b/drivers/rpmsg/rpmsg_raw.c
@@ -315,6 +315,11 @@ static struct rpmsg_driver rpmsg_raw_client = {
 	.remove		= rpmsg_raw_remove,
 };
 
+const struct rpmsg_drv_ctrl_info  rpmsg_raw_ctl_info = {
+	.drv_name = KBUILD_MODNAME,
+	.service = RPMSG_RAW_SERVICE,
+};
+
 static int rpmsg_raw_init(void)
 {
 	int ret;
@@ -328,7 +333,18 @@ static int rpmsg_raw_init(void)
 
 	ret = register_rpmsg_driver(&rpmsg_raw_client);
 	if (ret < 0)
-		unregister_chrdev_region(rpmsg_raw_major, RPMSG_DEV_MAX);
+		goto free_region;
+
+	ret = rpmsg_ctrl_register_ctl(&rpmsg_raw_ctl_info);
+	if (ret < 0)
+		goto free_rpmsg;
+
+	return 0;
+
+free_rpmsg:
+	unregister_rpmsg_driver(&rpmsg_raw_client);
+free_region:
+	unregister_chrdev_region(rpmsg_raw_major, RPMSG_DEV_MAX);
 
 	return ret;
 }
@@ -336,6 +352,7 @@ module_init(rpmsg_raw_init);
 
 static void rpmsg_raw_exit(void)
 {
+	rpmsg_ctrl_unregister_ctl(&rpmsg_raw_ctl_info);
 	unregister_rpmsg_driver(&rpmsg_raw_client);
 	unregister_chrdev_region(rpmsg_raw_major, RPMSG_DEV_MAX);
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 09/13] rpmsg: add override field in channel info
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (7 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 08/13] rpmsg: raw: register service to the rpmsg control Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 10/13] rpmsg: ns: initialize channel info override field Arnaud Pouliquen
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

The override field is already used in the rpmsg_device.
This allows to force a service name to be associated to
a RPMsg service driver.
Adding this field in the channel info allows to force the channel
creation with a specified RPMsg service driver.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 include/linux/rpmsg.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index ef8d1b987d38..4a34a8ea330f 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -52,11 +52,13 @@ struct rpmsg_drv_ctrl_info {
  * @name: name of service
  * @src: local address
  * @dst: destination address
+ * @driver_override: driver name to force a match
  */
 struct rpmsg_channel_info {
 	char name[RPMSG_NAME_SIZE];
 	u32 src;
 	u32 dst;
+	const char *driver_override;
 };
 
 /**
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 10/13] rpmsg: ns: initialize channel info override field
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (8 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 09/13] rpmsg: add override field in channel info Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 11/13] rpmsg: virtio: use the driver_override in channel creation Arnaud Pouliquen
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

By default driver_override should be 0 to avoid to force
the channel creation with a specified name.The local variable
is not initialized.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/rpmsg_ns.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rpmsg/rpmsg_ns.c b/drivers/rpmsg/rpmsg_ns.c
index b478e2b55213..ace237854f88 100644
--- a/drivers/rpmsg/rpmsg_ns.c
+++ b/drivers/rpmsg/rpmsg_ns.c
@@ -103,6 +103,7 @@ static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 	strncpy(chinfo.name, msg->name, sizeof(chinfo.name));
 	chinfo.src = RPMSG_ADDR_ANY;
 	chinfo.dst = le32_to_cpu(msg->addr);
+	chinfo.driver_override = NULL;
 
 	dev_info(dev, "%sing channel %s addr 0x%x\n",
 		 flags & RPMSG_NS_DESTROY ? "destroy" : "creat",
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 11/13] rpmsg: virtio: use the driver_override in channel creation
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (9 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 10/13] rpmsg: ns: initialize channel info override field Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 12/13] rpmsg: control: implement the ioctrl function to create device Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 13/13] rpmsg: ctrl: add support of the endpoints release Arnaud Pouliquen
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

Use the override information from the channel info structure
to set the rpdev override and so link the channel to a specific
driver.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index eaeaefdabf18..dbf7a597ae74 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -352,6 +352,7 @@ __rpmsg_create_channel(struct virtproc_info *vrp,
 	rpdev = &vch->rpdev;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
+	rpdev->driver_override = (char *)chinfo->driver_override;
 	if (virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS))
 		rpdev->ops = &virtio_rpmsg_w_nsa_ops;
 	else
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 12/13] rpmsg: control: implement the ioctrl function to create device
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (10 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 11/13] rpmsg: virtio: use the driver_override in channel creation Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  2020-07-31 12:10 ` [PATCH 13/13] rpmsg: ctrl: add support of the endpoints release Arnaud Pouliquen
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

Implement the ioctrl function that parses the list of
rpmsg drivers registered to create an associated device.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/rpmsg_ctrl.c | 39 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
index 8773c8395401..d2a6dbb8798f 100644
--- a/drivers/rpmsg/rpmsg_ctrl.c
+++ b/drivers/rpmsg/rpmsg_ctrl.c
@@ -55,12 +55,47 @@ static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
 	return 0;
 }
 
+static const char *rpmsg_ctrl_get_drv_name(u32 service)
+{
+	struct rpmsg_ctl_info *drv_info;
+
+	list_for_each_entry(drv_info, &rpmsg_drv_list, node) {
+		if (drv_info->ctrl->service == service)
+			return drv_info->ctrl->drv_name;
+	}
+
+	return NULL;
+}
+
 static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
 				 unsigned long arg)
 {
 	struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
-
-	dev_info(&ctrldev->dev, "Control not yet implemented\n");
+	void __user *argp = (void __user *)arg;
+	struct rpmsg_channel_info chinfo;
+	struct rpmsg_endpoint_info eptinfo;
+	struct rpmsg_device *newch;
+
+	if (cmd != RPMSG_CREATE_EPT_IOCTL)
+		return -EINVAL;
+
+	if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
+		return -EFAULT;
+
+	chinfo.driver_override = rpmsg_ctrl_get_drv_name(eptinfo.service);
+	if (!chinfo.driver_override)
+		return -ENODEV;
+
+	memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
+	chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
+	chinfo.src = eptinfo.src;
+	chinfo.dst = eptinfo.dst;
+
+	newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
+	if (!newch) {
+		dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
+		return -ENXIO;
+	}
 
 	return 0;
 };
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 13/13] rpmsg: ctrl: add support of the endpoints release
  2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
                   ` (11 preceding siblings ...)
  2020-07-31 12:10 ` [PATCH 12/13] rpmsg: control: implement the ioctrl function to create device Arnaud Pouliquen
@ 2020-07-31 12:10 ` Arnaud Pouliquen
  12 siblings, 0 replies; 15+ messages in thread
From: Arnaud Pouliquen @ 2020-07-31 12:10 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, arnaud.pouliquen

Add the support of the release of an endpoint using the ioctl
interface.
The endpoint is identified using its name, its source address
and is destination address.
To support legacy a new ioctl ioctl is created instead of updating
RPMSG_DESTROY_EPT_IOCTL.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
 drivers/rpmsg/rpmsg_ctrl.c | 35 ++++++++++++++++++++++++-----------
 include/uapi/linux/rpmsg.h |  1 +
 2 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
index d2a6dbb8798f..d696247970c2 100644
--- a/drivers/rpmsg/rpmsg_ctrl.c
+++ b/drivers/rpmsg/rpmsg_ctrl.c
@@ -75,26 +75,39 @@ static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
 	struct rpmsg_channel_info chinfo;
 	struct rpmsg_endpoint_info eptinfo;
 	struct rpmsg_device *newch;
-
-	if (cmd != RPMSG_CREATE_EPT_IOCTL)
-		return -EINVAL;
+	int ret;
 
 	if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
 		return -EFAULT;
 
-	chinfo.driver_override = rpmsg_ctrl_get_drv_name(eptinfo.service);
-	if (!chinfo.driver_override)
-		return -ENODEV;
-
 	memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
 	chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
 	chinfo.src = eptinfo.src;
 	chinfo.dst = eptinfo.dst;
 
-	newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
-	if (!newch) {
-		dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
-		return -ENXIO;
+	switch (cmd) {
+	case RPMSG_CREATE_EPT_IOCTL:
+		chinfo.driver_override =
+				rpmsg_ctrl_get_drv_name(eptinfo.service);
+		if (!chinfo.driver_override)
+			return -ENODEV;
+
+		newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
+		if (!newch) {
+			dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
+			return -ENXIO;
+		}
+		break;
+	case RPMSG_RELEASE_EPT_IOCTL:
+		ret = rpmsg_release_channel(ctrldev->rpdev, &chinfo);
+		if (ret) {
+			dev_err(&ctrldev->dev,
+				"rpmsg_release_channel failed: %d\n", ret);
+			return ret;
+		}
+		break;
+	default:
+		return -EINVAL;
 	}
 
 	return 0;
diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
index 2ccc10ffacd4..74d821ee5f8c 100644
--- a/include/uapi/linux/rpmsg.h
+++ b/include/uapi/linux/rpmsg.h
@@ -39,5 +39,6 @@ struct rpmsg_endpoint_info {
 
 #define RPMSG_CREATE_EPT_IOCTL	_IOW(0xb5, 0x1, struct rpmsg_endpoint_info)
 #define RPMSG_DESTROY_EPT_IOCTL	_IO(0xb5, 0x2)
+#define RPMSG_RELEASE_EPT_IOCTL	_IOW(0xb5, 0x3, struct rpmsg_endpoint_info)
 
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 02/13] rpmsg: introduce rpmsg_control driver for channel creation
  2020-07-31 12:10 ` [PATCH 02/13] rpmsg: introduce rpmsg_control driver for channel creation Arnaud Pouliquen
@ 2020-07-31 15:56   ` Randy Dunlap
  0 siblings, 0 replies; 15+ messages in thread
From: Randy Dunlap @ 2020-07-31 15:56 UTC (permalink / raw)
  To: Arnaud Pouliquen, Bjorn Andersson, Ohad Ben-Cohen, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32

On 7/31/20 5:10 AM, Arnaud Pouliquen wrote:
> diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> index 900ec8f54081..c5afbf24e793 100644
> --- a/drivers/rpmsg/Kconfig
> +++ b/drivers/rpmsg/Kconfig
> @@ -23,6 +23,14 @@ config RPMSG_NS
>  	  channel that probes the associate RPMsg device on remote endpoint
>  	  service announcement.
>  
> +config RPMSG_CTRL
> +	tristate "RPMSG control interface"
> +	depends on RPMSG
> +	help
> +	  Say Y here to enable the support of the name service announcement
> +	  channel that probe the associate RPMsg device on remote endpoint

	               probes the associated

> +	  service announcement.
> +
>  config RPMSG_RAW
>  	tristate "RPMSG raw service driver"
>  	depends on RPMSG


-- 
~Randy


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-07-31 15:57 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-31 12:10 [PATCH 00/13] introduce IOCTL interface for RPMsg channel management Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 01/13] rpmsg: introduce rpmsg raw driver Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 02/13] rpmsg: introduce rpmsg_control driver for channel creation Arnaud Pouliquen
2020-07-31 15:56   ` Randy Dunlap
2020-07-31 12:10 ` [PATCH 03/13] rpmsg: add helper to create the rpmsg ctrl device Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 04/13] rpmsg: virtio: probe the rpmsg_ctrl device Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 05/13] rpmsg: uapi: add service param for create destroy ioctls Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 06/13] rpmsg: add RPMsg control info structure Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 07/13] rpmsg: control: add driver registration API Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 08/13] rpmsg: raw: register service to the rpmsg control Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 09/13] rpmsg: add override field in channel info Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 10/13] rpmsg: ns: initialize channel info override field Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 11/13] rpmsg: virtio: use the driver_override in channel creation Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 12/13] rpmsg: control: implement the ioctrl function to create device Arnaud Pouliquen
2020-07-31 12:10 ` [PATCH 13/13] rpmsg: ctrl: add support of the endpoints release 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).