2023-04-22 10:45:08

by Sarannya S

[permalink] [raw]
Subject: [PATCH V7 0/3] rpmsg signaling/flowcontrol patches

For rpmsg_set_flow_control, change "EXPORT_SYMBOL" to "EXPORT_SYMBOL_GPL".
Update destination parameter in rpmsg_set_flow_control().


Chris Lew (2):
rpmsg: glink: Add support to handle signals command
rpmsg: char: Add RPMSG GET/SET FLOWCONTROL IOCTL support

Deepak Kumar Singh (1):
rpmsg: core: Add signal API support

drivers/rpmsg/qcom_glink_native.c | 64 +++++++++++++++++++++++++++++++++++++++
drivers/rpmsg/rpmsg_char.c | 49 ++++++++++++++++++++++++++----
drivers/rpmsg/rpmsg_core.c | 21 +++++++++++++
drivers/rpmsg/rpmsg_internal.h | 2 ++
include/linux/rpmsg.h | 15 +++++++++
include/uapi/linux/rpmsg.h | 11 ++++++-
6 files changed, 155 insertions(+), 7 deletions(-)

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2023-04-22 10:45:57

by Sarannya S

[permalink] [raw]
Subject: [PATCH V7 2/3] rpmsg: glink: Add support to handle signals command

From: Chris Lew <[email protected]>

Remote peripherals send signal notifications over glink with commandID 15.

Add support to send and receive the signal command and based signals
enable or disable flow control with remote host.

Signed-off-by: Chris Lew <[email protected]>
Signed-off-by: Deepak Kumar Singh <[email protected]>
Signed-off-by: Sarannya S <[email protected]>
---
drivers/rpmsg/qcom_glink_native.c | 64 +++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
index 01d2805..ff5e926 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -16,6 +16,7 @@
#include <linux/rpmsg.h>
#include <linux/sizes.h>
#include <linux/slab.h>
+#include <linux/termios.h>
#include <linux/workqueue.h>
#include <linux/mailbox_client.h>

@@ -197,9 +198,15 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;
#define GLINK_CMD_TX_DATA_CONT 12
#define GLINK_CMD_READ_NOTIF 13
#define GLINK_CMD_RX_DONE_W_REUSE 14
+#define GLINK_CMD_SIGNALS 15

#define GLINK_FEATURE_INTENTLESS BIT(1)

+#define NATIVE_DTR_SIG NATIVE_DSR_SIG
+#define NATIVE_DSR_SIG BIT(31)
+#define NATIVE_RTS_SIG NATIVE_CTS_SIG
+#define NATIVE_CTS_SIG BIT(30)
+
static void qcom_glink_rx_done_work(struct work_struct *work);

static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -1014,6 +1021,58 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
return 0;
}

+/**
+ * qcom_glink_set_flow_control() - convert a signal cmd to wire format and
+ * transmit
+ * @ept: Rpmsg endpoint for channel.
+ * @enable: True/False - enable or disable flow control
+ * @dst: destination address of the endpoint
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_set_flow_control(struct rpmsg_endpoint *ept, bool enable, u32 dst)
+{
+ struct glink_channel *channel = to_glink_channel(ept);
+ struct qcom_glink *glink = channel->glink;
+ struct glink_msg msg;
+ u32 sigs = 0;
+
+ if (enable)
+ sigs |= NATIVE_DTR_SIG | NATIVE_RTS_SIG;
+
+ msg.cmd = cpu_to_le16(GLINK_CMD_SIGNALS);
+ msg.param1 = cpu_to_le16(channel->lcid);
+ msg.param2 = cpu_to_le32(sigs);
+
+ return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+ unsigned int rcid, unsigned int sigs)
+{
+ struct glink_channel *channel;
+ unsigned long flags;
+ bool enable = false;
+
+ spin_lock_irqsave(&glink->idr_lock, flags);
+ channel = idr_find(&glink->rcids, rcid);
+ spin_unlock_irqrestore(&glink->idr_lock, flags);
+ if (!channel) {
+ dev_err(glink->dev, "signal for non-existing channel\n");
+ return -EINVAL;
+ }
+
+ if (!channel->ept.flow_cb)
+ return 0;
+
+ if (sigs & (NATIVE_DSR_SIG | NATIVE_CTS_SIG))
+ enable = true;
+
+ channel->ept.flow_cb(channel->ept.rpdev, channel->ept.priv, enable);
+
+ return 0;
+}
+
void qcom_glink_native_rx(struct qcom_glink *glink)
{
struct glink_msg msg;
@@ -1075,6 +1134,10 @@ void qcom_glink_native_rx(struct qcom_glink *glink)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+ case GLINK_CMD_SIGNALS:
+ qcom_glink_handle_signals(glink, param1, param2);
+ qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
+ break;
default:
dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd);
ret = -EINVAL;
@@ -1449,6 +1512,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops = {
.sendto = qcom_glink_sendto,
.trysend = qcom_glink_trysend,
.trysendto = qcom_glink_trysendto,
+ .set_flow_control = qcom_glink_set_flow_control,
};

static void qcom_glink_rpdev_release(struct device *dev)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2023-04-22 10:46:50

by Sarannya S

[permalink] [raw]
Subject: [PATCH V7 3/3] rpmsg: char: Add RPMSG GET/SET FLOWCONTROL IOCTL support

From: Chris Lew <[email protected]>

Add RPMSG_GET_OUTGOING_FLOWCONTROL and RPMSG_SET_INCOMING_FLOWCONTROL
IOCTL support for rpmsg char device nodes to get/set the low level
transport signals.

Signed-off-by: Chris Lew <[email protected]>
Signed-off-by: Deepak Kumar Singh <[email protected]>
Signed-off-by: Sarannya S <[email protected]>
---
drivers/rpmsg/rpmsg_char.c | 49 ++++++++++++++++++++++++++++++++++++++++------
include/uapi/linux/rpmsg.h | 11 ++++++++++-
2 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a271fce..d50908f 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>

@@ -68,6 +69,8 @@ struct rpmsg_eptdev {
struct sk_buff_head queue;
wait_queue_head_t readq;

+ bool remote_flow;
+ bool remote_flow_updated;
};

int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data)
@@ -116,6 +119,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
return 0;
}

+static int rpmsg_ept_flow_cb(struct rpmsg_device *rpdev, void *priv, bool enable)
+{
+ struct rpmsg_eptdev *eptdev = priv;
+
+ eptdev->remote_flow = enable;
+ eptdev->remote_flow_updated = true;
+
+ wake_up_interruptible(&eptdev->readq);
+
+ return 0;
+}
+
static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
{
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -152,6 +167,7 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
return -EINVAL;
}

+ ept->flow_cb = rpmsg_ept_flow_cb;
eptdev->ept = ept;
filp->private_data = eptdev;
mutex_unlock(&eptdev->ept_lock);
@@ -172,6 +188,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
eptdev->ept = NULL;
}
mutex_unlock(&eptdev->ept_lock);
+ eptdev->remote_flow_updated = false;

/* Discard all SKBs */
skb_queue_purge(&eptdev->queue);
@@ -285,6 +302,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait)
if (!skb_queue_empty(&eptdev->queue))
mask |= EPOLLIN | EPOLLRDNORM;

+ if (eptdev->remote_flow_updated)
+ mask |= EPOLLPRI;
+
mutex_lock(&eptdev->ept_lock);
mask |= rpmsg_poll(eptdev->ept, filp, wait);
mutex_unlock(&eptdev->ept_lock);
@@ -297,14 +317,31 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
{
struct rpmsg_eptdev *eptdev = fp->private_data;

- if (cmd != RPMSG_DESTROY_EPT_IOCTL)
- return -EINVAL;
+ bool set;
+ int ret;

- /* Don't allow to destroy a default endpoint. */
- if (eptdev->default_ept)
- return -EINVAL;
+ switch (cmd) {
+ case RPMSG_GET_OUTGOING_FLOWCONTROL:
+ eptdev->remote_flow_updated = false;
+ ret = put_user(eptdev->remote_flow, (int __user *)arg);
+ break;
+ case RPMSG_SET_INCOMING_FLOWCONTROL:
+ set = !!arg;
+ ret = rpmsg_set_flow_control(eptdev->ept, set, eptdev->chinfo.dst);
+ 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;
+ }

- return rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL);
+ return ret;
}

static const struct file_operations rpmsg_eptdev_fops = {
diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
index 1637e68..c955e27 100644
--- a/include/uapi/linux/rpmsg.h
+++ b/include/uapi/linux/rpmsg.h
@@ -10,7 +10,6 @@
#include <linux/types.h>

#define RPMSG_ADDR_ANY 0xFFFFFFFF
-
/**
* struct rpmsg_endpoint_info - endpoint info representation
* @name: name of service
@@ -43,4 +42,14 @@ struct rpmsg_endpoint_info {
*/
#define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info)

+/**
+ * Set the flow control for the remote rpmsg char device.
+ */
+#define RPMSG_GET_OUTGOING_FLOWCONTROL _IOW(0xb5, 0x5, struct rpmsg_endpoint_info)
+
+/**
+ * Set the flow control for the local rpmsg char device.
+ */
+#define RPMSG_SET_INCOMING_FLOWCONTROL _IOW(0xb5, 0x6, struct rpmsg_endpoint_info)
+
#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2023-04-22 19:57:03

by Trilok Soni

[permalink] [raw]
Subject: Re: [PATCH V7 3/3] rpmsg: char: Add RPMSG GET/SET FLOWCONTROL IOCTL support

On 4/22/2023 3:42 AM, Sarannya S wrote:
> From: Chris Lew <[email protected]>
>
> Add RPMSG_GET_OUTGOING_FLOWCONTROL and RPMSG_SET_INCOMING_FLOWCONTROL
> IOCTL support for rpmsg char device nodes to get/set the low level
> transport signals.
>
> Signed-off-by: Chris Lew <[email protected]>
> Signed-off-by: Deepak Kumar Singh <[email protected]>
> Signed-off-by: Sarannya S <[email protected]>

[...]

>
> static const struct file_operations rpmsg_eptdev_fops = {
> diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
> index 1637e68..c955e27 100644
> --- a/include/uapi/linux/rpmsg.h
> +++ b/include/uapi/linux/rpmsg.h
> @@ -10,7 +10,6 @@
> #include <linux/types.h>
>
> #define RPMSG_ADDR_ANY 0xFFFFFFFF
> -

What is need of deleting this line in this patch? I am not sure if this
was asked in earlier reviews.

---Trilok Soni

2023-04-24 13:34:57

by Arnaud POULIQUEN

[permalink] [raw]
Subject: Re: [PATCH V7 3/3] rpmsg: char: Add RPMSG GET/SET FLOWCONTROL IOCTL support



On 4/22/23 12:42, Sarannya S wrote:
> From: Chris Lew <[email protected]>
>
> Add RPMSG_GET_OUTGOING_FLOWCONTROL and RPMSG_SET_INCOMING_FLOWCONTROL
> IOCTL support for rpmsg char device nodes to get/set the low level
> transport signals.
>
> Signed-off-by: Chris Lew <[email protected]>
> Signed-off-by: Deepak Kumar Singh <[email protected]>
> Signed-off-by: Sarannya S <[email protected]>
> ---
> drivers/rpmsg/rpmsg_char.c | 49 ++++++++++++++++++++++++++++++++++++++++------
> include/uapi/linux/rpmsg.h | 11 ++++++++++-
> 2 files changed, 53 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> index a271fce..d50908f 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>

Seems useless now

> #include <linux/uaccess.h>
> #include <uapi/linux/rpmsg.h>
>
> @@ -68,6 +69,8 @@ struct rpmsg_eptdev {
> struct sk_buff_head queue;
> wait_queue_head_t readq;
>
> + bool remote_flow;
> + bool remote_flow_updated;
> };
>
> int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data)
> @@ -116,6 +119,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
> return 0;
> }
>
> +static int rpmsg_ept_flow_cb(struct rpmsg_device *rpdev, void *priv, bool enable)
> +{
> + struct rpmsg_eptdev *eptdev = priv;
> +
> + eptdev->remote_flow = enable;
> + eptdev->remote_flow_updated = true;
> +
> + wake_up_interruptible(&eptdev->readq);
> +
> + return 0;
> +}
> +
> static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
> {
> struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
> @@ -152,6 +167,7 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
> return -EINVAL;
> }
>
> + ept->flow_cb = rpmsg_ept_flow_cb;
> eptdev->ept = ept;
> filp->private_data = eptdev;
> mutex_unlock(&eptdev->ept_lock);
> @@ -172,6 +188,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
> eptdev->ept = NULL;
> }
> mutex_unlock(&eptdev->ept_lock);
> + eptdev->remote_flow_updated = false;
>
> /* Discard all SKBs */
> skb_queue_purge(&eptdev->queue);
> @@ -285,6 +302,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait)
> if (!skb_queue_empty(&eptdev->queue))
> mask |= EPOLLIN | EPOLLRDNORM;
>
> + if (eptdev->remote_flow_updated)
> + mask |= EPOLLPRI;
> +
> mutex_lock(&eptdev->ept_lock);
> mask |= rpmsg_poll(eptdev->ept, filp, wait);
> mutex_unlock(&eptdev->ept_lock);
> @@ -297,14 +317,31 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
> {
> struct rpmsg_eptdev *eptdev = fp->private_data;
>
> - if (cmd != RPMSG_DESTROY_EPT_IOCTL)
> - return -EINVAL;
> + bool set;
> + int ret;
>
> - /* Don't allow to destroy a default endpoint. */
> - if (eptdev->default_ept)
> - return -EINVAL;
> + switch (cmd) {
> + case RPMSG_GET_OUTGOING_FLOWCONTROL:
> + eptdev->remote_flow_updated = false;
> + ret = put_user(eptdev->remote_flow, (int __user *)arg);

If the rpmsg_set_flow_control is not implemented on remote side or in the
backend then we should return true by default.
Else the communication should not be possible if eptdev->remote_flow is not
initialized.

Perhaps adding a "flow_ctrl" boolean in the rpmsg_device (similar to the
"announce") would give the information if the flow control is supported or not.
This "flow_ctrl" boolean would be initialized by the backend.

Regards
Arnaud


> + break;
> + case RPMSG_SET_INCOMING_FLOWCONTROL:
> + set = !!arg;
> + ret = rpmsg_set_flow_control(eptdev->ept, set, eptdev->chinfo.dst);
> + 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;
> + }
>
> - return rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL);
> + return ret;
> }
>
> static const struct file_operations rpmsg_eptdev_fops = {
> diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
> index 1637e68..c955e27 100644
> --- a/include/uapi/linux/rpmsg.h
> +++ b/include/uapi/linux/rpmsg.h
> @@ -10,7 +10,6 @@
> #include <linux/types.h>
>
> #define RPMSG_ADDR_ANY 0xFFFFFFFF
> -
> /**
> * struct rpmsg_endpoint_info - endpoint info representation
> * @name: name of service
> @@ -43,4 +42,14 @@ struct rpmsg_endpoint_info {
> */
> #define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info)
>
> +/**
> + * Set the flow control for the remote rpmsg char device.
> + */
> +#define RPMSG_GET_OUTGOING_FLOWCONTROL _IOW(0xb5, 0x5, struct rpmsg_endpoint_info)
> +
> +/**
> + * Set the flow control for the local rpmsg char device.
> + */
> +#define RPMSG_SET_INCOMING_FLOWCONTROL _IOW(0xb5, 0x6, struct rpmsg_endpoint_info)
> +
> #endif

2023-06-14 15:47:34

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH V7 2/3] rpmsg: glink: Add support to handle signals command

On Sat, Apr 22, 2023 at 04:12:06PM +0530, Sarannya S wrote:
> From: Chris Lew <[email protected]>
>
> Remote peripherals send signal notifications over glink with commandID 15.
>
> Add support to send and receive the signal command and based signals
> enable or disable flow control with remote host.
>
> Signed-off-by: Chris Lew <[email protected]>
> Signed-off-by: Deepak Kumar Singh <[email protected]>
> Signed-off-by: Sarannya S <[email protected]>
> ---
> drivers/rpmsg/qcom_glink_native.c | 64 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 64 insertions(+)
>
> diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
> index 01d2805..ff5e926 100644
> --- a/drivers/rpmsg/qcom_glink_native.c
> +++ b/drivers/rpmsg/qcom_glink_native.c
> @@ -16,6 +16,7 @@
> #include <linux/rpmsg.h>
> #include <linux/sizes.h>
> #include <linux/slab.h>
> +#include <linux/termios.h>
> #include <linux/workqueue.h>
> #include <linux/mailbox_client.h>
>
> @@ -197,9 +198,15 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;
> #define GLINK_CMD_TX_DATA_CONT 12
> #define GLINK_CMD_READ_NOTIF 13
> #define GLINK_CMD_RX_DONE_W_REUSE 14
> +#define GLINK_CMD_SIGNALS 15
>
> #define GLINK_FEATURE_INTENTLESS BIT(1)
>
> +#define NATIVE_DTR_SIG NATIVE_DSR_SIG
> +#define NATIVE_DSR_SIG BIT(31)
> +#define NATIVE_RTS_SIG NATIVE_CTS_SIG
> +#define NATIVE_CTS_SIG BIT(30)
> +
> static void qcom_glink_rx_done_work(struct work_struct *work);
>
> static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
> @@ -1014,6 +1021,58 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
> return 0;
> }
>
> +/**
> + * qcom_glink_set_flow_control() - convert a signal cmd to wire format and
> + * transmit
> + * @ept: Rpmsg endpoint for channel.
> + * @enable: True/False - enable or disable flow control
> + * @dst: destination address of the endpoint
> + *
> + * Return: 0 on success or standard Linux error code.
> + */
> +static int qcom_glink_set_flow_control(struct rpmsg_endpoint *ept, bool enable, u32 dst)
> +{
> + struct glink_channel *channel = to_glink_channel(ept);
> + struct qcom_glink *glink = channel->glink;
> + struct glink_msg msg;
> + u32 sigs = 0;
> +
> + if (enable)
> + sigs |= NATIVE_DTR_SIG | NATIVE_RTS_SIG;
> +
> + msg.cmd = cpu_to_le16(GLINK_CMD_SIGNALS);
> + msg.param1 = cpu_to_le16(channel->lcid);
> + msg.param2 = cpu_to_le32(sigs);
> +
> + return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
> +}
> +
> +static int qcom_glink_handle_signals(struct qcom_glink *glink,
> + unsigned int rcid, unsigned int sigs)
> +{
> + struct glink_channel *channel;
> + unsigned long flags;
> + bool enable = false;
> +
> + spin_lock_irqsave(&glink->idr_lock, flags);
> + channel = idr_find(&glink->rcids, rcid);
> + spin_unlock_irqrestore(&glink->idr_lock, flags);
> + if (!channel) {
> + dev_err(glink->dev, "signal for non-existing channel\n");
> + return -EINVAL;

You don't handle this return value, so this works fine. But the other
cases of returning an error to qcom_glink_native_rx() indicates that no
further messages should be processed (e.g. because there's no sufficient
data in the FIFO).

But getting a signal on a non-existing channel is not something that's
going to be resolved until we get the next interrupt, so I think you
shouldn't propagate this error.

Which means that it would be better to make the return type void of this
function.

> + }
> +
> + if (!channel->ept.flow_cb)
> + return 0;
> +
> + if (sigs & (NATIVE_DSR_SIG | NATIVE_CTS_SIG))
> + enable = true;

I'd find it cleaner to skip the early initialization and have a single
point of assignment of enable, like:

enable = sigs & NATIVE_DSR_SIG || sigs & NATIVE_CTS_SIG;


And consolidate the flow_cb query/invocation to one place:
if (channel->eptf.flow_cb)
channel->ept.flow_cb(, enable);

Regards,
Bjorn

> +
> + channel->ept.flow_cb(channel->ept.rpdev, channel->ept.priv, enable);
> +
> + return 0;
> +}
> +
> void qcom_glink_native_rx(struct qcom_glink *glink)
> {
> struct glink_msg msg;
> @@ -1075,6 +1134,10 @@ void qcom_glink_native_rx(struct qcom_glink *glink)
> qcom_glink_handle_intent_req_ack(glink, param1, param2);
> qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
> break;
> + case GLINK_CMD_SIGNALS:
> + qcom_glink_handle_signals(glink, param1, param2);
> + qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
> + break;
> default:
> dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd);
> ret = -EINVAL;
> @@ -1449,6 +1512,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops = {
> .sendto = qcom_glink_sendto,
> .trysend = qcom_glink_trysend,
> .trysendto = qcom_glink_trysendto,
> + .set_flow_control = qcom_glink_set_flow_control,
> };
>
> static void qcom_glink_rpdev_release(struct device *dev)
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
>

2023-06-14 16:28:10

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH V7 3/3] rpmsg: char: Add RPMSG GET/SET FLOWCONTROL IOCTL support

On Sat, Apr 22, 2023 at 04:12:07PM +0530, Sarannya S wrote:
> From: Chris Lew <[email protected]>
>
> Add RPMSG_GET_OUTGOING_FLOWCONTROL and RPMSG_SET_INCOMING_FLOWCONTROL
> IOCTL support for rpmsg char device nodes to get/set the low level
> transport signals.
>
> Signed-off-by: Chris Lew <[email protected]>
> Signed-off-by: Deepak Kumar Singh <[email protected]>
> Signed-off-by: Sarannya S <[email protected]>
> ---
> drivers/rpmsg/rpmsg_char.c | 49 ++++++++++++++++++++++++++++++++++++++++------
> include/uapi/linux/rpmsg.h | 11 ++++++++++-
> 2 files changed, 53 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> index a271fce..d50908f 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>
>
> @@ -68,6 +69,8 @@ struct rpmsg_eptdev {
> struct sk_buff_head queue;
> wait_queue_head_t readq;
>
> + bool remote_flow;

I was about to agree with Arnaud, that this needs to be defaulted to
true. But the flag means "has the remote asked for flow to be limited".

As such, the name of this variable is misleading. Please rename it
"remote_flow_restricted" or something like that.

And please update the kerneldoc for this struct.

Regards,
Bjorn

> + bool remote_flow_updated;
> };
>
> int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data)
> @@ -116,6 +119,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
> return 0;
> }
>
> +static int rpmsg_ept_flow_cb(struct rpmsg_device *rpdev, void *priv, bool enable)
> +{
> + struct rpmsg_eptdev *eptdev = priv;
> +
> + eptdev->remote_flow = enable;
> + eptdev->remote_flow_updated = true;
> +
> + wake_up_interruptible(&eptdev->readq);
> +
> + return 0;
> +}
> +
> static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
> {
> struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
> @@ -152,6 +167,7 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
> return -EINVAL;
> }
>
> + ept->flow_cb = rpmsg_ept_flow_cb;
> eptdev->ept = ept;
> filp->private_data = eptdev;
> mutex_unlock(&eptdev->ept_lock);
> @@ -172,6 +188,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
> eptdev->ept = NULL;
> }
> mutex_unlock(&eptdev->ept_lock);
> + eptdev->remote_flow_updated = false;
>
> /* Discard all SKBs */
> skb_queue_purge(&eptdev->queue);
> @@ -285,6 +302,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait)
> if (!skb_queue_empty(&eptdev->queue))
> mask |= EPOLLIN | EPOLLRDNORM;
>
> + if (eptdev->remote_flow_updated)
> + mask |= EPOLLPRI;
> +
> mutex_lock(&eptdev->ept_lock);
> mask |= rpmsg_poll(eptdev->ept, filp, wait);
> mutex_unlock(&eptdev->ept_lock);
> @@ -297,14 +317,31 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
> {
> struct rpmsg_eptdev *eptdev = fp->private_data;
>
> - if (cmd != RPMSG_DESTROY_EPT_IOCTL)
> - return -EINVAL;
> + bool set;
> + int ret;
>
> - /* Don't allow to destroy a default endpoint. */
> - if (eptdev->default_ept)
> - return -EINVAL;
> + switch (cmd) {
> + case RPMSG_GET_OUTGOING_FLOWCONTROL:
> + eptdev->remote_flow_updated = false;
> + ret = put_user(eptdev->remote_flow, (int __user *)arg);
> + break;
> + case RPMSG_SET_INCOMING_FLOWCONTROL:
> + set = !!arg;
> + ret = rpmsg_set_flow_control(eptdev->ept, set, eptdev->chinfo.dst);
> + 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;
> + }
>
> - return rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL);
> + return ret;
> }
>
> static const struct file_operations rpmsg_eptdev_fops = {
> diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
> index 1637e68..c955e27 100644
> --- a/include/uapi/linux/rpmsg.h
> +++ b/include/uapi/linux/rpmsg.h
> @@ -10,7 +10,6 @@
> #include <linux/types.h>
>
> #define RPMSG_ADDR_ANY 0xFFFFFFFF
> -
> /**
> * struct rpmsg_endpoint_info - endpoint info representation
> * @name: name of service
> @@ -43,4 +42,14 @@ struct rpmsg_endpoint_info {
> */
> #define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info)
>
> +/**
> + * Set the flow control for the remote rpmsg char device.
> + */
> +#define RPMSG_GET_OUTGOING_FLOWCONTROL _IOW(0xb5, 0x5, struct rpmsg_endpoint_info)
> +
> +/**
> + * Set the flow control for the local rpmsg char device.
> + */
> +#define RPMSG_SET_INCOMING_FLOWCONTROL _IOW(0xb5, 0x6, struct rpmsg_endpoint_info)
> +
> #endif
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
>