Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.

Signed-off-by: Chris Lew <c...@codeaurora.org>
Signed-off-by: Arun Kumar Neelakantam <ane...@codeaurora.org>
---
 drivers/rpmsg/rpmsg_core.c     | 42 ++++++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h |  5 +++++
 include/linux/rpmsg.h          | 27 +++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 8122807..9efcd26 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -2,6 +2,7 @@
 /*
  * remote processor messaging bus
  *
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (C) 2011 Texas Instruments, Inc.
  * Copyright (C) 2011 Google, Inc.
  *
@@ -177,6 +178,43 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 
src, u32 dst,
 EXPORT_SYMBOL(rpmsg_send_offchannel);
 
 /**
+ * rpmsg_get_signals() - get the signals for this endpoint
+ * @ept:       the rpmsg endpoint
+ * @sigs:      serial signals bitmask
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_get_signals(struct rpmsg_endpoint *ept, u32 *lsigs, u32 *rsigs)
+{
+       if (WARN_ON(!ept))
+               return -EINVAL;
+       if (!ept->ops->get_signals)
+               return -EOPNOTSUPP;
+
+       return ept->ops->get_signals(ept, lsigs, rsigs);
+}
+EXPORT_SYMBOL(rpmsg_get_signals);
+
+/**
+ * rpmsg_set_signals() - set the remote signals for this endpoint
+ * @ept:       the rpmsg endpoint
+ * @set:       set mask for signals
+ * @clear:     clear mask for signals
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_set_signals(struct rpmsg_endpoint *ept, u32 set, u32 clear)
+{
+       if (WARN_ON(!ept))
+               return -EINVAL;
+       if (!ept->ops->set_signals)
+               return -EOPNOTSUPP;
+
+       return ept->ops->set_signals(ept, set, clear);
+}
+EXPORT_SYMBOL(rpmsg_set_signals);
+
+/**
  * rpmsg_send() - send a message across to the remote processor
  * @ept: the rpmsg endpoint
  * @data: payload of message
@@ -468,6 +506,10 @@ 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 0d791c3..0a37d9bf 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -2,6 +2,7 @@
 /*
  * remote processor messaging bus internals
  *
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (C) 2011 Texas Instruments, Inc.
  * Copyright (C) 2011 Google, Inc.
  *
@@ -46,6 +47,8 @@ struct rpmsg_device_ops {
  * @trysend:           see @rpmsg_trysend(), required
  * @trysendto:         see @rpmsg_trysendto(), optional
  * @trysend_offchannel:        see @rpmsg_trysend_offchannel(), optional
+ * @get_signals:       see @rpmsg_get_signals(), optional
+ * @set_signals:       see @rpmsg_set_signals(), optional
  *
  * Indirection table for the operations that a rpmsg backend should implement.
  * In addition to @destroy_ept, the backend must at least implement @send and
@@ -65,6 +68,8 @@ struct rpmsg_endpoint_ops {
                             void *data, int len);
        __poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp,
                             poll_table *wait);
+       int (*get_signals)(struct rpmsg_endpoint *ept, u32 *lsigs, u32 *rsigs);
+       int (*set_signals)(struct rpmsg_endpoint *ept, u32 set, u32 clear);
 };
 
 int rpmsg_register_device(struct rpmsg_device *rpdev);
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 9fe156d..4e50d57 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -2,6 +2,7 @@
 /*
  * Remote processor messaging
  *
+ * Copyright (c) 2018 The Linux Foundation.
  * Copyright (C) 2011 Texas Instruments, Inc.
  * Copyright (C) 2011 Google, Inc.
  * All rights reserved.
@@ -60,6 +61,7 @@ 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, u32);
 
 /**
  * struct rpmsg_endpoint - binds a local rpmsg address to its user
@@ -67,6 +69,7 @@ struct rpmsg_device {
  * @refcount: when this drops to zero, the ept is deallocated
  * @cb: rx callback handler
  * @cb_lock: must be taken before accessing/changing @cb
+ * @sig_cb: rx serial signal handler
  * @addr: local rpmsg address
  * @priv: private data for the driver's use
  *
@@ -89,6 +92,7 @@ struct rpmsg_endpoint {
        struct kref refcount;
        rpmsg_rx_cb_t cb;
        struct mutex cb_lock;
+       rpmsg_rx_sig_t sig_cb;
        u32 addr;
        void *priv;
 
@@ -102,6 +106,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
+ * @signals: invoked when a serial signal change is received on the channel
  */
 struct rpmsg_driver {
        struct device_driver drv;
@@ -109,6 +114,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 *, void *, u32, u32);
 };
 
 #if IS_ENABLED(CONFIG_RPMSG)
@@ -135,6 +141,9 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, 
u32 src, u32 dst,
 __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp,
                        poll_table *wait);
 
+int rpmsg_get_signals(struct rpmsg_endpoint *ept, u32 *lsigs, u32 *rsigs);
+int rpmsg_set_signals(struct rpmsg_endpoint *ept, u32 set, u32 clear);
+
 #else
 
 static inline int register_rpmsg_device(struct rpmsg_device *dev)
@@ -242,6 +251,24 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint 
*ept,
        return 0;
 }
 
+static inline int rpmsg_get_signals(struct rpmsg_endpoint *ept,
+                                   u32 *lsigs, u32 *rsigs)
+{
+       /* This shouldn't be possible */
+       WARN_ON(1);
+
+       return -ENXIO;
+}
+
+static inline int rpmsg_set_signals(struct rpmsg_endpoint *ept,
+                                   u32 set, u32 clear)
+{
+       /* 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 */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

Reply via email to