linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/10] Introduction of rpmsg flow control service
@ 2022-05-20  8:29 Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 01/10] rpmsg: core: Add signal API support Arnaud Pouliquen
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

This series proposes an implementation for the rpmsg virtio transport
backend, of the signaling API proposed by Deepak Kumar Singh:
"rpmsg and glink signaling API support" [1]

The aim of the series is to offer the possibility for an endpoint to inform
a remote endpoint about its state, based on a software flow control[2].

For this a new rpmsg service( with a fixed address 64) is proposed.
It is responsible for:
- transmitting local endpoint flow control information to the remote side,
- informing a local endpoint about a remote endpoint flow control.

For the rpmsg virtio transport layer the service is negotiated thanks to the 
virtio feature flag: VIRTIO_RPMSG_F_FC

Notice that this pull request introduces new feature in the rpmsg protocol,
So it has to be aligned with OpenAMP implementation.
Pending OpenAMP pull request is available here:
https://github.com/OpenAMP/open-amp/pull/394


[1]https://lkml.org/lkml/2022/1/18/867
[2]https://en.wikipedia.org/wiki/Software_flow_control

Arnaud Pouliquen (8):
  rpmsg: core: Add rpmsg device remote flow control announcement ops
  rpmsg: virtio: Implement the announce_remote_fc ops
  rpmsg: Introduce flow control channel driver
  rpmsg: virtio: Add support of the VIRTIO_RPMSG_F_FC feature
  rpmsg: virtio: Implement the set_flow_control ops
  rpmsg: Add the destination address in rpmsg_set_flow_control
  rpmsg: tty : Add the support of the flow control
  rpmsg: virtio: Set default dst address on flow control

Deepak Kumar Singh (2):
  rpmsg: core: Add signal API support
  rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

 drivers/rpmsg/Kconfig            |  11 +++
 drivers/rpmsg/Makefile           |   1 +
 drivers/rpmsg/rpmsg_char.c       |  56 +++++++++++++--
 drivers/rpmsg/rpmsg_core.c       |  47 +++++++++++++
 drivers/rpmsg/rpmsg_fc.c         | 113 +++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   |   9 +++
 drivers/rpmsg/virtio_rpmsg_bus.c | 111 +++++++++++++++++++++++++++++-
 drivers/tty/rpmsg_tty.c          |  50 ++++++++++++++
 include/linux/rpmsg.h            |  15 ++++
 include/linux/rpmsg/fc.h         |  51 ++++++++++++++
 10 files changed, 456 insertions(+), 8 deletions(-)
 create mode 100644 drivers/rpmsg/rpmsg_fc.c
 create mode 100644 include/linux/rpmsg/fc.h

-- 
2.25.1


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

* [RFC PATCH 01/10] rpmsg: core: Add signal API support
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 02/10] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support Arnaud Pouliquen
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

From: Deepak Kumar Singh <quic_deesin@quicinc.com>

Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.
Local glink client drivers can send and receive signals to glink
clients running on remote processors.

Add APIs to support sending and receiving of signals by rpmsg clients.

Signed-off-by: Deepak Kumar Singh <quic_deesin@quicinc.com>
---
 drivers/rpmsg/rpmsg_core.c     | 21 +++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h |  2 ++
 include/linux/rpmsg.h          | 15 +++++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 79368a957d89..8de8aadd9b27 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -330,6 +330,24 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
+/**
+ * rpmsg_set_flow_control() - sets/clears serial flow control signals
+ * @ept:	the rpmsg endpoint
+ * @enable:	enable or disable serial flow control
+ *
+ * Return: 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable)
+{
+	if (WARN_ON(!ept))
+		return -EINVAL;
+	if (!ept->ops->set_flow_control)
+		return -ENXIO;
+
+	return ept->ops->set_flow_control(ept, enable);
+}
+EXPORT_SYMBOL(rpmsg_set_flow_control);
+
 /**
  * rpmsg_get_mtu() - get maximum transmission buffer size for sending message.
  * @ept: the rpmsg endpoint
@@ -538,6 +556,9 @@ static int rpmsg_dev_probe(struct device *dev)
 
 		rpdev->ept = ept;
 		rpdev->src = ept->addr;
+
+		if (rpdrv->signals)
+			ept->sig_cb = rpdrv->signals;
 	}
 
 	err = rpdrv->probe(rpdev);
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index d4b23fd019a8..4ce58e68af30 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -55,6 +55,7 @@ struct rpmsg_device_ops {
  * @trysendto:		see @rpmsg_trysendto(), optional
  * @trysend_offchannel:	see @rpmsg_trysend_offchannel(), optional
  * @poll:		see @rpmsg_poll(), optional
+ * @set_flow_control:	see @rpmsg_set_flow_control(), optional
  * @get_mtu:		see @rpmsg_get_mtu(), optional
  *
  * Indirection table for the operations that a rpmsg backend should implement.
@@ -75,6 +76,7 @@ struct rpmsg_endpoint_ops {
 			     void *data, int len);
 	__poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp,
 			     poll_table *wait);
+	int (*set_flow_control)(struct rpmsg_endpoint *ept, bool enable);
 	ssize_t (*get_mtu)(struct rpmsg_endpoint *ept);
 };
 
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 02fa9116cd60..dbd0c591bb85 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -62,12 +62,14 @@ struct rpmsg_device {
 };
 
 typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
+typedef int (*rpmsg_rx_sig_t)(struct rpmsg_device *, void *, u32);
 
 /**
  * struct rpmsg_endpoint - binds a local rpmsg address to its user
  * @rpdev: rpmsg channel device
  * @refcount: when this drops to zero, the ept is deallocated
  * @cb: rx callback handler
+ * @sig_cb: rx serial signal handler
  * @cb_lock: must be taken before accessing/changing @cb
  * @addr: local rpmsg address
  * @priv: private data for the driver's use
@@ -90,6 +92,7 @@ struct rpmsg_endpoint {
 	struct rpmsg_device *rpdev;
 	struct kref refcount;
 	rpmsg_rx_cb_t cb;
+	rpmsg_rx_sig_t sig_cb;
 	struct mutex cb_lock;
 	u32 addr;
 	void *priv;
@@ -104,6 +107,7 @@ struct rpmsg_endpoint {
  * @probe: invoked when a matching rpmsg channel (i.e. device) is found
  * @remove: invoked when the rpmsg channel is removed
  * @callback: invoked when an inbound message is received on the channel
+ * @signal:  invoked to received remote flow control signaling.
  */
 struct rpmsg_driver {
 	struct device_driver drv;
@@ -111,6 +115,7 @@ struct rpmsg_driver {
 	int (*probe)(struct rpmsg_device *dev);
 	void (*remove)(struct rpmsg_device *dev);
 	int (*callback)(struct rpmsg_device *, void *, int, void *, u32);
+	int (*signals)(struct rpmsg_device *rpdev, void *priv, u32 state);
 };
 
 static inline u16 rpmsg16_to_cpu(struct rpmsg_device *rpdev, __rpmsg16 val)
@@ -188,6 +193,8 @@ __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp,
 
 ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept);
 
+int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable);
+
 #else
 
 static inline int rpmsg_register_device(struct rpmsg_device *rpdev)
@@ -306,6 +313,14 @@ static inline ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept)
 	return -ENXIO;
 }
 
+static inline int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+
+	return -ENXIO;
+}
+
 #endif /* IS_ENABLED(CONFIG_RPMSG) */
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
-- 
2.25.1


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

* [RFC PATCH 02/10] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 01/10] rpmsg: core: Add signal API support Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 03/10] rpmsg: core: Add rpmsg device remote flow control announcement ops Arnaud Pouliquen
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

From: Deepak Kumar Singh <quic_deesin@quicinc.com>

Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Chris Lew <quic_clew@quicinc.com>
Signed-off-by: Deepak Kumar Singh <quic_deesin@quicinc.com>
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 drivers/rpmsg/rpmsg_char.c | 56 +++++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 7 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index b6183d4f62a2..904e7c67b356 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -23,6 +23,7 @@
 #include <linux/rpmsg.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
+#include <linux/termios.h>
 #include <linux/uaccess.h>
 #include <uapi/linux/rpmsg.h>
 
@@ -52,6 +53,8 @@ static DEFINE_IDA(rpmsg_minor_ida);
  * @readq:	wait object for incoming queue
  * @default_ept: set to channel default endpoint if the default endpoint should be re-used
  *              on device open to prevent endpoint address update.
+ * @rsigs: remote flow control state
+ * @sig_pending: inform that flow control information has been received from remote but not treated
  */
 struct rpmsg_eptdev {
 	struct device dev;
@@ -68,6 +71,8 @@ struct rpmsg_eptdev {
 	struct sk_buff_head queue;
 	wait_queue_head_t readq;
 
+	u32 rsigs;
+	bool sig_pending;
 };
 
 int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data)
@@ -107,7 +112,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
 	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_sigs_cb(struct rpmsg_device *rpdev, void *priv, u32 sigs)
+{
+	struct rpmsg_eptdev *eptdev = priv;
+
+	eptdev->rsigs = sigs;
+	eptdev->sig_pending = true;
+
 	wake_up_interruptible(&eptdev->readq);
 
 	return 0;
@@ -140,6 +156,7 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 		return -EINVAL;
 	}
 
+	ept->sig_cb = rpmsg_sigs_cb;
 	eptdev->ept = ept;
 	filp->private_data = eptdev;
 
@@ -159,6 +176,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
 		eptdev->ept = NULL;
 	}
 	mutex_unlock(&eptdev->ept_lock);
+	eptdev->sig_pending = false;
 
 	/* Discard all SKBs */
 	skb_queue_purge(&eptdev->queue);
@@ -272,6 +290,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait)
 	if (!skb_queue_empty(&eptdev->queue))
 		mask |= EPOLLIN | EPOLLRDNORM;
 
+	if (eptdev->sig_pending)
+		mask |= EPOLLPRI;
+
 	mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
 	return mask;
@@ -281,15 +302,36 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
 			       unsigned long arg)
 {
 	struct rpmsg_eptdev *eptdev = fp->private_data;
+	bool set;
+	u32 val;
+	int ret;
 
-	if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-		return -EINVAL;
+	switch (cmd) {
+	case TIOCMGET:
+		eptdev->sig_pending = false;
+		ret = put_user(eptdev->rsigs, (int __user *)arg);
+		break;
+	case TIOCMSET:
+		ret = get_user(val, (int __user *)arg);
+		if (ret)
+			break;
+		set = (val & TIOCM_DTR) ? true : false;
+		ret = rpmsg_set_flow_control(eptdev->ept, set);
+		break;
+	case RPMSG_DESTROY_EPT_IOCTL:
+		/* Don't allow to destroy a default endpoint. */
+		if (eptdev->default_ept) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL);
+		break;
+	default:
+		ret = -EINVAL;
+	}
 
-	/* Don't allow to destroy a default endpoint. */
-	if (eptdev->default_ept)
-		return -EINVAL;
 
-	return rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL);
+	return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
2.25.1


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

* [RFC PATCH 03/10] rpmsg: core: Add rpmsg device remote flow control announcement ops
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 01/10] rpmsg: core: Add signal API support Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 02/10] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 04/10] rpmsg: virtio: Implement the announce_remote_fc ops Arnaud Pouliquen
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

This ops is called by the rpmsg flow control service to inform
a rpmsg local device of a remote endpoint flow control state.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 drivers/rpmsg/rpmsg_core.c     | 24 ++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h |  7 +++++++
 2 files changed, 31 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 8de8aadd9b27..6bbc3b3ace50 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -67,6 +67,30 @@ int rpmsg_release_channel(struct rpmsg_device *rpdev,
 }
 EXPORT_SYMBOL(rpmsg_release_channel);
 
+/**
+ * rpmsg_channel_remote_fc() - announce remote endpoint flow control state
+ * using source and destination endpoint address info.
+ * @rpdev: rpmsg device
+ * @chinfo: channel_info
+ * @enable: state of the remote endpoint
+ *
+ * Return: 0 on success or an appropriate error value.
+ */
+int rpmsg_channel_remote_fc(struct rpmsg_device *rpdev,
+			    struct rpmsg_channel_info *chinfo,
+			    bool enable)
+{
+	if (WARN_ON(!rpdev))
+		return -EINVAL;
+	if (!rpdev->ops || !rpdev->ops->announce_remote_fc) {
+		dev_err(&rpdev->dev, "no flow control ops found\n");
+		return -ENXIO;
+	}
+
+	return rpdev->ops->announce_remote_fc(rpdev, chinfo, enable);
+}
+EXPORT_SYMBOL(rpmsg_channel_remote_fc);
+
 /**
  * rpmsg_create_ept() - create a new rpmsg_endpoint
  * @rpdev: rpmsg channel device
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 4ce58e68af30..44e2c0f2f5ea 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -43,6 +43,9 @@ struct rpmsg_device_ops {
 
 	int (*announce_create)(struct rpmsg_device *ept);
 	int (*announce_destroy)(struct rpmsg_device *ept);
+	int (*announce_remote_fc)(struct rpmsg_device *rpdev,
+				  struct rpmsg_channel_info *chinfo,
+				  bool enable);
 };
 
 /**
@@ -87,6 +90,10 @@ struct rpmsg_device *rpmsg_create_channel(struct rpmsg_device *rpdev,
 					  struct rpmsg_channel_info *chinfo);
 int rpmsg_release_channel(struct rpmsg_device *rpdev,
 			  struct rpmsg_channel_info *chinfo);
+
+int rpmsg_channel_remote_fc(struct rpmsg_device *rpdev,
+			    struct rpmsg_channel_info *chinfo,
+			    bool enable);
 /**
  * rpmsg_ctrldev_register_device() - register a char device for control based on rpdev
  * @rpdev:	prepared rpdev to be used for creating endpoints
-- 
2.25.1


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

* [RFC PATCH 04/10] rpmsg: virtio: Implement the announce_remote_fc ops
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
                   ` (2 preceding siblings ...)
  2022-05-20  8:29 ` [RFC PATCH 03/10] rpmsg: core: Add rpmsg device remote flow control announcement ops Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 05/10] rpmsg: Introduce flow control channel driver Arnaud Pouliquen
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

Add the capability for a rpmsg local endpoint to receive information
of a remote endpoint state using the flow control channel.

The virtio_rpmsg_remote_flowctrl function calls the endpoint which
matches with the chinfo.

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

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 0db8043e6c49..785fda77984e 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -305,6 +305,7 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
 	/* make sure in-flight inbound messages won't invoke cb anymore */
 	mutex_lock(&ept->cb_lock);
 	ept->cb = NULL;
+	ept->sig_cb =  NULL;
 	mutex_unlock(&ept->cb_lock);
 
 	kref_put(&ept->refcount, __ept_release);
@@ -365,12 +366,49 @@ static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 	return err;
 }
 
+static int virtio_rpmsg_remote_flowctrl(struct rpmsg_device *rpdev,
+					struct rpmsg_channel_info *chinfo,
+					bool enable)
+{
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
+	struct virtproc_info *vrp = vch->vrp;
+	struct rpmsg_endpoint *ept;
+
+	/* Use the dst addr to fetch the callback of the appropriate user */
+	mutex_lock(&vrp->endpoints_lock);
+
+	ept = idr_find(&vrp->endpoints, chinfo->dst);
+
+	/* Let's make sure no one deallocates ept while we use it */
+	if (ept)
+		kref_get(&ept->refcount);
+
+	mutex_unlock(&vrp->endpoints_lock);
+
+	if (!ept)
+		return -EINVAL;
+
+	/* Make sure ept->sig_cb doesn't go away while we use it */
+	mutex_lock(&ept->cb_lock);
+
+	if (ept->sig_cb)
+		ept->sig_cb(ept->rpdev, ept->priv, enable);
+
+	mutex_unlock(&ept->cb_lock);
+
+	/* Farewell, ept, we don't need you anymore */
+	kref_put(&ept->refcount, __ept_release);
+
+	return 0;
+}
+
 static const struct rpmsg_device_ops virtio_rpmsg_ops = {
 	.create_channel = virtio_rpmsg_create_channel,
 	.release_channel = virtio_rpmsg_release_channel,
 	.create_ept = virtio_rpmsg_create_ept,
 	.announce_create = virtio_rpmsg_announce_create,
 	.announce_destroy = virtio_rpmsg_announce_destroy,
+	.announce_remote_fc = virtio_rpmsg_remote_flowctrl,
 };
 
 static void virtio_rpmsg_release_device(struct device *dev)
-- 
2.25.1


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

* [RFC PATCH 05/10] rpmsg: Introduce flow control channel driver
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
                   ` (3 preceding siblings ...)
  2022-05-20  8:29 ` [RFC PATCH 04/10] rpmsg: virtio: Implement the announce_remote_fc ops Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 06/10] rpmsg: virtio: Add support of the VIRTIO_RPMSG_F_FC feature Arnaud Pouliquen
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

Register the channel 54 to manage flow control between endpoints.
the aim of this service is.
- to inform the local endpoint of the state of the associated remote
endpoints.
- to inform remote endpoint about the state of the local endpoint.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 drivers/rpmsg/Kconfig    |  10 ++++
 drivers/rpmsg/Makefile   |   1 +
 drivers/rpmsg/rpmsg_fc.c | 113 +++++++++++++++++++++++++++++++++++++++
 include/linux/rpmsg/fc.h |  51 ++++++++++++++++++
 4 files changed, 175 insertions(+)
 create mode 100644 drivers/rpmsg/rpmsg_fc.c
 create mode 100644 include/linux/rpmsg/fc.h

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index d3795860f5c0..c6659f27c617 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -31,6 +31,16 @@ config RPMSG_NS
 	  channel that probes the associated RPMsg device on remote endpoint
 	  service announcement.
 
+config RPMSG_FC
+	tristate "RPMSG endpoint flow control management"
+	depends on RPMSG
+	help
+	  Say Y here to enable the support of the flow control management
+	  for the rpmsg endpoints.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called rpmsg_fc.
+
 config RPMSG_MTK_SCP
 	tristate "MediaTek SCP"
 	depends on MTK_SCP
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 58e3b382e316..c70b9864231f 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -3,6 +3,7 @@ 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_FC)		+= rpmsg_fc.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_fc.c b/drivers/rpmsg/rpmsg_fc.c
new file mode 100644
index 000000000000..d7e17c8cffb0
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_fc.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
+ */
+
+#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/rpmsg/fc.h>
+#include <linux/slab.h>
+
+#include "rpmsg_internal.h"
+
+/**
+ * rpmsg_fc_register_device() - register name service device based on rpdev
+ * @rpdev: prepared rpdev to be used catfor creating endpoints
+ *
+ * This function wraps rpmsg_register_device() preparing the rpdev for use as
+ * basis for the rpmsg name service device.
+ */
+int rpmsg_fc_register_device(struct rpmsg_device *rpdev)
+{
+	strcpy(rpdev->id.name, "rpmsg_fc");
+	rpdev->driver_override = KBUILD_MODNAME;
+	rpdev->src = RPMSG_FC_ADDR;
+	rpdev->dst = RPMSG_FC_ADDR;
+
+	return rpmsg_register_device(rpdev);
+}
+EXPORT_SYMBOL(rpmsg_fc_register_device);
+
+/* Invoked when a name service announcement arrives */
+static int rpmsg_fc_cb(struct rpmsg_device *rpdev, void *data, int len,
+		       void *priv, u32 src)
+{
+	struct rpmsg_ept_msg *msg = data;
+	struct rpmsg_channel_info chinfo;
+	struct device *dev = rpdev->dev.parent;
+	bool enable;
+	int ret;
+
+	if (len != sizeof(*msg)) {
+		dev_err(dev, "malformed fc msg (%d)\n", len);
+		return -EINVAL;
+	}
+
+	chinfo.src = rpmsg32_to_cpu(rpdev, msg->src);
+	chinfo.dst = rpmsg32_to_cpu(rpdev, msg->dst);
+	enable = rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_EPT_FC_ON;
+
+	dev_dbg(dev, "remote endpoint 0x%x in state %sable\n", chinfo.src, enable ? "en" : "dis");
+
+	ret = rpmsg_channel_remote_fc(rpdev, &chinfo, enable);
+	if (ret)
+		dev_err(dev, "rpmsg_annouce_flow_ctrl failed: %d\n", ret);
+
+	return ret;
+}
+
+static int rpmsg_fc_probe(struct rpmsg_device *rpdev)
+{
+	struct rpmsg_endpoint *fc_ept;
+	struct rpmsg_channel_info fc_chinfo = {
+		.src = RPMSG_FC_ADDR,
+		.dst = RPMSG_FC_ADDR,
+		.name = "flow_control_service",
+	};
+
+	/*
+	 * Create the Flow control (FC) service endpoint associated to the RPMsg
+	 * device. The endpoint will be automatically destroyed when the RPMsg
+	 * device will be deleted.
+	 */
+	fc_ept = rpmsg_create_ept(rpdev, rpmsg_fc_cb, NULL, fc_chinfo);
+	if (!fc_ept) {
+		dev_err(&rpdev->dev, "failed to create the FC ept\n");
+		return -ENOMEM;
+	}
+	rpdev->ept = fc_ept;
+
+	return 0;
+}
+
+static struct rpmsg_driver rpmsg_fc_driver = {
+	.drv.name = KBUILD_MODNAME,
+	.probe = rpmsg_fc_probe,
+};
+
+static int rpmsg_fc_init(void)
+{
+	int ret;
+
+	ret = register_rpmsg_driver(&rpmsg_fc_driver);
+	if (ret < 0)
+		pr_err("%s: Failed to register FC rpmsg driver\n", __func__);
+
+	return ret;
+}
+postcore_initcall(rpmsg_fc_init);
+
+static void rpmsg_fc_exit(void)
+{
+	unregister_rpmsg_driver(&rpmsg_fc_driver);
+}
+module_exit(rpmsg_fc_exit);
+
+MODULE_DESCRIPTION("Flow control service rpmsg driver");
+MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>");
+MODULE_ALIAS("rpmsg:" KBUILD_MODNAME);
+MODULE_LICENSE("GPL");
diff --git a/include/linux/rpmsg/fc.h b/include/linux/rpmsg/fc.h
new file mode 100644
index 000000000000..5284ea410673
--- /dev/null
+++ b/include/linux/rpmsg/fc.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _LINUX_RPMSG_FC_H
+#define _LINUX_RPMSG_FC_H
+
+#include <linux/mod_devicetable.h>
+#include <linux/rpmsg.h>
+#include <linux/rpmsg/byteorder.h>
+#include <linux/types.h>
+
+/* The feature bitmap for the endpoint flow control flags */
+#define	RPMSG_EPT_FC_ON	 BIT(0) /* Set when endpoint is ready to communicate */
+
+/**
+ * struct rpmsg_ept_msg - dynamic endpoint announcement message
+ * @src: address of the endpoint that sends the message
+ * @dest: address of the destination endpoint.
+ * @flags: indicates the state of the endpoint based on @rpmsg_ept_flags enum.
+ *
+ * This message is sent across to inform the remote about the state of a local
+ * endpoint associated with a remote endpoint:
+ * - a RPMSG_EPT_OFF can be sent to inform that a local endpoint is suspended.
+ * - a RPMSG_EPT_ON can be sent to inform that a local endpoint is ready to communicate.
+ *
+ * When we receive these messages, the appropriate endpoint is informed.
+ */
+struct rpmsg_ept_msg {
+	__rpmsg32 src;
+	__rpmsg32 dst;
+	__rpmsg32 flags;
+} __packed;
+
+/* Address 54 is reserved for flow control advertising */
+#define RPMSG_FC_ADDR                   (54)
+
+#if IS_ENABLED(CONFIG_RPMSG_FC)
+
+int rpmsg_fc_register_device(struct rpmsg_device *rpdev);
+
+#else
+
+static inline int rpmsg_fc_register_device(struct rpmsg_device *rpdev)
+{
+	/* This shouldn't be possible */
+	WARN_ON(1);
+
+	return -ENXIO;
+}
+#endif /* IS_ENABLED(CONFIG_RPMSG_FC)*/
+
+#endif
-- 
2.25.1


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

* [RFC PATCH 06/10] rpmsg: virtio: Add support of the VIRTIO_RPMSG_F_FC feature
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
                   ` (4 preceding siblings ...)
  2022-05-20  8:29 ` [RFC PATCH 05/10] rpmsg: Introduce flow control channel driver Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 07/10] rpmsg: virtio: Implement the set_flow_control ops Arnaud Pouliquen
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

Introduce the VIRTIO_RPMSG_F_FC feature in charge of the end
point flow control management.
The virtio feature is negotiated. If the remote side supports it,
the rpmsg_fc device is probed.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 drivers/rpmsg/Kconfig            |  1 +
 drivers/rpmsg/virtio_rpmsg_bus.c | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index c6659f27c617..e39cf32483de 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -89,6 +89,7 @@ config RPMSG_VIRTIO
 	depends on HAS_DMA
 	select RPMSG
 	select RPMSG_NS
+	select RPMSG_FC
 	select VIRTIO
 
 endmenu
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 785fda77984e..40d2ab86b395 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/rpmsg.h>
 #include <linux/rpmsg/byteorder.h>
+#include <linux/rpmsg/fc.h>
 #include <linux/rpmsg/ns.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
@@ -70,6 +71,7 @@ struct virtproc_info {
 
 /* The feature bitmap for virtio rpmsg */
 #define VIRTIO_RPMSG_F_NS	0 /* RP supports name service notifications */
+#define VIRTIO_RPMSG_F_FC	1 /* RP supports endpoint flow control notifications */
 
 /**
  * struct rpmsg_hdr - common header for all rpmsg messages
@@ -909,7 +911,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
 	struct virtqueue *vqs[2];
 	struct virtproc_info *vrp;
 	struct virtio_rpmsg_channel *vch = NULL;
-	struct rpmsg_device *rpdev_ns, *rpdev_ctrl;
+	struct rpmsg_device *rpdev_ns = NULL, *rpdev_ctrl, *rpdev_fc;
 	void *bufs_va;
 	int err = 0, i;
 	size_t total_buf_space;
@@ -1013,6 +1015,30 @@ static int rpmsg_probe(struct virtio_device *vdev)
 			goto free_ctrldev;
 	}
 
+	/* If supported by the remote processor, enable the flow control service */
+	if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_FC)) {
+		vch = kzalloc(sizeof(*vch), GFP_KERNEL);
+		if (!vch) {
+			err = -ENOMEM;
+			goto free_ns;
+		}
+
+		/* Link the channel to our vrp */
+		vch->vrp = vrp;
+
+		/* Assign public information to the rpmsg_device */
+		rpdev_fc = &vch->rpdev;
+		rpdev_fc->ops = &virtio_rpmsg_ops;
+		rpdev_fc->little_endian = virtio_is_little_endian(vrp->vdev);
+
+		rpdev_fc->dev.parent = &vrp->vdev->dev;
+		rpdev_fc->dev.release = virtio_rpmsg_release_device;
+
+		err = rpmsg_fc_register_device(rpdev_fc);
+		if (err)
+			goto free_ns;
+	}
+
 	/*
 	 * Prepare to kick but don't notify yet - we can't do this before
 	 * device is ready.
@@ -1034,6 +1060,9 @@ static int rpmsg_probe(struct virtio_device *vdev)
 
 	return 0;
 
+free_ns:
+	if (rpdev_ns)
+		device_unregister(&rpdev_ns->dev);
 free_ctrldev:
 	rpmsg_virtio_del_ctrl_dev(rpdev_ctrl);
 free_coherent:
@@ -1082,6 +1111,7 @@ static struct virtio_device_id id_table[] = {
 
 static unsigned int features[] = {
 	VIRTIO_RPMSG_F_NS,
+	VIRTIO_RPMSG_F_FC,
 };
 
 static struct virtio_driver virtio_ipc_driver = {
-- 
2.25.1


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

* [RFC PATCH 07/10] rpmsg: virtio: Implement the set_flow_control ops
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
                   ` (5 preceding siblings ...)
  2022-05-20  8:29 ` [RFC PATCH 06/10] rpmsg: virtio: Add support of the VIRTIO_RPMSG_F_FC feature Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 08/10] rpmsg: Add the destination address in rpmsg_set_flow_control Arnaud Pouliquen
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

Add the capability for a rpmsg local endpoint to informs the
remote of its state using the flow control channel.

If the feature is not supported by the remote processor, no
message is sent.

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

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 40d2ab86b395..96bd12095c8c 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -154,6 +154,8 @@ static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept);
 static struct rpmsg_device *__rpmsg_create_channel(struct virtproc_info *vrp,
 						   struct rpmsg_channel_info *chinfo);
 
+static int virtio_rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable);
+
 static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
 	.destroy_ept = virtio_rpmsg_destroy_ept,
 	.send = virtio_rpmsg_send,
@@ -163,6 +165,7 @@ static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
 	.trysendto = virtio_rpmsg_trysendto,
 	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
 	.get_mtu = virtio_rpmsg_get_mtu,
+	.set_flow_control = virtio_rpmsg_set_flow_control,
 };
 
 /**
@@ -745,6 +748,34 @@ static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept)
 	return vch->vrp->buf_size - sizeof(struct rpmsg_hdr);
 }
 
+static int virtio_rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable)
+{
+	struct rpmsg_device *rpdev;
+	struct virtio_rpmsg_channel *vch;
+	int err = 0;
+
+	if (!ept)
+		return -EINVAL;
+
+	rpdev = ept->rpdev;
+	vch = to_virtio_rpmsg_channel(rpdev);
+
+	if (virtio_has_feature(vch->vrp->vdev, VIRTIO_RPMSG_F_FC)) {
+		struct rpmsg_ept_msg msg;
+
+		msg.src = cpu_to_rpmsg32(rpdev, ept->addr);
+		msg.dst = cpu_to_rpmsg32(rpdev, rpdev->dst);
+		msg.flags = cpu_to_rpmsg32(rpdev, enable ? RPMSG_EPT_FC_ON : 0);
+
+		err = rpmsg_sendto(ept, &msg, sizeof(msg), RPMSG_FC_ADDR);
+		if (err)
+			dev_err(&rpdev->dev, "Failed to set endpoint 0x%x state %sable (%d)\n",
+				ept->addr, enable ? "en" : "dis", err);
+	}
+
+	return err;
+}
+
 static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
 			     struct rpmsg_hdr *msg, unsigned int len)
 {
-- 
2.25.1


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

* [RFC PATCH 08/10] rpmsg: Add the destination address in rpmsg_set_flow_control
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
                   ` (6 preceding siblings ...)
  2022-05-20  8:29 ` [RFC PATCH 07/10] rpmsg: virtio: Implement the set_flow_control ops Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 09/10] rpmsg: tty : Add the support of the flow control Arnaud Pouliquen
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

The destination address is not part of the rpmsg_endpoint structure.
For static endpoint without channel, we need to specify the
destination address for backend such as the rpmsg virtio.
It is also needed for endpoint to multi endpoint communication.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 drivers/rpmsg/rpmsg_char.c       | 2 +-
 drivers/rpmsg/rpmsg_core.c       | 6 ++++--
 drivers/rpmsg/rpmsg_internal.h   | 2 +-
 drivers/rpmsg/virtio_rpmsg_bus.c | 6 +++---
 include/linux/rpmsg.h            | 4 ++--
 5 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 904e7c67b356..f44747e64b5b 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -316,7 +316,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
 		if (ret)
 			break;
 		set = (val & TIOCM_DTR) ? true : false;
-		ret = rpmsg_set_flow_control(eptdev->ept, set);
+		ret = rpmsg_set_flow_control(eptdev->ept, eptdev->chinfo.dst, set);
 		break;
 	case RPMSG_DESTROY_EPT_IOCTL:
 		/* Don't allow to destroy a default endpoint. */
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 6bbc3b3ace50..ab9a170ffa93 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -357,18 +357,20 @@ EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 /**
  * rpmsg_set_flow_control() - sets/clears serial flow control signals
  * @ept:	the rpmsg endpoint
+ * @dst:	the remote endpoint destination addr, set to RPMSG_ADDR_ANY to send to the default
+ *		remote endpoint associated to the rpmsg device.
  * @enable:	enable or disable serial flow control
  *
  * Return: 0 on success and an appropriate error value on failure.
  */
-int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable)
+int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, u32 dst, bool enable)
 {
 	if (WARN_ON(!ept))
 		return -EINVAL;
 	if (!ept->ops->set_flow_control)
 		return -ENXIO;
 
-	return ept->ops->set_flow_control(ept, enable);
+	return ept->ops->set_flow_control(ept, dst, enable);
 }
 EXPORT_SYMBOL(rpmsg_set_flow_control);
 
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 44e2c0f2f5ea..c34175f5093c 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -79,7 +79,7 @@ struct rpmsg_endpoint_ops {
 			     void *data, int len);
 	__poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp,
 			     poll_table *wait);
-	int (*set_flow_control)(struct rpmsg_endpoint *ept, bool enable);
+	int (*set_flow_control)(struct rpmsg_endpoint *ept, u32 dst, bool enable);
 	ssize_t (*get_mtu)(struct rpmsg_endpoint *ept);
 };
 
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 96bd12095c8c..a8e60ca4cd08 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -154,7 +154,7 @@ static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept);
 static struct rpmsg_device *__rpmsg_create_channel(struct virtproc_info *vrp,
 						   struct rpmsg_channel_info *chinfo);
 
-static int virtio_rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable);
+static int virtio_rpmsg_set_flow_control(struct rpmsg_endpoint *ept, u32 dst, bool enable);
 
 static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
 	.destroy_ept = virtio_rpmsg_destroy_ept,
@@ -748,7 +748,7 @@ static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept)
 	return vch->vrp->buf_size - sizeof(struct rpmsg_hdr);
 }
 
-static int virtio_rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable)
+static int virtio_rpmsg_set_flow_control(struct rpmsg_endpoint *ept, u32 dst, bool enable)
 {
 	struct rpmsg_device *rpdev;
 	struct virtio_rpmsg_channel *vch;
@@ -764,7 +764,7 @@ static int virtio_rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable
 		struct rpmsg_ept_msg msg;
 
 		msg.src = cpu_to_rpmsg32(rpdev, ept->addr);
-		msg.dst = cpu_to_rpmsg32(rpdev, rpdev->dst);
+		msg.dst = cpu_to_rpmsg32(rpdev, dst == RPMSG_ADDR_ANY ? rpdev->dst : dst);
 		msg.flags = cpu_to_rpmsg32(rpdev, enable ? RPMSG_EPT_FC_ON : 0);
 
 		err = rpmsg_sendto(ept, &msg, sizeof(msg), RPMSG_FC_ADDR);
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index dbd0c591bb85..9b321e1554e3 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -193,7 +193,7 @@ __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp,
 
 ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept);
 
-int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable);
+int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, u32 dst, bool enable);
 
 #else
 
@@ -313,7 +313,7 @@ static inline ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept)
 	return -ENXIO;
 }
 
-static inline int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable)
+static inline int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, u32 dst, bool enable)
 {
 	/* This shouldn't be possible */
 	WARN_ON(1);
-- 
2.25.1


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

* [RFC PATCH 09/10] rpmsg: tty : Add the support of the flow control
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
                   ` (7 preceding siblings ...)
  2022-05-20  8:29 ` [RFC PATCH 08/10] rpmsg: Add the destination address in rpmsg_set_flow_control Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-20  8:29 ` [RFC PATCH 10/10] rpmsg: virtio: Set default dst address on " Arnaud Pouliquen
  2022-05-24 15:34 ` [RFC PATCH 00/10] Introduction of rpmsg flow control service Mathieu Poirier
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

Add Software flow control support based on the RPMsg flow
control channel.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 drivers/tty/rpmsg_tty.c | 50 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/drivers/tty/rpmsg_tty.c b/drivers/tty/rpmsg_tty.c
index 29db413bbc03..fc1dc4a5ca9d 100644
--- a/drivers/tty/rpmsg_tty.c
+++ b/drivers/tty/rpmsg_tty.c
@@ -30,6 +30,7 @@ struct rpmsg_tty_port {
 	struct tty_port		port;	 /* TTY port data */
 	int			id;	 /* TTY rpmsg index */
 	struct rpmsg_device	*rpdev;	 /* rpmsg device */
+	bool			flow_stopped; /* remote device flow control */
 };
 
 static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 src)
@@ -106,6 +107,9 @@ static unsigned int rpmsg_tty_write_room(struct tty_struct *tty)
 	struct rpmsg_tty_port *cport = tty->driver_data;
 	int size;
 
+	if (cport->flow_stopped)
+		return 0;
+
 	size = rpmsg_get_mtu(cport->rpdev->ept);
 	if (size < 0)
 		return 0;
@@ -118,6 +122,28 @@ static void rpmsg_tty_hangup(struct tty_struct *tty)
 	tty_port_hangup(tty->port);
 }
 
+static void rpmsg_tty_throttle(struct tty_struct *tty)
+{
+	struct rpmsg_tty_port *cport = tty->driver_data;
+	int ret;
+
+	/* Disable remote transmission */
+	ret = rpmsg_set_flow_control(cport->rpdev->ept, RPMSG_ADDR_ANY, 0);
+	if (ret && ret != ENXIO)
+		dev_err(tty->dev, "cannot send control (%d)\n", ret);
+};
+
+static void rpmsg_tty_unthrottle(struct tty_struct *tty)
+{
+	struct rpmsg_tty_port *cport = tty->driver_data;
+	int ret;
+
+	/* Enable remote transmission */
+	ret = rpmsg_set_flow_control(cport->rpdev->ept, RPMSG_ADDR_ANY, 1);
+	if (ret && ret != ENXIO)
+		dev_err(tty->dev, "cannot send control (%d)\n", ret);
+};
+
 static const struct tty_operations rpmsg_tty_ops = {
 	.install	= rpmsg_tty_install,
 	.open		= rpmsg_tty_open,
@@ -126,6 +152,8 @@ static const struct tty_operations rpmsg_tty_ops = {
 	.write_room	= rpmsg_tty_write_room,
 	.hangup		= rpmsg_tty_hangup,
 	.cleanup	= rpmsg_tty_cleanup,
+	.throttle	= rpmsg_tty_throttle,
+	.unthrottle	= rpmsg_tty_unthrottle,
 };
 
 static struct rpmsg_tty_port *rpmsg_tty_alloc_cport(void)
@@ -162,11 +190,32 @@ static void rpmsg_tty_destruct_port(struct tty_port *port)
 	kfree(cport);
 }
 
+static void rpmsg_tty_dtr_rts(struct tty_port *port, int raise)
+{
+	if (!port->tty)
+		return;
+
+	if (raise)
+		rpmsg_tty_unthrottle(port->tty);
+	else
+		rpmsg_tty_throttle(port->tty);
+}
+
 static const struct tty_port_operations rpmsg_tty_port_ops = {
 	.destruct = rpmsg_tty_destruct_port,
+	.dtr_rts  = rpmsg_tty_dtr_rts,
 };
 
 
+static int rpmsg_tty_dsr_cts(struct rpmsg_device *rpdev, void *priv, u32 state)
+{
+	struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev);
+
+	cport->flow_stopped = !state;
+
+	return 0;
+}
+
 static int rpmsg_tty_probe(struct rpmsg_device *rpdev)
 {
 	struct rpmsg_tty_port *cport;
@@ -225,6 +274,7 @@ static struct rpmsg_driver rpmsg_tty_rpmsg_drv = {
 	.probe		= rpmsg_tty_probe,
 	.callback	= rpmsg_tty_cb,
 	.remove		= rpmsg_tty_remove,
+	.signals        = rpmsg_tty_dsr_cts,
 };
 
 static int __init rpmsg_tty_init(void)
-- 
2.25.1


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

* [RFC PATCH 10/10] rpmsg: virtio: Set default dst address on flow control
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
                   ` (8 preceding siblings ...)
  2022-05-20  8:29 ` [RFC PATCH 09/10] rpmsg: tty : Add the support of the flow control Arnaud Pouliquen
@ 2022-05-20  8:29 ` Arnaud Pouliquen
  2022-05-24 15:34 ` [RFC PATCH 00/10] Introduction of rpmsg flow control service Mathieu Poirier
  10 siblings, 0 replies; 13+ messages in thread
From: Arnaud Pouliquen @ 2022-05-20  8:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier
  Cc: linux-remoteproc, linux-kernel, linux-stm32, Deepak Kumar Singh,
	Chris Lew, arnaud.pouliquen

When a rpmsg channel has been created locally with a destination address
set to RPMSG_ADDR_ANY, a name service announcement message is sent to
the remote side. Then the destination address is never updated, making it
impossible to send messages to the remote.

An example of kernel trace observed:
rpmsg_tty virtio0.rpmsg-tty.29.-1: invalid addr (src 0x1d, dst 0xffffffff)

The flow control can be used to set the rpmsg device address.
If the destination address is RPMSG_ADDR_ANY, then set it to
address of the remote endpoint that send the message.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
This patch is an alternative of the fix proposed in patch [1]

[1] https://lore.kernel.org/lkml/20220316153001.662422-1-arnaud.pouliquen@foss.st.com/
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index a8e60ca4cd08..0337a07e278c 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -393,6 +393,16 @@ static int virtio_rpmsg_remote_flowctrl(struct rpmsg_device *rpdev,
 	if (!ept)
 		return -EINVAL;
 
+	/*
+	 * If the endpoint is the rpmsg device default one, then it can not be yet associated
+	 * to the remote endpoint. This can occur if a ns announcement message has been
+	 * previously sent to the remote side.
+	 * Update the rpmsg device destination address in such case to store the remote
+	 * address as default remote endpoint.
+	 */
+	if (rpdev->ept == ept && rpdev->dst == RPMSG_ADDR_ANY)
+		rpdev->dst = __rpmsg32_to_cpu(virtio_is_little_endian(vrp->vdev), chinfo->src);
+
 	/* Make sure ept->sig_cb doesn't go away while we use it */
 	mutex_lock(&ept->cb_lock);
 
-- 
2.25.1


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

* Re: [RFC PATCH 00/10] Introduction of rpmsg flow control service
  2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
                   ` (9 preceding siblings ...)
  2022-05-20  8:29 ` [RFC PATCH 10/10] rpmsg: virtio: Set default dst address on " Arnaud Pouliquen
@ 2022-05-24 15:34 ` Mathieu Poirier
  2022-05-25  8:57   ` Arnaud POULIQUEN
  10 siblings, 1 reply; 13+ messages in thread
From: Mathieu Poirier @ 2022-05-24 15:34 UTC (permalink / raw)
  To: Arnaud Pouliquen
  Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
	Deepak Kumar Singh, Chris Lew

Hi Arnaud,

I added your patchset to my review list.  Unfortunately it sits behind
a sizable backlog and as such I won't be able to get to it for some
time.

Thanks,
Mathieu

On Fri, 20 May 2022 at 02:30, Arnaud Pouliquen
<arnaud.pouliquen@foss.st.com> wrote:
>
> This series proposes an implementation for the rpmsg virtio transport
> backend, of the signaling API proposed by Deepak Kumar Singh:
> "rpmsg and glink signaling API support" [1]
>
> The aim of the series is to offer the possibility for an endpoint to inform
> a remote endpoint about its state, based on a software flow control[2].
>
> For this a new rpmsg service( with a fixed address 64) is proposed.
> It is responsible for:
> - transmitting local endpoint flow control information to the remote side,
> - informing a local endpoint about a remote endpoint flow control.
>
> For the rpmsg virtio transport layer the service is negotiated thanks to the
> virtio feature flag: VIRTIO_RPMSG_F_FC
>
> Notice that this pull request introduces new feature in the rpmsg protocol,
> So it has to be aligned with OpenAMP implementation.
> Pending OpenAMP pull request is available here:
> https://github.com/OpenAMP/open-amp/pull/394
>
>
> [1]https://lkml.org/lkml/2022/1/18/867
> [2]https://en.wikipedia.org/wiki/Software_flow_control
>
> Arnaud Pouliquen (8):
>   rpmsg: core: Add rpmsg device remote flow control announcement ops
>   rpmsg: virtio: Implement the announce_remote_fc ops
>   rpmsg: Introduce flow control channel driver
>   rpmsg: virtio: Add support of the VIRTIO_RPMSG_F_FC feature
>   rpmsg: virtio: Implement the set_flow_control ops
>   rpmsg: Add the destination address in rpmsg_set_flow_control
>   rpmsg: tty : Add the support of the flow control
>   rpmsg: virtio: Set default dst address on flow control
>
> Deepak Kumar Singh (2):
>   rpmsg: core: Add signal API support
>   rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
>
>  drivers/rpmsg/Kconfig            |  11 +++
>  drivers/rpmsg/Makefile           |   1 +
>  drivers/rpmsg/rpmsg_char.c       |  56 +++++++++++++--
>  drivers/rpmsg/rpmsg_core.c       |  47 +++++++++++++
>  drivers/rpmsg/rpmsg_fc.c         | 113 +++++++++++++++++++++++++++++++
>  drivers/rpmsg/rpmsg_internal.h   |   9 +++
>  drivers/rpmsg/virtio_rpmsg_bus.c | 111 +++++++++++++++++++++++++++++-
>  drivers/tty/rpmsg_tty.c          |  50 ++++++++++++++
>  include/linux/rpmsg.h            |  15 ++++
>  include/linux/rpmsg/fc.h         |  51 ++++++++++++++
>  10 files changed, 456 insertions(+), 8 deletions(-)
>  create mode 100644 drivers/rpmsg/rpmsg_fc.c
>  create mode 100644 include/linux/rpmsg/fc.h
>
> --
> 2.25.1
>

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

* Re: [RFC PATCH 00/10] Introduction of rpmsg flow control service
  2022-05-24 15:34 ` [RFC PATCH 00/10] Introduction of rpmsg flow control service Mathieu Poirier
@ 2022-05-25  8:57   ` Arnaud POULIQUEN
  0 siblings, 0 replies; 13+ messages in thread
From: Arnaud POULIQUEN @ 2022-05-25  8:57 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Bjorn Andersson, linux-remoteproc, linux-kernel, linux-stm32,
	Deepak Kumar Singh, Chris Lew, Xiang Xiao

Hi Mathieu,

On 5/24/22 17:34, Mathieu Poirier wrote:
> Hi Arnaud,
> 
> I added your patchset to my review list.  Unfortunately it sits behind
> a sizable backlog and as such I won't be able to get to it for some
> time.

No worries, I hope to get some feedbacks and to have discussion on the
topic from some other people as well 
FYI, as a similar Pull request exists on OpenAMP github, I requsted in the
OpenAMP PR to centralize all the discussions around the design choice in this
thread. The aim is that we have a single discussion thread to find a consensus
on the way of implementing such service on virtio backend.

Creating a specific rpmsg service is one approach, some other can exist...

Regards,
Arnaud


> 
> Thanks,
> Mathieu
> 
> On Fri, 20 May 2022 at 02:30, Arnaud Pouliquen
> <arnaud.pouliquen@foss.st.com> wrote:
>>
>> This series proposes an implementation for the rpmsg virtio transport
>> backend, of the signaling API proposed by Deepak Kumar Singh:
>> "rpmsg and glink signaling API support" [1]
>>
>> The aim of the series is to offer the possibility for an endpoint to inform
>> a remote endpoint about its state, based on a software flow control[2].
>>
>> For this a new rpmsg service( with a fixed address 64) is proposed.
>> It is responsible for:
>> - transmitting local endpoint flow control information to the remote side,
>> - informing a local endpoint about a remote endpoint flow control.
>>
>> For the rpmsg virtio transport layer the service is negotiated thanks to the
>> virtio feature flag: VIRTIO_RPMSG_F_FC
>>
>> Notice that this pull request introduces new feature in the rpmsg protocol,
>> So it has to be aligned with OpenAMP implementation.
>> Pending OpenAMP pull request is available here:
>> https://github.com/OpenAMP/open-amp/pull/394
>>
>>
>> [1]https://lkml.org/lkml/2022/1/18/867
>> [2]https://en.wikipedia.org/wiki/Software_flow_control
>>
>> Arnaud Pouliquen (8):
>>   rpmsg: core: Add rpmsg device remote flow control announcement ops
>>   rpmsg: virtio: Implement the announce_remote_fc ops
>>   rpmsg: Introduce flow control channel driver
>>   rpmsg: virtio: Add support of the VIRTIO_RPMSG_F_FC feature
>>   rpmsg: virtio: Implement the set_flow_control ops
>>   rpmsg: Add the destination address in rpmsg_set_flow_control
>>   rpmsg: tty : Add the support of the flow control
>>   rpmsg: virtio: Set default dst address on flow control
>>
>> Deepak Kumar Singh (2):
>>   rpmsg: core: Add signal API support
>>   rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
>>
>>  drivers/rpmsg/Kconfig            |  11 +++
>>  drivers/rpmsg/Makefile           |   1 +
>>  drivers/rpmsg/rpmsg_char.c       |  56 +++++++++++++--
>>  drivers/rpmsg/rpmsg_core.c       |  47 +++++++++++++
>>  drivers/rpmsg/rpmsg_fc.c         | 113 +++++++++++++++++++++++++++++++
>>  drivers/rpmsg/rpmsg_internal.h   |   9 +++
>>  drivers/rpmsg/virtio_rpmsg_bus.c | 111 +++++++++++++++++++++++++++++-
>>  drivers/tty/rpmsg_tty.c          |  50 ++++++++++++++
>>  include/linux/rpmsg.h            |  15 ++++
>>  include/linux/rpmsg/fc.h         |  51 ++++++++++++++
>>  10 files changed, 456 insertions(+), 8 deletions(-)
>>  create mode 100644 drivers/rpmsg/rpmsg_fc.c
>>  create mode 100644 include/linux/rpmsg/fc.h
>>
>> --
>> 2.25.1
>>

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

end of thread, other threads:[~2022-05-25  8:57 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-20  8:29 [RFC PATCH 00/10] Introduction of rpmsg flow control service Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 01/10] rpmsg: core: Add signal API support Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 02/10] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 03/10] rpmsg: core: Add rpmsg device remote flow control announcement ops Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 04/10] rpmsg: virtio: Implement the announce_remote_fc ops Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 05/10] rpmsg: Introduce flow control channel driver Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 06/10] rpmsg: virtio: Add support of the VIRTIO_RPMSG_F_FC feature Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 07/10] rpmsg: virtio: Implement the set_flow_control ops Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 08/10] rpmsg: Add the destination address in rpmsg_set_flow_control Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 09/10] rpmsg: tty : Add the support of the flow control Arnaud Pouliquen
2022-05-20  8:29 ` [RFC PATCH 10/10] rpmsg: virtio: Set default dst address on " Arnaud Pouliquen
2022-05-24 15:34 ` [RFC PATCH 00/10] Introduction of rpmsg flow control service Mathieu Poirier
2022-05-25  8:57   ` 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).