[PATCH V6 2/5] rpmsg: Guard against null endpoint ops in destroy

2020-05-20 Thread Arun Kumar Neelakantam
From: Chris Lew 

In RPMSG GLINK the chrdev device will allocate an ept as part of the
rpdev creation. This device will not register endpoint ops even though
it has an allocated ept. Protect against the case where the device is
being destroyed.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index e330ec4..d6c3275 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -81,7 +81,7 @@ EXPORT_SYMBOL(rpmsg_create_ept);
  */
 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-   if (ept)
+   if (ept && ept->ops)
ept->ops->destroy_ept(ept);
 }
 EXPORT_SYMBOL(rpmsg_destroy_ept);
-- 
2.7.4


[PATCH V6 3/5] rpmsg: glink: Add support for rpmsg glink chrdev

2020-05-20 Thread Arun Kumar Neelakantam
From: Chris Lew 

RPMSG provides a char device interface to userspace. Probe the rpmsg
chrdev channel to enable the rpmsg_ctrl device creation on glink
transports.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index ea2f33f..b85433c 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1574,6 +1574,40 @@ static void qcom_glink_cancel_rx_work(struct qcom_glink 
*glink)
kfree(dcmd);
 }
 
+static void qcom_glink_device_release(struct device *dev)
+{
+   struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+   struct glink_channel *channel = to_glink_channel(rpdev->ept);
+
+   /* Release qcom_glink_alloc_channel() reference */
+   kref_put(>refcount, qcom_glink_channel_release);
+   kfree(rpdev);
+}
+
+static int qcom_glink_create_chrdev(struct qcom_glink *glink)
+{
+   struct rpmsg_device *rpdev;
+   struct glink_channel *channel;
+
+   rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
+   if (!rpdev)
+   return -ENOMEM;
+
+   channel = qcom_glink_alloc_channel(glink, "rpmsg_chrdev");
+   if (IS_ERR(channel)) {
+   kfree(rpdev);
+   return PTR_ERR(channel);
+   }
+   channel->rpdev = rpdev;
+
+   rpdev->ept = >ept;
+   rpdev->ops = _device_ops;
+   rpdev->dev.parent = glink->dev;
+   rpdev->dev.release = qcom_glink_device_release;
+
+   return rpmsg_chrdev_register_device(rpdev);
+}
+
 struct qcom_glink *qcom_glink_native_probe(struct device *dev,
   unsigned long features,
   struct qcom_glink_pipe *rx,
@@ -1633,6 +1667,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
if (ret)
return ERR_PTR(ret);
 
+   ret = qcom_glink_create_chrdev(glink);
+   if (ret)
+   dev_err(glink->dev, "failed to register chrdev\n");
+
return glink;
 }
 EXPORT_SYMBOL_GPL(qcom_glink_native_probe);
-- 
2.7.4


[PATCH V6 5/5] rpmsg: glink: unregister rpmsg device during endpoint destroy

2020-05-20 Thread Arun Kumar Neelakantam
Rpmsg device unregister is not happening if channel close is triggered
from local side and causing re-registration of device failures.

Unregister rpmsg device for local close in endpoint destroy path.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 2b5368b..53b90a1 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1207,6 +1207,7 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
 {
struct glink_channel *channel = to_glink_channel(ept);
struct qcom_glink *glink = channel->glink;
+   struct rpmsg_channel_info chinfo;
unsigned long flags;
 
spin_lock_irqsave(>recv_lock, flags);
@@ -1214,6 +1215,13 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
spin_unlock_irqrestore(>recv_lock, flags);
 
/* Decouple the potential rpdev from the channel */
+   if (channel->rpdev) {
+   strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+   chinfo.src = RPMSG_ADDR_ANY;
+   chinfo.dst = RPMSG_ADDR_ANY;
+
+   rpmsg_unregister_device(glink->dev, );
+   }
channel->rpdev = NULL;
 
qcom_glink_send_close_req(glink, channel);
@@ -1477,6 +1485,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, 
unsigned int rcid)
 
rpmsg_unregister_device(glink->dev, );
}
+   channel->rpdev = NULL;
 
qcom_glink_send_close_ack(glink, channel->rcid);
 
-- 
2.7.4


[PATCH V6 1/5] rpmsg: glink: Use complete_all for open states

2020-05-20 Thread Arun Kumar Neelakantam
From: Chris Lew 

The open_req and open_ack completion variables are the state variables
to represent a remote channel as open. Use complete_all so there are no
races with waiters and using completion_done.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 1995f5b..ea2f33f 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -970,7 +970,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, 
unsigned int lcid)
return -EINVAL;
}
 
-   complete(>open_ack);
+   complete_all(>open_ack);
 
return 0;
 }
@@ -1178,7 +1178,7 @@ static int qcom_glink_announce_create(struct rpmsg_device 
*rpdev)
__be32 *val = defaults;
int size;
 
-   if (glink->intentless)
+if (glink->intentless || !completion_done(>open_ack))
return 0;
 
prop = of_find_property(np, "qcom,intents", NULL);
@@ -1413,7 +1413,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, 
unsigned int rcid,
channel->rcid = ret;
spin_unlock_irqrestore(>idr_lock, flags);
 
-   complete(>open_req);
+   complete_all(>open_req);
 
if (create_device) {
rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
-- 
2.7.4


[PATCH V5 0/5] Add chrdev and name query support for GLINK

2020-05-20 Thread Arun Kumar Neelakantam
Add support for the GLINK rpmsg transport to register a rpmsg chrdev.
This will create the rpmsg_ctrl nodes for userspace clients to open 
rpmsg epts. The rpmsg chrdev allocation is done by allocating a local
channel which also allocates an ept. We need to add some guards against
edge cases for this chrdev because it will never fully open.

Changes since v5:
- Re-orange the completion_done code

Changes since v4:
- Resending by removing approved patches

Changes since v3:
- Change to device_add_group for rpmsg name attr
- Add patch to unregister the rpmsg device
- Add patch to support compat ioctl for rpmsg char driver

Changes since v2:
- Revert change to make glink attribute table const

Changes since v1:
- Add explanation to dt-bindings commit message
- Add patch complete_all the open_req/ack variables
- Add patch to prevent null pointer dereference in chrdev channel release
- Change chrdev allocation to use glink channel allocation
- Change glink attr struct to const

Arun Kumar Neelakantam (1):
  rpmsg: glink: unregister rpmsg device during endpoint destroy

Chris Lew (4):
  rpmsg: glink: Use complete_all for open states
  rpmsg: Guard against null endpoint ops in destroy
  rpmsg: glink: Add support for rpmsg glink chrdev
  rpmsg: glink: Expose rpmsg name attr for glink

 drivers/rpmsg/qcom_glink_native.c | 79 +--
 drivers/rpmsg/rpmsg_core.c|  2 +-
 2 files changed, 77 insertions(+), 4 deletions(-)

-- 
2.7.4


[PATCH V6 4/5] rpmsg: glink: Expose rpmsg name attr for glink

2020-05-20 Thread Arun Kumar Neelakantam
From: Chris Lew 

Expose the name field as an attr so clients listening to uevents for
rpmsg can identify the edge the events correspond to.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index b85433c..2b5368b 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1574,6 +1574,26 @@ static void qcom_glink_cancel_rx_work(struct qcom_glink 
*glink)
kfree(dcmd);
 }
 
+static ssize_t rpmsg_name_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   int ret = 0;
+   const char *name;
+
+   ret = of_property_read_string(dev->of_node, "label", );
+   if (ret < 0)
+   name = dev->of_node->name;
+
+   return snprintf(buf, RPMSG_NAME_SIZE, "%s\n", name);
+}
+static DEVICE_ATTR_RO(rpmsg_name);
+
+static struct attribute *qcom_glink_attrs[] = {
+   _attr_rpmsg_name.attr,
+   NULL
+};
+ATTRIBUTE_GROUPS(qcom_glink);
+
 static void qcom_glink_device_release(struct device *dev)
 {
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
@@ -1638,6 +1658,12 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
idr_init(>lcids);
idr_init(>rcids);
 
+   glink->dev->groups = qcom_glink_groups;
+
+   ret = device_add_groups(dev, qcom_glink_groups);
+   if (ret)
+   dev_err(dev, "failed to add groups\n");
+
ret = of_property_read_string(dev->of_node, "label", >name);
if (ret < 0)
glink->name = dev->of_node->name;
-- 
2.7.4


Re: [PATCH V5 5/5] rpmsg: glink: unregister rpmsg device during endpoint destroy

2020-05-20 Thread Arun Kumar Neelakantam



On 5/14/2020 3:43 AM, Mathieu Poirier wrote:

On Wed, May 13, 2020 at 10:40:06AM +0530, Arun Kumar Neelakantam wrote:

Rpmsg device unregister is not happening if channel close is triggered
from local side and causing re-registration of device failures.

Unregister rpmsg device for local close in endpoint destroy path.

Signed-off-by: Arun Kumar Neelakantam 
---
  drivers/rpmsg/qcom_glink_native.c | 9 +
  1 file changed, 9 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 0e8a28c0..fc8ef66 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1207,6 +1207,7 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
  {
struct glink_channel *channel = to_glink_channel(ept);
struct qcom_glink *glink = channel->glink;
+   struct rpmsg_channel_info chinfo;
unsigned long flags;
  
  	spin_lock_irqsave(>recv_lock, flags);

@@ -1214,6 +1215,13 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
spin_unlock_irqrestore(>recv_lock, flags);
  
  	/* Decouple the potential rpdev from the channel */

+   if (channel->rpdev) {

If we proceed this way no other channel can have an rpdev.  I would hope that
unregistration of rpdev would be more symetrical to what is done in patch 03.

Thanks,
Mathieu
Unregister here also required along with in qcom_glink_rx_close() 
otherwise if the remote open the channel again it map to stale rpmsg 
device.



+   strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+   chinfo.src = RPMSG_ADDR_ANY;
+   chinfo.dst = RPMSG_ADDR_ANY;
+
+   rpmsg_unregister_device(glink->dev, );
+   }
channel->rpdev = NULL;
  
  	qcom_glink_send_close_req(glink, channel);

@@ -1477,6 +1485,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, 
unsigned int rcid)
  
  		rpmsg_unregister_device(glink->dev, );

}
+   channel->rpdev = NULL;
  
  	qcom_glink_send_close_ack(glink, channel->rcid);
  
--

2.7.4


Re: [PATCH V5 1/5] rpmsg: glink: Use complete_all for open states

2020-05-20 Thread Arun Kumar Neelakantam



On 5/14/2020 2:29 AM, Mathieu Poirier wrote:

Hi Arun,

On Wed, May 13, 2020 at 10:40:02AM +0530, Arun Kumar Neelakantam wrote:

From: Chris Lew 

The open_req and open_ack completion variables are the state variables
to represet a remote channel as open. Use complete_all so there are no

s/represet/represent

done added in patch set 6



races with waiters and using completion_done.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
  drivers/rpmsg/qcom_glink_native.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 1995f5b..604f11f 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -970,7 +970,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, 
unsigned int lcid)
return -EINVAL;
}
  
-	complete(>open_ack);

+   complete_all(>open_ack);

If you do this and as per the note in the comment section above
completion_done(), there shouldn't be a need to call completion_done() in
qcom_glink_announce_create().

Thanks,
Mathieu
the completion_done() check still required to avoid sending intent 
request on channel which only opened by remote.
  

  
  	return 0;

  }
@@ -1413,7 +1413,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, 
unsigned int rcid,
channel->rcid = ret;
spin_unlock_irqrestore(>idr_lock, flags);
  
-	complete(>open_req);

+   complete_all(>open_req);
  
  	if (create_device) {

rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
--
2.7.4


[PATCH V4 2/4] rpmsg: glink: Add support to handle signals command

2020-05-12 Thread Arun Kumar Neelakantam
Remote peripherals send signal notifications over glink with commandID 15.

Add support to send and receive the signal command and convert the signals
from NATIVE to TIOCM while receiving and vice versa while sending.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 126 ++
 1 file changed, 126 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index fc8ef66..68e039a 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016-2017, Linaro Ltd
  */
 
@@ -17,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -150,6 +152,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: local side signals
+ * @rsigs: remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +185,10 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
+
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,9 +209,15 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG  BIT(29)
+#define NATIVE_RI_SIG  BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -975,6 +989,76 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb) {
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+   }
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1036,6 +1120,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_CMD_SIGNALS:
+   qcom_glink_handle_signals(glink, param1, param2);
+   

[RESEND PATCH V4 0/4] Add TIOCM Signals support for RPMSG char devices

2020-05-12 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Changes since v3:
- Correct the TICOMGET case handling as per new rpmsg_get_signals prototype
- Update the rpmsg_get_signals function header

Changes since v2:
- Modify the rpmsg_get_signals function prototype

Changes since v1:
- Split the patches as per functional areas like core, char, glink
- Add set, clear mask for TIOCMSET
- Merge the char signal callback and POLLPRI patches

Arun Kumar Neelakantam (4):
  rpmsg: core: Add signal API support
  rpmsg: glink: Add support to handle signals command
  rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: char: Add signal callback and POLLPRI support

 drivers/rpmsg/qcom_glink_native.c | 126 ++
 drivers/rpmsg/rpmsg_char.c|  75 ++-
 drivers/rpmsg/rpmsg_core.c|  41 +
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  26 
 5 files changed, 270 insertions(+), 3 deletions(-)

-- 
2.7.4


[PATCH V4 4/4] rpmsg: char: Add signal callback and POLLPRI support

2020-05-12 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg and
send POLLPRI mask to indicate the signal change in POLL system call.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index e2f92f3..ae15d4f 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   bool sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -122,6 +125,19 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   struct rpmsg_eptdev *eptdev = priv;
+
+   eptdev->sig_pending = true;
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
+   return 0;
+}
+
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -138,6 +154,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;
 
@@ -156,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   eptdev->sig_pending = false;
 
/* Discard all SKBs */
skb_queue_purge(>queue);
@@ -266,6 +284,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (eptdev->sig_pending)
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -309,6 +330,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
 
switch (cmd) {
case TIOCMGET:
+   eptdev->sig_pending = false;
ret = rpmsg_get_signals(eptdev->ept);
if (ret >= 0)
ret = put_user(ret, (int __user *)arg);
-- 
2.7.4


[PATCH V4 1/4] rpmsg: core: Add signal API support

2020-05-12 Thread Arun Kumar Neelakantam
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 41 +
 drivers/rpmsg/rpmsg_internal.h |  5 +
 include/linux/rpmsg.h  | 26 ++
 3 files changed, 72 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index d6c3275..453790b 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.
  *
@@ -283,6 +284,42 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, 
u32 src, u32 dst,
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
+/**
+ * rpmsg_get_signals() - get the signals for this endpoint
+ * @ept:   the rpmsg endpoint
+ *
+ * Returns signal bits on success and an appropriate error value on failure.
+ */
+int rpmsg_get_signals(struct rpmsg_endpoint *ept)
+{
+   if (WARN_ON(!ept))
+   return -EINVAL;
+   if (!ept->ops->get_signals)
+   return -EOPNOTSUPP;
+
+   return ept->ops->get_signals(ept);
+}
+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);
+
 /*
  * match an rpmsg channel with a channel info struct.
  * this is used to make sure we're not creating rpmsg devices for channels
@@ -468,6 +505,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 3fc83cd..8958d6c 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.
  *
@@ -47,6 +48,8 @@ struct rpmsg_device_ops {
  * @trysendto: see @rpmsg_trysendto(), optional
  * @trysend_offchannel:see @rpmsg_trysend_offchannel(), optional
  * @poll:  see @rpmsg_poll(), 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
@@ -66,6 +69,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);
+   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..48c8ae3 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 @@ typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, 
int, void *, u32);
  * @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.

[PATCH V4 3/4] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

2020-05-12 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 53 +++---
 1 file changed, 50 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 4bbbacd..e2f92f3 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016, Linaro Ltd.
  * Copyright (c) 2012, Michal Simek 
  * Copyright (c) 2012, PetaLogix
@@ -19,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -269,15 +271,60 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+int __user *arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 set, clear, val;
+   int ret;
+
+   ret = get_user(val, arg);
+   if (ret)
+   return ret;
+   set = clear = 0;
+   switch (cmd) {
+   case TIOCMBIS:
+   set = val;
+   break;
+   case TIOCMBIC:
+   clear = val;
+   break;
+   case TIOCMSET:
+   set = val;
+   clear = ~val;
+   break;
+   }
+
+   set &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+   clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+
+   return rpmsg_set_signals(eptdev->ept, set, clear);
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_signals(eptdev->ept);
+   if (ret >= 0)
+   ret = put_user(ret, (int __user *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, (int __user *)arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
2.7.4


[PATCH V5 0/5] Add chrdev and name query support for GLINK

2020-05-12 Thread Arun Kumar Neelakantam
Add support for the GLINK rpmsg transport to register a rpmsg chrdev.
This will create the rpmsg_ctrl nodes for userspace clients to open 
rpmsg epts. The rpmsg chrdev allocation is done by allocating a local
channel which also allocates an ept. We need to add some guards against
edge cases for this chrdev because it will never fully open.

Changes since v4:
- Resending by removing approved patches

Changes since v3:
- Change to device_add_group for rpmsg name attr
- Add patch to unregister the rpmsg device
- Add patch to support compat ioctl for rpmsg char driver

Changes since v2:
- Revert change to make glink attribute table const

Changes since v1:
- Add explanation to dt-bindings commit message
- Add patch complete_all the open_req/ack variables
- Add patch to prevent null pointer dereference in chrdev channel release
- Change chrdev allocation to use glink channel allocation
- Change glink attr struct to const


Arun Kumar Neelakantam (1):
  rpmsg: glink: unregister rpmsg device during endpoint destroy

Chris Lew (4):
  rpmsg: glink: Use complete_all for open states
  rpmsg: Guard against null endpoint ops in destroy
  rpmsg: glink: Add support for rpmsg glink chrdev
  rpmsg: glink: Expose rpmsg name attr for glink

 drivers/rpmsg/qcom_glink_native.c | 79 +--
 drivers/rpmsg/rpmsg_core.c|  2 +-
 2 files changed, 77 insertions(+), 4 deletions(-)

-- 
2.7.4


[PATCH V5 2/5] rpmsg: Guard against null endpoint ops in destroy

2020-05-12 Thread Arun Kumar Neelakantam
From: Chris Lew 

In RPMSG GLINK the chrdev device will allocate an ept as part of the
rpdev creation. This device will not register endpoint ops even though
it has an allocated ept. Protect against the case where the device is
being destroyed.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index e330ec4..d6c3275 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -81,7 +81,7 @@ EXPORT_SYMBOL(rpmsg_create_ept);
  */
 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-   if (ept)
+   if (ept && ept->ops)
ept->ops->destroy_ept(ept);
 }
 EXPORT_SYMBOL(rpmsg_destroy_ept);
-- 
2.7.4


[PATCH V5 3/5] rpmsg: glink: Add support for rpmsg glink chrdev

2020-05-12 Thread Arun Kumar Neelakantam
From: Chris Lew 

RPMSG provides a char device interface to userspace. Probe the rpmsg
chrdev channel to enable the rpmsg_ctrl device creation on glink
transports.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 40 ++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 604f11f..3a7f87c 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1178,7 +1178,7 @@ static int qcom_glink_announce_create(struct rpmsg_device 
*rpdev)
__be32 *val = defaults;
int size;
 
-   if (glink->intentless)
+   if (glink->intentless || !completion_done(>open_ack))
return 0;
 
prop = of_find_property(np, "qcom,intents", NULL);
@@ -1574,6 +1574,40 @@ static void qcom_glink_cancel_rx_work(struct qcom_glink 
*glink)
kfree(dcmd);
 }
 
+static void qcom_glink_device_release(struct device *dev)
+{
+   struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+   struct glink_channel *channel = to_glink_channel(rpdev->ept);
+
+   /* Release qcom_glink_alloc_channel() reference */
+   kref_put(>refcount, qcom_glink_channel_release);
+   kfree(rpdev);
+}
+
+static int qcom_glink_create_chrdev(struct qcom_glink *glink)
+{
+   struct rpmsg_device *rpdev;
+   struct glink_channel *channel;
+
+   rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
+   if (!rpdev)
+   return -ENOMEM;
+
+   channel = qcom_glink_alloc_channel(glink, "rpmsg_chrdev");
+   if (IS_ERR(channel)) {
+   kfree(rpdev);
+   return PTR_ERR(channel);
+   }
+   channel->rpdev = rpdev;
+
+   rpdev->ept = >ept;
+   rpdev->ops = _device_ops;
+   rpdev->dev.parent = glink->dev;
+   rpdev->dev.release = qcom_glink_device_release;
+
+   return rpmsg_chrdev_register_device(rpdev);
+}
+
 struct qcom_glink *qcom_glink_native_probe(struct device *dev,
   unsigned long features,
   struct qcom_glink_pipe *rx,
@@ -1633,6 +1667,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
if (ret)
return ERR_PTR(ret);
 
+   ret = qcom_glink_create_chrdev(glink);
+   if (ret)
+   dev_err(glink->dev, "failed to register chrdev\n");
+
return glink;
 }
 EXPORT_SYMBOL_GPL(qcom_glink_native_probe);
-- 
2.7.4


[PATCH V5 1/5] rpmsg: glink: Use complete_all for open states

2020-05-12 Thread Arun Kumar Neelakantam
From: Chris Lew 

The open_req and open_ack completion variables are the state variables
to represet a remote channel as open. Use complete_all so there are no
races with waiters and using completion_done.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 1995f5b..604f11f 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -970,7 +970,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, 
unsigned int lcid)
return -EINVAL;
}
 
-   complete(>open_ack);
+   complete_all(>open_ack);
 
return 0;
 }
@@ -1413,7 +1413,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, 
unsigned int rcid,
channel->rcid = ret;
spin_unlock_irqrestore(>idr_lock, flags);
 
-   complete(>open_req);
+   complete_all(>open_req);
 
if (create_device) {
rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
-- 
2.7.4


[PATCH V5 4/5] rpmsg: glink: Expose rpmsg name attr for glink

2020-05-12 Thread Arun Kumar Neelakantam
From: Chris Lew 

Expose the name field as an attr so clients listening to uevents for
rpmsg can identify the edge the events correspond to.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 3a7f87c..0e8a28c0 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1574,6 +1574,26 @@ static void qcom_glink_cancel_rx_work(struct qcom_glink 
*glink)
kfree(dcmd);
 }
 
+static ssize_t rpmsg_name_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   int ret = 0;
+   const char *name;
+
+   ret = of_property_read_string(dev->of_node, "label", );
+   if (ret < 0)
+   name = dev->of_node->name;
+
+   return snprintf(buf, RPMSG_NAME_SIZE, "%s\n", name);
+}
+static DEVICE_ATTR_RO(rpmsg_name);
+
+static struct attribute *qcom_glink_attrs[] = {
+   _attr_rpmsg_name.attr,
+   NULL
+};
+ATTRIBUTE_GROUPS(qcom_glink);
+
 static void qcom_glink_device_release(struct device *dev)
 {
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
@@ -1638,6 +1658,12 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
idr_init(>lcids);
idr_init(>rcids);
 
+   glink->dev->groups = qcom_glink_groups;
+
+   ret = device_add_groups(dev, qcom_glink_groups);
+   if (ret)
+   dev_err(dev, "failed to add groups\n");
+
ret = of_property_read_string(dev->of_node, "label", >name);
if (ret < 0)
glink->name = dev->of_node->name;
-- 
2.7.4


[PATCH V5 5/5] rpmsg: glink: unregister rpmsg device during endpoint destroy

2020-05-12 Thread Arun Kumar Neelakantam
Rpmsg device unregister is not happening if channel close is triggered
from local side and causing re-registration of device failures.

Unregister rpmsg device for local close in endpoint destroy path.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 0e8a28c0..fc8ef66 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1207,6 +1207,7 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
 {
struct glink_channel *channel = to_glink_channel(ept);
struct qcom_glink *glink = channel->glink;
+   struct rpmsg_channel_info chinfo;
unsigned long flags;
 
spin_lock_irqsave(>recv_lock, flags);
@@ -1214,6 +1215,13 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
spin_unlock_irqrestore(>recv_lock, flags);
 
/* Decouple the potential rpdev from the channel */
+   if (channel->rpdev) {
+   strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+   chinfo.src = RPMSG_ADDR_ANY;
+   chinfo.dst = RPMSG_ADDR_ANY;
+
+   rpmsg_unregister_device(glink->dev, );
+   }
channel->rpdev = NULL;
 
qcom_glink_send_close_req(glink, channel);
@@ -1477,6 +1485,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, 
unsigned int rcid)
 
rpmsg_unregister_device(glink->dev, );
}
+   channel->rpdev = NULL;
 
qcom_glink_send_close_ack(glink, channel->rcid);
 
-- 
2.7.4


Re: [PATCH v7 2/4] soc: qcom: Add AOSS QMP driver

2019-05-21 Thread Arun Kumar Neelakantam

Hi Bjorn,

On 5/1/2019 10:07 AM, Bjorn Andersson wrote:

The Always On Subsystem (AOSS) Qualcomm Messaging Protocol (QMP) driver
is used to communicate with the AOSS for certain side-channel requests,
that are not available through the RPMh interface.

The communication is a very simple synchronous mechanism of messages
being written in message RAM and a doorbell in the AOSS is rung. As the
AOSS has processed the message length is cleared and an interrupt is
fired by the AOSS as acknowledgment.

The driver exposes the QDSS clock as a clock and the low-power state
associated with the remoteprocs in the system as a set of power-domains.

Signed-off-by: Bjorn Andersson 
---

Changes since v6:
- Squash the pd into the same driver as the communication, to simplify
   the interaction.
- Representing the QDSS clocks as a clock/power domain turns out to
   cascade into a request to make all Coresight drivers have a secondary
   compatible to replace the required bus clock with a required power
   domain. So in v7 this is exposed as a clock instead.
- Some error checking updates, as reported by Doug.

  drivers/soc/qcom/Kconfig |  11 +
  drivers/soc/qcom/Makefile|   1 +
  drivers/soc/qcom/qcom_aoss.c | 473 +++
  3 files changed, 485 insertions(+)
  create mode 100644 drivers/soc/qcom/qcom_aoss.c

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 1ee298f6bf17..3e460b334b47 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -3,6 +3,17 @@
  #
  menu "Qualcomm SoC drivers"
  
+config QCOM_AOSS_QMP

+   tristate "Qualcomm AOSS Driver"
+   depends on ARCH_QCOM || COMPILE_TEST
+   depends on MAILBOX
+   select PM_GENERIC_DOMAINS
+   help
+ This driver provides the means of communicating with and controlling
+ the low-power state for resources related to the remoteproc
+ subsystems as well as controlling the debug clocks exposed by the 
Always On
+ Subsystem (AOSS) using Qualcomm Messaging Protocol (QMP).
+
  config QCOM_COMMAND_DB
bool "Qualcomm Command DB"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index ffe519b0cb66..eeb088beb15f 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,5 +1,6 @@
  # SPDX-License-Identifier: GPL-2.0
  CFLAGS_rpmh-rsc.o := -I$(src)
+obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
  obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
  obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
  obj-$(CONFIG_QCOM_GLINK_SSR) +=   glink_ssr.o
diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
new file mode 100644
index ..f1fc26ab2e36
--- /dev/null
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, Linaro Ltd
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define QMP_DESC_MAGIC 0x0
+#define QMP_DESC_VERSION   0x4
+#define QMP_DESC_FEATURES  0x8
+
+/* AOP-side offsets */
+#define QMP_DESC_UCORE_LINK_STATE  0xc
+#define QMP_DESC_UCORE_LINK_STATE_ACK  0x10
+#define QMP_DESC_UCORE_CH_STATE0x14
+#define QMP_DESC_UCORE_CH_STATE_ACK0x18
+#define QMP_DESC_UCORE_MBOX_SIZE   0x1c
+#define QMP_DESC_UCORE_MBOX_OFFSET 0x20
+
+/* Linux-side offsets */
+#define QMP_DESC_MCORE_LINK_STATE  0x24
+#define QMP_DESC_MCORE_LINK_STATE_ACK  0x28
+#define QMP_DESC_MCORE_CH_STATE0x2c
+#define QMP_DESC_MCORE_CH_STATE_ACK0x30
+#define QMP_DESC_MCORE_MBOX_SIZE   0x34
+#define QMP_DESC_MCORE_MBOX_OFFSET 0x38
+
+#define QMP_STATE_UP   0x
+#define QMP_STATE_DOWN 0x
+
+#define QMP_MAGIC  0x4d41494c
+#define QMP_VERSION1
+
+/* Requests are expected to be 96 bytes long */
+#define QMP_MSG_LEN96
+
+/**
+ * struct qmp - driver state for QMP implementation
+ * @msgram: iomem referencing the message RAM used for communication
+ * @dev: reference to QMP device
+ * @mbox_client: mailbox client used to ring the doorbell on transmit
+ * @mbox_chan: mailbox channel used to ring the doorbell on transmit
+ * @offset: offset within @msgram where messages should be written
+ * @size: maximum size of the messages to be transmitted
+ * @event: wait_queue for synchronization with the IRQ
+ * @tx_lock: provides syncrhonization between multiple callers of qmp_send()
+ * @qdss_clk: QDSS clock hw struct
+ * @pd_data: genpd data
+ */
+struct qmp {
+   void __iomem *msgram;
+   struct device *dev;
+
+   struct mbox_client mbox_client;
+   struct mbox_chan *mbox_chan;
+
+   size_t offset;
+   size_t size;
+
+   wait_queue_head_t event;
+
+   struct mutex tx_lock;
+
+   struct clk_hw qdss_clk;
+   struct genpd_onecell_data pd_data;
+};
+
+struct qmp_pd {
+   struct qmp *qmp;
+   struct generic_pm_domain pd;
+};
+
+#define 

Re: [PATCH v2 2/7] soc: qcom: Add AOSS QMP communication driver

2019-01-10 Thread Arun Kumar Neelakantam



On 1/6/2019 1:39 PM, Bjorn Andersson wrote:

The AOSS QMP driver is used to communicate with the AOSS for certain
side-channel requests, that are not enabled through the RPMh interface.

The communication is a very simple synchronous mechanism of messages
being written in message RAM and a doorbell in the AOSS is rung. As the
AOSS has processed the message length is cleared and an interrupt is
fired by the AOSS as acknowledgment.

Signed-off-by: Bjorn Andersson 
---

Reviewed-by: Arun Kumar Neelakantam 

Changes since v1:
- Skip check in send for empty TX buffer
- Don't follow WARN_ON() with dev_err()
- Register platform_device rather than populate based on of-children

  drivers/soc/qcom/Kconfig  |   9 +
  drivers/soc/qcom/Makefile |   1 +
  drivers/soc/qcom/aoss-qmp.c   | 313 ++
  include/linux/soc/qcom/aoss-qmp.h |  12 ++
  4 files changed, 335 insertions(+)
  create mode 100644 drivers/soc/qcom/aoss-qmp.c
  create mode 100644 include/linux/soc/qcom/aoss-qmp.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index a51458022d21..dda19471057f 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -3,6 +3,15 @@
  #
  menu "Qualcomm SoC drivers"
  
+config QCOM_AOSS_QMP

+   tristate "Qualcomm AOSS Messaging Driver"
+   depends on ARCH_QCOM || COMPILE_TEST
+   depends on MAILBOX
+   help
+ This driver provides the means for communicating with the
+ micro-controller in the AOSS, using QMP, to control certain resource
+ that are not exposed through RPMh.
+
  config QCOM_COMMAND_DB
bool "Qualcomm Command DB"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 67cb85d0373c..d0d7fdc94d9a 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,5 +1,6 @@
  # SPDX-License-Identifier: GPL-2.0
  CFLAGS_rpmh-rsc.o := -I$(src)
+obj-$(CONFIG_QCOM_AOSS_QMP) += aoss-qmp.o
  obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
  obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
  obj-$(CONFIG_QCOM_GLINK_SSR) +=   glink_ssr.o
diff --git a/drivers/soc/qcom/aoss-qmp.c b/drivers/soc/qcom/aoss-qmp.c
new file mode 100644
index ..de52703b96b6
--- /dev/null
+++ b/drivers/soc/qcom/aoss-qmp.c
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, Linaro Ltd
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define QMP_DESC_MAGIC 0x0
+#define QMP_DESC_VERSION   0x4
+#define QMP_DESC_FEATURES  0x8
+
+#define QMP_DESC_UCORE_LINK_STATE  0xc
+#define QMP_DESC_UCORE_LINK_STATE_ACK  0x10
+#define QMP_DESC_UCORE_CH_STATE0x14
+#define QMP_DESC_UCORE_CH_STATE_ACK0x18
+#define QMP_DESC_UCORE_MBOX_SIZE   0x1c
+#define QMP_DESC_UCORE_MBOX_OFFSET 0x20
+
+#define QMP_DESC_MCORE_LINK_STATE  0x24
+#define QMP_DESC_MCORE_LINK_STATE_ACK  0x28
+#define QMP_DESC_MCORE_CH_STATE0x2c
+#define QMP_DESC_MCORE_CH_STATE_ACK0x30
+#define QMP_DESC_MCORE_MBOX_SIZE   0x34
+#define QMP_DESC_MCORE_MBOX_OFFSET 0x38
+
+#define QMP_STATE_UP   0x
+#define QMP_STATE_DOWN 0x
+
+#define QMP_MAGIC  0x4d41494c
+#define QMP_VERSION1
+
+/**
+ * struct qmp - driver state for QMP implementation
+ * @msgram: iomem referencing the message RAM used for communication
+ * @dev: reference to QMP device
+ * @mbox_client: mailbox client used to ring the doorbell on transmit
+ * @mbox_chan: mailbox channel used to ring the doorbell on transmit
+ * @offset: offset within @msgram where messages should be written
+ * @size: maximum size of the messages to be transmitted
+ * @event: wait_queue for synchronization with the IRQ
+ * @tx_lock: provides syncrhonization between multiple callers of qmp_send()
+ * @pd_pdev: platform device for the power-domain child device
+ */
+struct qmp {
+   void __iomem *msgram;
+   struct device *dev;
+
+   struct mbox_client mbox_client;
+   struct mbox_chan *mbox_chan;
+
+   size_t offset;
+   size_t size;
+
+   wait_queue_head_t event;
+
+   struct mutex tx_lock;
+
+   struct platform_device *pd_pdev;
+};
+
+static void qmp_kick(struct qmp *qmp)
+{
+   mbox_send_message(qmp->mbox_chan, NULL);
+   mbox_client_txdone(qmp->mbox_chan, 0);
+}
+
+static bool qmp_magic_valid(struct qmp *qmp)
+{
+   return readl(qmp->msgram + QMP_DESC_MAGIC) == QMP_MAGIC;
+}
+
+static bool qmp_link_acked(struct qmp *qmp)
+{
+   return readl(qmp->msgram + QMP_DESC_MCORE_LINK_STATE_ACK) == 
QMP_STATE_UP;
+}
+
+static bool qmp_mcore_channel_acked(struct qmp *qmp)
+{
+   return readl(qmp->msgram + QMP_DESC_MCORE_CH_STATE_ACK) == QMP_STATE_UP;
+}
+
+static bool qmp_ucore_channel_up(struct qmp *qmp)
+{
+   return readl(qmp->msgram + QMP_DESC_UCORE_CH_STATE) == QMP_STATE_UP;
+}
+
+static 

Re: [PATCH 2/3] soc: qcom: Add AOSS QMP communication driver

2019-01-03 Thread Arun Kumar Neelakantam



On 12/27/2018 1:58 AM, Bjorn Andersson wrote:

On Tue 20 Nov 04:22 PST 2018, Arun Kumar Neelakantam wrote:

Thanks for the review Arun.


On 11/12/2018 1:35 PM, Bjorn Andersson wrote:

[..]

+int qmp_send(struct qmp *qmp, const void *data, size_t len)
+{
+   int ret;
+
+   if (WARN_ON(len + sizeof(u32) > qmp->size)) {
+   dev_err(qmp->dev, "message too long\n");
+   return -EINVAL;
+   }
+
+   if (WARN_ON(len % sizeof(u32))) {
+   dev_err(qmp->dev, "message not 32-bit aligned\n");
+   return -EINVAL;
+   }
+
+   mutex_lock(>tx_lock);
+
+   if (!qmp_message_empty(qmp)) {
+   dev_err(qmp->dev, "mailbox left busy\n");
+   ret = -EINVAL;

should it be -EBUSY ?

That makes more sense.


And qmp_messge_empty will be done either by remote if it process the data
else by this driver in TIMEOUT case, so does we need this check for every TX
? I think we can just reset to Zero once in open time.

Didn't think about that, should we really make the QMP link ready again
when we get a timeout? Can we expect that the firmware of the remote
side is ready to serve future messages?


Should we keep this check and remove the writel() below?
I prefer we can just remove this check and keep writel() below same as 
down stream.



+   goto out_unlock;
+   }
+
+   /* The message RAM only implements 32-bit accesses */
+   __iowrite32_copy(qmp->msgram + qmp->offset + sizeof(u32),
+data, len / sizeof(u32));
+   writel(len, qmp->msgram + qmp->offset);
+   qmp_kick(qmp);
+
+   ret = wait_event_interruptible_timeout(qmp->event,
+  qmp_message_empty(qmp), HZ);
+   if (!ret) {
+   dev_err(qmp->dev, "ucore did not ack channel\n");
+   ret = -ETIMEDOUT;
+
+   writel(0, qmp->msgram + qmp->offset);
+   } else {
+   ret = 0;
+   }
+
+out_unlock:
+   mutex_unlock(>tx_lock);
+
+   return ret;
+}

Regards,
Bjorn


[PATCH V4 4/4] rpmsg: char: Add signal callback and POLLPRI support

2018-10-08 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg and
send POLLPRI mask to indicate the signal change in POLL system call.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index b136684..8a3cbe9 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   bool sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -122,6 +125,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   struct rpmsg_eptdev *eptdev = priv;
+
+   eptdev->sig_pending = true;
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
+   return 0;
+}
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -138,6 +153,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;
 
@@ -157,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   eptdev->sig_pending = false;
 
/* Discard all SKBs */
while (!skb_queue_empty(>queue)) {
@@ -263,6 +280,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (eptdev->sig_pending)
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -306,6 +326,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
 
switch (cmd) {
case TIOCMGET:
+   eptdev->sig_pending = false;
ret = rpmsg_get_signals(eptdev->ept);
if (ret >= 0)
ret = put_user(ret, (int __user *)arg);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 4/4] rpmsg: char: Add signal callback and POLLPRI support

2018-10-08 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg and
send POLLPRI mask to indicate the signal change in POLL system call.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index b136684..8a3cbe9 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   bool sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -122,6 +125,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   struct rpmsg_eptdev *eptdev = priv;
+
+   eptdev->sig_pending = true;
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
+   return 0;
+}
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -138,6 +153,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;
 
@@ -157,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   eptdev->sig_pending = false;
 
/* Discard all SKBs */
while (!skb_queue_empty(>queue)) {
@@ -263,6 +280,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (eptdev->sig_pending)
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -306,6 +326,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
 
switch (cmd) {
case TIOCMGET:
+   eptdev->sig_pending = false;
ret = rpmsg_get_signals(eptdev->ept);
if (ret >= 0)
ret = put_user(ret, (int __user *)arg);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 3/4] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

2018-10-08 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 53 +++---
 1 file changed, 50 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a76b963..b136684 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016, Linaro Ltd.
  * Copyright (c) 2012, Michal Simek 
  * Copyright (c) 2012, PetaLogix
@@ -19,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -266,15 +268,60 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+int __user *arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 set, clear, val;
+   int ret;
+
+   ret = get_user(val, arg);
+   if (ret)
+   return ret;
+   set = clear = 0;
+   switch (cmd) {
+   case TIOCMBIS:
+   set = val;
+   break;
+   case TIOCMBIC:
+   clear = val;
+   break;
+   case TIOCMSET:
+   set = val;
+   clear = ~val;
+   break;
+   }
+
+   set &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+   clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+
+   return rpmsg_set_signals(eptdev->ept, set, clear);
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_signals(eptdev->ept);
+   if (ret >= 0)
+   ret = put_user(ret, (int __user *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, (int __user *)arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 3/4] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

2018-10-08 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 53 +++---
 1 file changed, 50 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a76b963..b136684 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016, Linaro Ltd.
  * Copyright (c) 2012, Michal Simek 
  * Copyright (c) 2012, PetaLogix
@@ -19,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -266,15 +268,60 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+int __user *arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 set, clear, val;
+   int ret;
+
+   ret = get_user(val, arg);
+   if (ret)
+   return ret;
+   set = clear = 0;
+   switch (cmd) {
+   case TIOCMBIS:
+   set = val;
+   break;
+   case TIOCMBIC:
+   clear = val;
+   break;
+   case TIOCMSET:
+   set = val;
+   clear = ~val;
+   break;
+   }
+
+   set &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+   clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+
+   return rpmsg_set_signals(eptdev->ept, set, clear);
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_signals(eptdev->ept);
+   if (ret >= 0)
+   ret = put_user(ret, (int __user *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, (int __user *)arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 2/4] rpmsg: glink: Add support to handle signals command

2018-10-08 Thread Arun Kumar Neelakantam
Remote peripherals send signal notifications over glink with commandID 15.

Add support to send and receive the signal command and convert the signals
from NATIVE to TIOCM while receiving and vice versa while sending.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 126 ++
 1 file changed, 126 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index e2ce4e6..e90f543 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016-2017, Linaro Ltd
  */
 
@@ -17,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -150,6 +152,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: local side signals
+ * @rsigs: remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +185,10 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
+
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,9 +209,15 @@ struct glink_channel {
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG  BIT(29)
+#define NATIVE_RI_SIG  BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -957,6 +971,76 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb) {
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+   }
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1018,6 +1102,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_CMD_SIGNALS:
+   qcom_glink_handle_signals(glink, param1, param2);
+   qcom_glink_rx_advance

[PATCH V4 0/4] Add TIOCM Signals support for RPMSG char devices

2018-10-08 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Changes since v1:
- Split the patches as per functional areas like core, char, glink
- Add set, clear mask for TIOCMSET
- Merge the char signal callback and POLLPRI patches

Changes since v2:
- Modify the rpmsg_get_signals function prototype

Changes since v3:
- Correct the TICOMGET case handling as per new rpmsg_get_signals prototype
- Update the rpmsg_get_signals function header

Arun Kumar Neelakantam (4):
  rpmsg: core: Add signal API support
  rpmsg: glink: Add support to handle signals command
  rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: char: Add signal callback and POLLPRI support

 drivers/rpmsg/qcom_glink_native.c | 126 ++
 drivers/rpmsg/rpmsg_char.c|  74 +-
 drivers/rpmsg/rpmsg_core.c|  41 +
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  26 
 5 files changed, 269 insertions(+), 3 deletions(-)

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



[PATCH V4 2/4] rpmsg: glink: Add support to handle signals command

2018-10-08 Thread Arun Kumar Neelakantam
Remote peripherals send signal notifications over glink with commandID 15.

Add support to send and receive the signal command and convert the signals
from NATIVE to TIOCM while receiving and vice versa while sending.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 126 ++
 1 file changed, 126 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index e2ce4e6..e90f543 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016-2017, Linaro Ltd
  */
 
@@ -17,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -150,6 +152,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: local side signals
+ * @rsigs: remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +185,10 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
+
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,9 +209,15 @@ struct glink_channel {
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG  BIT(29)
+#define NATIVE_RI_SIG  BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -957,6 +971,76 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb) {
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+   }
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1018,6 +1102,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_CMD_SIGNALS:
+   qcom_glink_handle_signals(glink, param1, param2);
+   qcom_glink_rx_advance

[PATCH V4 0/4] Add TIOCM Signals support for RPMSG char devices

2018-10-08 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Changes since v1:
- Split the patches as per functional areas like core, char, glink
- Add set, clear mask for TIOCMSET
- Merge the char signal callback and POLLPRI patches

Changes since v2:
- Modify the rpmsg_get_signals function prototype

Changes since v3:
- Correct the TICOMGET case handling as per new rpmsg_get_signals prototype
- Update the rpmsg_get_signals function header

Arun Kumar Neelakantam (4):
  rpmsg: core: Add signal API support
  rpmsg: glink: Add support to handle signals command
  rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: char: Add signal callback and POLLPRI support

 drivers/rpmsg/qcom_glink_native.c | 126 ++
 drivers/rpmsg/rpmsg_char.c|  74 +-
 drivers/rpmsg/rpmsg_core.c|  41 +
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  26 
 5 files changed, 269 insertions(+), 3 deletions(-)

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



[PATCH V4 1/4] rpmsg: core: Add signal API support

2018-10-08 Thread Arun Kumar Neelakantam
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 41 +
 drivers/rpmsg/rpmsg_internal.h |  5 +
 include/linux/rpmsg.h  | 26 ++
 3 files changed, 72 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 8122807..3d7458a 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.
  *
@@ -283,6 +284,42 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, 
u32 src, u32 dst,
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
+/**
+ * rpmsg_get_signals() - get the signals for this endpoint
+ * @ept:   the rpmsg endpoint
+ *
+ * Returns signal bits on success and an appropriate error value on failure.
+ */
+int rpmsg_get_signals(struct rpmsg_endpoint *ept)
+{
+   if (WARN_ON(!ept))
+   return -EINVAL;
+   if (!ept->ops->get_signals)
+   return -EOPNOTSUPP;
+
+   return ept->ops->get_signals(ept);
+}
+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);
+
 /*
  * match an rpmsg channel with a channel info struct.
  * this is used to make sure we're not creating rpmsg devices for channels
@@ -468,6 +505,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..033656d 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);
+   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..48c8ae3 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 c

[PATCH V4 1/4] rpmsg: core: Add signal API support

2018-10-08 Thread Arun Kumar Neelakantam
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 41 +
 drivers/rpmsg/rpmsg_internal.h |  5 +
 include/linux/rpmsg.h  | 26 ++
 3 files changed, 72 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 8122807..3d7458a 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.
  *
@@ -283,6 +284,42 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, 
u32 src, u32 dst,
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
+/**
+ * rpmsg_get_signals() - get the signals for this endpoint
+ * @ept:   the rpmsg endpoint
+ *
+ * Returns signal bits on success and an appropriate error value on failure.
+ */
+int rpmsg_get_signals(struct rpmsg_endpoint *ept)
+{
+   if (WARN_ON(!ept))
+   return -EINVAL;
+   if (!ept->ops->get_signals)
+   return -EOPNOTSUPP;
+
+   return ept->ops->get_signals(ept);
+}
+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);
+
 /*
  * match an rpmsg channel with a channel info struct.
  * this is used to make sure we're not creating rpmsg devices for channels
@@ -468,6 +505,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..033656d 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);
+   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..48c8ae3 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 c

[PATCH V3 3/4] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

2018-10-05 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 53 +++---
 1 file changed, 50 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a76b963..16978f7b 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016, Linaro Ltd.
  * Copyright (c) 2012, Michal Simek 
  * Copyright (c) 2012, PetaLogix
@@ -19,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -266,15 +268,60 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+int __user *arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 set, clear, val;
+   int ret;
+
+   ret = get_user(val, arg);
+   if (ret)
+   return ret;
+   set = clear = 0;
+   switch (cmd) {
+   case TIOCMBIS:
+   set = val;
+   break;
+   case TIOCMBIC:
+   clear = val;
+   break;
+   case TIOCMSET:
+   set = val;
+   clear = ~val;
+   break;
+   }
+
+   set &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+   clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+
+   return rpmsg_set_signals(eptdev->ept, set, clear);
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_signals(eptdev->ept);
+   if (!ret)
+   ret = put_user(ret, (int __user *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, (int __user *)arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V3 4/4] rpmsg: char: Add signal callback and POLLPRI support

2018-10-05 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg and
send POLLPRI mask to indicate the signal change in POLL system call.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 16978f7b..a5855f7 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   bool sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -122,6 +125,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   struct rpmsg_eptdev *eptdev = priv;
+
+   eptdev->sig_pending = true;
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
+   return 0;
+}
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -138,6 +153,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;
 
@@ -157,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   eptdev->sig_pending = false;
 
/* Discard all SKBs */
while (!skb_queue_empty(>queue)) {
@@ -263,6 +280,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (eptdev->sig_pending)
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -306,6 +326,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
 
switch (cmd) {
case TIOCMGET:
+   eptdev->sig_pending = false;
ret = rpmsg_get_signals(eptdev->ept);
if (!ret)
ret = put_user(ret, (int __user *)arg);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V3 3/4] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

2018-10-05 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 53 +++---
 1 file changed, 50 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a76b963..16978f7b 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016, Linaro Ltd.
  * Copyright (c) 2012, Michal Simek 
  * Copyright (c) 2012, PetaLogix
@@ -19,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -266,15 +268,60 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+int __user *arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 set, clear, val;
+   int ret;
+
+   ret = get_user(val, arg);
+   if (ret)
+   return ret;
+   set = clear = 0;
+   switch (cmd) {
+   case TIOCMBIS:
+   set = val;
+   break;
+   case TIOCMBIC:
+   clear = val;
+   break;
+   case TIOCMSET:
+   set = val;
+   clear = ~val;
+   break;
+   }
+
+   set &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+   clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+
+   return rpmsg_set_signals(eptdev->ept, set, clear);
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_signals(eptdev->ept);
+   if (!ret)
+   ret = put_user(ret, (int __user *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, (int __user *)arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V3 4/4] rpmsg: char: Add signal callback and POLLPRI support

2018-10-05 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg and
send POLLPRI mask to indicate the signal change in POLL system call.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 16978f7b..a5855f7 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   bool sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -122,6 +125,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   struct rpmsg_eptdev *eptdev = priv;
+
+   eptdev->sig_pending = true;
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
+   return 0;
+}
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -138,6 +153,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;
 
@@ -157,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   eptdev->sig_pending = false;
 
/* Discard all SKBs */
while (!skb_queue_empty(>queue)) {
@@ -263,6 +280,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (eptdev->sig_pending)
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -306,6 +326,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
 
switch (cmd) {
case TIOCMGET:
+   eptdev->sig_pending = false;
ret = rpmsg_get_signals(eptdev->ept);
if (!ret)
ret = put_user(ret, (int __user *)arg);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V3 2/4] rpmsg: glink: Add support to handle signals command

2018-10-05 Thread Arun Kumar Neelakantam
Remote peripherals send signal notifications over glink with commandID 15.

Add support to send and receive the signal command and convert the signals
from NATIVE to TIOCM while receiving and vice versa while sending.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 126 ++
 1 file changed, 126 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index e2ce4e6..e90f543 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016-2017, Linaro Ltd
  */
 
@@ -17,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -150,6 +152,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: local side signals
+ * @rsigs: remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +185,10 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
+
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,9 +209,15 @@ struct glink_channel {
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG  BIT(29)
+#define NATIVE_RI_SIG  BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -957,6 +971,76 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb) {
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+   }
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1018,6 +1102,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_CMD_SIGNALS:
+   qcom_glink_handle_signals(glink, param1, param2);
+   qcom_glink_rx_advance

[PATCH V3 2/4] rpmsg: glink: Add support to handle signals command

2018-10-05 Thread Arun Kumar Neelakantam
Remote peripherals send signal notifications over glink with commandID 15.

Add support to send and receive the signal command and convert the signals
from NATIVE to TIOCM while receiving and vice versa while sending.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 126 ++
 1 file changed, 126 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index e2ce4e6..e90f543 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016-2017, Linaro Ltd
  */
 
@@ -17,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -150,6 +152,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: local side signals
+ * @rsigs: remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +185,10 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
+
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,9 +209,15 @@ struct glink_channel {
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG  BIT(29)
+#define NATIVE_RI_SIG  BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -957,6 +971,76 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb) {
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+   }
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1018,6 +1102,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_CMD_SIGNALS:
+   qcom_glink_handle_signals(glink, param1, param2);
+   qcom_glink_rx_advance

[PATCH V3 1/4] rpmsg: core: Add signal API support

2018-10-05 Thread Arun Kumar Neelakantam
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 41 +
 drivers/rpmsg/rpmsg_internal.h |  5 +
 include/linux/rpmsg.h  | 26 ++
 3 files changed, 72 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 8122807..e9b719b 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.
  *
@@ -283,6 +284,42 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, 
u32 src, u32 dst,
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
+/**
+ * rpmsg_get_signals() - get the signals for this endpoint
+ * @ept:   the rpmsg endpoint
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_get_signals(struct rpmsg_endpoint *ept)
+{
+   if (WARN_ON(!ept))
+   return -EINVAL;
+   if (!ept->ops->get_signals)
+   return -EOPNOTSUPP;
+
+   return ept->ops->get_signals(ept);
+}
+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);
+
 /*
  * match an rpmsg channel with a channel info struct.
  * this is used to make sure we're not creating rpmsg devices for channels
@@ -468,6 +505,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..033656d 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);
+   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..48c8ae3 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 r

[PATCH V3 0/4] Add TIOCM Signals support for RPMSG char devices

2018-10-05 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Changes since v1:
- Split the patches as per functional areas like core, char, glink
- Add set, clear mask for TIOCMSET
- Merge the char signal callback and POLLPRI patches

Changes since v2:
- Modify the rpmsg_get_signals function prototype

Arun Kumar Neelakantam (4):
  rpmsg: core: Add signal API support
  rpmsg: glink: Add support to handle signals command
  rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: char: Add signal callback and POLLPRI support

 drivers/rpmsg/qcom_glink_native.c | 126 ++
 drivers/rpmsg/rpmsg_char.c|  74 +-
 drivers/rpmsg/rpmsg_core.c|  41 +
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  26 
 5 files changed, 269 insertions(+), 3 deletions(-)

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



[PATCH V3 1/4] rpmsg: core: Add signal API support

2018-10-05 Thread Arun Kumar Neelakantam
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 41 +
 drivers/rpmsg/rpmsg_internal.h |  5 +
 include/linux/rpmsg.h  | 26 ++
 3 files changed, 72 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 8122807..e9b719b 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.
  *
@@ -283,6 +284,42 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, 
u32 src, u32 dst,
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
+/**
+ * rpmsg_get_signals() - get the signals for this endpoint
+ * @ept:   the rpmsg endpoint
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_get_signals(struct rpmsg_endpoint *ept)
+{
+   if (WARN_ON(!ept))
+   return -EINVAL;
+   if (!ept->ops->get_signals)
+   return -EOPNOTSUPP;
+
+   return ept->ops->get_signals(ept);
+}
+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);
+
 /*
  * match an rpmsg channel with a channel info struct.
  * this is used to make sure we're not creating rpmsg devices for channels
@@ -468,6 +505,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..033656d 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);
+   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..48c8ae3 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 r

[PATCH V3 0/4] Add TIOCM Signals support for RPMSG char devices

2018-10-05 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Changes since v1:
- Split the patches as per functional areas like core, char, glink
- Add set, clear mask for TIOCMSET
- Merge the char signal callback and POLLPRI patches

Changes since v2:
- Modify the rpmsg_get_signals function prototype

Arun Kumar Neelakantam (4):
  rpmsg: core: Add signal API support
  rpmsg: glink: Add support to handle signals command
  rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: char: Add signal callback and POLLPRI support

 drivers/rpmsg/qcom_glink_native.c | 126 ++
 drivers/rpmsg/rpmsg_char.c|  74 +-
 drivers/rpmsg/rpmsg_core.c|  41 +
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  26 
 5 files changed, 269 insertions(+), 3 deletions(-)

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



[PATCH V2 0/4] Add TIOCM Signals support for RPMSG char devices

2018-10-04 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Changes since v1:
- Split the patches as per functional areas like core, char, glink
- Add set, clear mask for TIOCMSET
- Merge the char signal callback and POLLPRI patches

Arun Kumar Neelakantam (4):
  rpmsg: core: Add signal API support
  rpmsg: glink: Add support to handle signals command
  rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: char: Add signal callback and POLLPRI support

 drivers/rpmsg/qcom_glink_native.c | 130 ++
 drivers/rpmsg/rpmsg_char.c|  75 +-
 drivers/rpmsg/rpmsg_core.c|  42 
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  27 
 5 files changed, 276 insertions(+), 3 deletions(-)

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



[PATCH V2 0/4] Add TIOCM Signals support for RPMSG char devices

2018-10-04 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Changes since v1:
- Split the patches as per functional areas like core, char, glink
- Add set, clear mask for TIOCMSET
- Merge the char signal callback and POLLPRI patches

Arun Kumar Neelakantam (4):
  rpmsg: core: Add signal API support
  rpmsg: glink: Add support to handle signals command
  rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: char: Add signal callback and POLLPRI support

 drivers/rpmsg/qcom_glink_native.c | 130 ++
 drivers/rpmsg/rpmsg_char.c|  75 +-
 drivers/rpmsg/rpmsg_core.c|  42 
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  27 
 5 files changed, 276 insertions(+), 3 deletions(-)

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



[PATCH V2 3/4] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

2018-10-04 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 54 +++---
 1 file changed, 51 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a76b963..9380c6e 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016, Linaro Ltd.
  * Copyright (c) 2012, Michal Simek 
  * Copyright (c) 2012, PetaLogix
@@ -19,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -266,15 +268,61 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+int __user *arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 set, clear, val;
+   int ret;
+
+   ret = get_user(val, arg);
+   if (ret)
+   return ret;
+   set = clear = 0;
+   switch (cmd) {
+   case TIOCMBIS:
+   set = val;
+   break;
+   case TIOCMBIC:
+   clear = val;
+   break;
+   case TIOCMSET:
+   set = val;
+   clear = ~val;
+   break;
+   }
+
+   set &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+   clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+
+   return rpmsg_set_signals(eptdev->ept, set, clear);
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 lsigs, rsigs;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_signals(eptdev->ept, , );
+   if (!ret)
+   ret = put_user(rsigs, (int __user *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, (int __user *)arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V2 3/4] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

2018-10-04 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 54 +++---
 1 file changed, 51 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a76b963..9380c6e 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016, Linaro Ltd.
  * Copyright (c) 2012, Michal Simek 
  * Copyright (c) 2012, PetaLogix
@@ -19,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -266,15 +268,61 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+int __user *arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 set, clear, val;
+   int ret;
+
+   ret = get_user(val, arg);
+   if (ret)
+   return ret;
+   set = clear = 0;
+   switch (cmd) {
+   case TIOCMBIS:
+   set = val;
+   break;
+   case TIOCMBIC:
+   clear = val;
+   break;
+   case TIOCMSET:
+   set = val;
+   clear = ~val;
+   break;
+   }
+
+   set &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+   clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_CD | TIOCM_RI;
+
+   return rpmsg_set_signals(eptdev->ept, set, clear);
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 lsigs, rsigs;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_signals(eptdev->ept, , );
+   if (!ret)
+   ret = put_user(rsigs, (int __user *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, (int __user *)arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V2 2/4] rpmsg: glink: Add support to handle signals command

2018-10-04 Thread Arun Kumar Neelakantam
Remote peripherals send signal notifications over glink with commandID 15.

Add support to send and receive the signal command and convert the signals
from NATIVE to TIOCM while receiving and vice versa while sending.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 130 ++
 1 file changed, 130 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index e2ce4e6..35e2009 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016-2017, Linaro Ltd
  */
 
@@ -17,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -150,6 +152,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: local side signals
+ * @rsigs: remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +185,10 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
+
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,9 +209,15 @@ struct glink_channel {
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG  BIT(29)
+#define NATIVE_RI_SIG  BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -957,6 +971,76 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb) {
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+   }
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1018,6 +1102,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_CMD_SIGNALS:
+   qcom_glink_handle_signals(glink, param1, param2);
+   qcom_glink_rx_advance

[PATCH V2 4/4] rpmsg: char: Add signal callback and POLLPRI support

2018-10-04 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg and
send POLLPRI mask to indicate the signal change in POLL system call.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 9380c6e..194d54a 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   bool sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -122,6 +125,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   struct rpmsg_eptdev *eptdev = priv;
+
+   eptdev->sig_pending = true;
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
+   return 0;
+}
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -138,6 +153,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;
 
@@ -157,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   eptdev->sig_pending = false;
 
/* Discard all SKBs */
while (!skb_queue_empty(>queue)) {
@@ -263,6 +280,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (eptdev->sig_pending)
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -307,6 +327,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
 
switch (cmd) {
case TIOCMGET:
+   eptdev->sig_pending = false;
ret = rpmsg_get_signals(eptdev->ept, , );
if (!ret)
ret = put_user(rsigs, (int __user *)arg);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V2 1/4] rpmsg: core: Add signal API support

2018-10-04 Thread Arun Kumar Neelakantam
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 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 

[PATCH V2 2/4] rpmsg: glink: Add support to handle signals command

2018-10-04 Thread Arun Kumar Neelakantam
Remote peripherals send signal notifications over glink with commandID 15.

Add support to send and receive the signal command and convert the signals
from NATIVE to TIOCM while receiving and vice versa while sending.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 130 ++
 1 file changed, 130 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index e2ce4e6..35e2009 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2018, The Linux Foundation.
  * Copyright (c) 2016-2017, Linaro Ltd
  */
 
@@ -17,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -150,6 +152,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: local side signals
+ * @rsigs: remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +185,10 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
+
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,9 +209,15 @@ struct glink_channel {
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG  BIT(29)
+#define NATIVE_RI_SIG  BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -957,6 +971,76 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb) {
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+   }
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1018,6 +1102,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_CMD_SIGNALS:
+   qcom_glink_handle_signals(glink, param1, param2);
+   qcom_glink_rx_advance

[PATCH V2 4/4] rpmsg: char: Add signal callback and POLLPRI support

2018-10-04 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg and
send POLLPRI mask to indicate the signal change in POLL system call.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 9380c6e..194d54a 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   bool sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -122,6 +125,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   struct rpmsg_eptdev *eptdev = priv;
+
+   eptdev->sig_pending = true;
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
+   return 0;
+}
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -138,6 +153,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;
 
@@ -157,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   eptdev->sig_pending = false;
 
/* Discard all SKBs */
while (!skb_queue_empty(>queue)) {
@@ -263,6 +280,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (eptdev->sig_pending)
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -307,6 +327,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
 
switch (cmd) {
case TIOCMGET:
+   eptdev->sig_pending = false;
ret = rpmsg_get_signals(eptdev->ept, , );
if (!ret)
ret = put_user(rsigs, (int __user *)arg);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V2 1/4] rpmsg: core: Add signal API support

2018-10-04 Thread Arun Kumar Neelakantam
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 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 

[PATCH] rpmsg: glink: smem: Support rx peak for size less than 4 bytes

2018-10-03 Thread Arun Kumar Neelakantam
The current rx peak function fails to read the data if size is
less than 4bytes.

Use memcpy_fromio to support data reads of size less than 4 bytes.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_smem.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index 2b5cf27..7b65443 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -89,15 +89,11 @@ static void glink_smem_rx_peak(struct qcom_glink_pipe *np,
tail -= pipe->native.length;
 
len = min_t(size_t, count, pipe->native.length - tail);
-   if (len) {
-   __ioread32_copy(data, pipe->fifo + tail,
-   len / sizeof(u32));
-   }
+   if (len)
+   memcpy_fromio(data, pipe->fifo + tail, len);
 
-   if (len != count) {
-   __ioread32_copy(data + len, pipe->fifo,
-   (count - len) / sizeof(u32));
-   }
+   if (len != count)
+   memcpy_fromio(data + len, pipe->fifo, (count - len));
 }
 
 static void glink_smem_rx_advance(struct qcom_glink_pipe *np,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] rpmsg: glink: smem: Support rx peak for size less than 4 bytes

2018-10-03 Thread Arun Kumar Neelakantam
The current rx peak function fails to read the data if size is
less than 4bytes.

Use memcpy_fromio to support data reads of size less than 4 bytes.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_smem.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index 2b5cf27..7b65443 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -89,15 +89,11 @@ static void glink_smem_rx_peak(struct qcom_glink_pipe *np,
tail -= pipe->native.length;
 
len = min_t(size_t, count, pipe->native.length - tail);
-   if (len) {
-   __ioread32_copy(data, pipe->fifo + tail,
-   len / sizeof(u32));
-   }
+   if (len)
+   memcpy_fromio(data, pipe->fifo + tail, len);
 
-   if (len != count) {
-   __ioread32_copy(data + len, pipe->fifo,
-   (count - len) / sizeof(u32));
-   }
+   if (len != count)
+   memcpy_fromio(data + len, pipe->fifo, (count - len));
 }
 
 static void glink_smem_rx_advance(struct qcom_glink_pipe *np,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 4/5] rpmsg: wakeup poll to notify signal update

2018-10-03 Thread Arun Kumar Neelakantam
Add support to wait on poll to get signal notifications.
Send POLLPRI mask to indicate the signal change.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index c983d6c..aee5561 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   atomic_t sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -125,6 +128,12 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
 static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
 u32 old, u32 new)
 {
+   struct rpmsg_eptdev *eptdev = priv;
+
+   atomic_set(>sig_pending, 1);
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
return 0;
 }
 
@@ -164,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   atomic_set(>sig_pending, 0);
 
/* Discard all SKBs */
while (!skb_queue_empty(>queue)) {
@@ -270,6 +280,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (atomic_read(>sig_pending))
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -318,6 +331,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
ret = rpmsg_get_sigs(eptdev->ept, , );
if (!ret)
ret = put_user(rsigs, (u32 *)arg);
+   atomic_set(>sig_pending, 0);
break;
case TIOCMSET:
case TIOCMBIS:
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 3/5] rpmsg: Add TIOCMGET/TIOCMSET ioctl support

2018-10-03 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 54 +++---
 1 file changed, 51 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 86003d5..c983d6c 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -274,15 +275,62 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+unsigned long arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 lsigs, rsigs, val;
+   int ret;
+
+   ret = get_user(val, (u32 *)arg);
+   if (ret)
+   return ret;
+
+   ret = rpmsg_get_sigs(eptdev->ept, , );
+   if (ret < 0)
+   return ret;
+
+   switch (cmd) {
+   case TIOCMBIS:
+   lsigs |= val;
+   break;
+   case TIOCMBIC:
+   lsigs &= ~val;
+   break;
+   case TIOCMSET:
+   lsigs = val;
+   break;
+   }
+
+   ret = rpmsg_set_sigs(eptdev->ept, lsigs);
+   return ret;
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 lsigs, rsigs;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_sigs(eptdev->ept, , );
+   if (!ret)
+   ret = put_user(rsigs, (u32 *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 4/5] rpmsg: wakeup poll to notify signal update

2018-10-03 Thread Arun Kumar Neelakantam
Add support to wait on poll to get signal notifications.
Send POLLPRI mask to indicate the signal change.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index c983d6c..aee5561 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -64,6 +64,7 @@ struct rpmsg_ctrldev {
  * @queue_lock:synchronization of @queue operations
  * @queue: incoming message queue
  * @readq: wait object for incoming queue
+ * @sig_pending:state of signal notification
  */
 struct rpmsg_eptdev {
struct device dev;
@@ -78,6 +79,8 @@ struct rpmsg_eptdev {
spinlock_t queue_lock;
struct sk_buff_head queue;
wait_queue_head_t readq;
+
+   atomic_t sig_pending;
 };
 
 static int rpmsg_eptdev_destroy(struct device *dev, void *data)
@@ -125,6 +128,12 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
 static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
 u32 old, u32 new)
 {
+   struct rpmsg_eptdev *eptdev = priv;
+
+   atomic_set(>sig_pending, 1);
+
+   /* wake up any blocking processes, waiting for signal notification */
+   wake_up_interruptible(>readq);
return 0;
 }
 
@@ -164,6 +173,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct 
file *filp)
eptdev->ept = NULL;
}
mutex_unlock(>ept_lock);
+   atomic_set(>sig_pending, 0);
 
/* Discard all SKBs */
while (!skb_queue_empty(>queue)) {
@@ -270,6 +280,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
if (!skb_queue_empty(>queue))
mask |= EPOLLIN | EPOLLRDNORM;
 
+   if (atomic_read(>sig_pending))
+   mask |= POLLPRI;
+
mask |= rpmsg_poll(eptdev->ept, filp, wait);
 
return mask;
@@ -318,6 +331,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
ret = rpmsg_get_sigs(eptdev->ept, , );
if (!ret)
ret = put_user(rsigs, (u32 *)arg);
+   atomic_set(>sig_pending, 0);
break;
case TIOCMSET:
case TIOCMBIS:
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 3/5] rpmsg: Add TIOCMGET/TIOCMSET ioctl support

2018-10-03 Thread Arun Kumar Neelakantam
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes
to get/set the low level transport signals.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 54 +++---
 1 file changed, 51 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 86003d5..c983d6c 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -274,15 +275,62 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, 
poll_table *wait)
return mask;
 }
 
+static int rpmsg_eptdev_tiocmset(struct file *fp, unsigned int cmd,
+unsigned long arg)
+{
+   struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 lsigs, rsigs, val;
+   int ret;
+
+   ret = get_user(val, (u32 *)arg);
+   if (ret)
+   return ret;
+
+   ret = rpmsg_get_sigs(eptdev->ept, , );
+   if (ret < 0)
+   return ret;
+
+   switch (cmd) {
+   case TIOCMBIS:
+   lsigs |= val;
+   break;
+   case TIOCMBIC:
+   lsigs &= ~val;
+   break;
+   case TIOCMSET:
+   lsigs = val;
+   break;
+   }
+
+   ret = rpmsg_set_sigs(eptdev->ept, lsigs);
+   return ret;
+}
+
 static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
   unsigned long arg)
 {
struct rpmsg_eptdev *eptdev = fp->private_data;
+   u32 lsigs, rsigs;
+   int ret;
 
-   if (cmd != RPMSG_DESTROY_EPT_IOCTL)
-   return -EINVAL;
+   switch (cmd) {
+   case TIOCMGET:
+   ret = rpmsg_get_sigs(eptdev->ept, , );
+   if (!ret)
+   ret = put_user(rsigs, (u32 *)arg);
+   break;
+   case TIOCMSET:
+   case TIOCMBIS:
+   case TIOCMBIC:
+   ret = rpmsg_eptdev_tiocmset(fp, cmd, arg);
+   break;
+   case RPMSG_DESTROY_EPT_IOCTL:
+   ret = rpmsg_eptdev_destroy(>dev, NULL);
+   default:
+   ret = -EINVAL;
+   }
 
-   return rpmsg_eptdev_destroy(>dev, NULL);
+   return ret;
 }
 
 static const struct file_operations rpmsg_eptdev_fops = {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 5/5] rpmsg: glink: Convert the native signals to TIOCM

2018-10-03 Thread Arun Kumar Neelakantam
Native signals over SMEM transport are different from Linux TIOCM signals.
Add a macro to convert signals when sent or received from clients.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index ff8751b..3054c86 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -211,6 +212,11 @@ struct glink_channel {
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG BIT(29)
+#define NATIVE_RI_SIG BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -998,6 +1004,18 @@ static int qcom_glink_handle_signals(struct qcom_glink 
*glink,
}
 
old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
channel->rsigs = signals;
 
if (channel->ept.sig_cb)
@@ -1387,6 +1405,17 @@ static int qcom_glink_set_sigs(struct rpmsg_endpoint 
*ept, u32 sigs)
 
channel->lsigs = sigs;
 
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
return qcom_glink_send_signals(glink, channel, sigs);
 }
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 5/5] rpmsg: glink: Convert the native signals to TIOCM

2018-10-03 Thread Arun Kumar Neelakantam
Native signals over SMEM transport are different from Linux TIOCM signals.
Add a macro to convert signals when sent or received from clients.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index ff8751b..3054c86 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -211,6 +212,11 @@ struct glink_channel {
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
+#define NATIVE_DTR_SIG BIT(31)
+#define NATIVE_CTS_SIG BIT(30)
+#define NATIVE_CD_SIG BIT(29)
+#define NATIVE_RI_SIG BIT(28)
+
 static void qcom_glink_rx_done_work(struct work_struct *work);
 
 static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -998,6 +1004,18 @@ static int qcom_glink_handle_signals(struct qcom_glink 
*glink,
}
 
old = channel->rsigs;
+
+   /* convert signals from NATIVE to TIOCM */
+   if (signals & NATIVE_DTR_SIG)
+   signals |= TIOCM_DSR;
+   if (signals & NATIVE_CTS_SIG)
+   signals |= TIOCM_CTS;
+   if (signals & NATIVE_CD_SIG)
+   signals |= TIOCM_CD;
+   if (signals & NATIVE_RI_SIG)
+   signals |= TIOCM_RI;
+   signals &= 0x0fff;
+
channel->rsigs = signals;
 
if (channel->ept.sig_cb)
@@ -1387,6 +1405,17 @@ static int qcom_glink_set_sigs(struct rpmsg_endpoint 
*ept, u32 sigs)
 
channel->lsigs = sigs;
 
+   /* convert signals from TIOCM to NATIVE */
+   sigs &= 0x0fff;
+   if (sigs & TIOCM_DTR)
+   sigs |= NATIVE_DTR_SIG;
+   if (sigs & TIOCM_RTS)
+   sigs |= NATIVE_CTS_SIG;
+   if (sigs & TIOCM_CD)
+   sigs |= NATIVE_CD_SIG;
+   if (sigs & TIOCM_RI)
+   sigs |= NATIVE_RI_SIG;
+
return qcom_glink_send_signals(glink, channel, sigs);
 }
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 0/5] Add TIOCM Signals support for RPMSG char devices

2018-10-03 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Arun Kumar Neelakantam (5):
  rpmsg: glink: Add GLINK signal support for RPMSG
  rpmsg: Add signal callback to rpmsg char device
  rpmsg: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: wakeup poll to notify signal update
  rpmsg: glink: Convert the native signals to TIOCM

 drivers/rpmsg/qcom_glink_native.c | 109 ++
 drivers/rpmsg/rpmsg_char.c|  76 --
 drivers/rpmsg/rpmsg_core.c|  41 ++
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  25 +
 5 files changed, 253 insertions(+), 3 deletions(-)

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



[PATCH 2/5] rpmsg: Add signal callback to rpmsg char device

2018-10-03 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a76b963..86003d5 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2012, PetaLogix
  * Copyright (c) 2011, Texas Instruments, Inc.
  * Copyright (c) 2011, Google, Inc.
+ * Copyright (c) 2018, The Linux Foundation.
  *
  * Based on rpmsg performance statistics driver by Michal Simek, which in turn
  * was based on TI & Google OMX rpmsg driver.
@@ -120,6 +121,12 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   return 0;
+}
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -136,6 +143,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;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 0/5] Add TIOCM Signals support for RPMSG char devices

2018-10-03 Thread Arun Kumar Neelakantam
Glink transport support signals to exchange state notification between
local and remote side clients. Adding support to send/receive the signal
command and notify the clients through callback and POLL notification.

Arun Kumar Neelakantam (5):
  rpmsg: glink: Add GLINK signal support for RPMSG
  rpmsg: Add signal callback to rpmsg char device
  rpmsg: Add TIOCMGET/TIOCMSET ioctl support
  rpmsg: wakeup poll to notify signal update
  rpmsg: glink: Convert the native signals to TIOCM

 drivers/rpmsg/qcom_glink_native.c | 109 ++
 drivers/rpmsg/rpmsg_char.c|  76 --
 drivers/rpmsg/rpmsg_core.c|  41 ++
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  25 +
 5 files changed, 253 insertions(+), 3 deletions(-)

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



[PATCH 2/5] rpmsg: Add signal callback to rpmsg char device

2018-10-03 Thread Arun Kumar Neelakantam
Register a callback to get the signal notifications from rpmsg.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index a76b963..86003d5 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2012, PetaLogix
  * Copyright (c) 2011, Texas Instruments, Inc.
  * Copyright (c) 2011, Google, Inc.
+ * Copyright (c) 2018, The Linux Foundation.
  *
  * Based on rpmsg performance statistics driver by Michal Simek, which in turn
  * was based on TI & Google OMX rpmsg driver.
@@ -120,6 +121,12 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void 
*buf, int len,
return 0;
 }
 
+static int rpmsg_sigs_cb(struct rpmsg_device *rpdev, void *priv,
+u32 old, u32 new)
+{
+   return 0;
+}
+
 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
 {
struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
@@ -136,6 +143,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;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 1/5] rpmsg: glink: Add GLINK signal support for RPMSG

2018-10-03 Thread Arun Kumar Neelakantam
Add support to handle SMD signals to RPMSG over GLINK. SMD signals
mimic serial protocol signals to notify of ports opening and closing.
This change affects the rpmsg core, rpmsg char and glink drivers.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 80 +++
 drivers/rpmsg/rpmsg_core.c| 41 
 drivers/rpmsg/rpmsg_internal.h|  5 +++
 include/linux/rpmsg.h | 25 
 4 files changed, 151 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index f6988fd..ff8751b 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2016-2017, Linaro Ltd
+ * Copyright (c) 2018, The Linux Foundation.
  */
 
 #include 
@@ -150,6 +151,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: Local side signals
+ * @rsigs: Remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +184,9 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,6 +207,7 @@ struct glink_channel {
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
@@ -954,6 +961,52 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb)
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1015,6 +1068,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_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;
@@ -1312,6 +1369,27 @@ static int qcom_glink_trysend(struct rpmsg_endpoint 
*ept, void *data, int len)
return __qcom_glink_send(channel, data, len, false);
 }
 
+static int qcom_glink_get_sigs(struct rpmsg_endpoint *ept,
+  u32 *lsigs, u32 *rsigs)
+{
+   struct glink_channel *channel = to_glink_channel(ept);
+
+   *lsigs = channel->lsigs;
+   *rsigs = channel->rsigs;
+
+   return 0;
+}
+
+static int qcom_glink_set_sigs(struct rpmsg_endpoint *ept, u32 sigs)
+{
+   struct glink_channel *channel = to_glink_channel(ept);
+   struct qcom_glink *glink = channel->glink;
+
+   channel->lsigs = sigs;
+
+   return qcom_glink_send_signals(glink, channel, sigs);
+}
+
 /*
  * Finds the device_node for the glink chi

[PATCH 1/5] rpmsg: glink: Add GLINK signal support for RPMSG

2018-10-03 Thread Arun Kumar Neelakantam
Add support to handle SMD signals to RPMSG over GLINK. SMD signals
mimic serial protocol signals to notify of ports opening and closing.
This change affects the rpmsg core, rpmsg char and glink drivers.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 80 +++
 drivers/rpmsg/rpmsg_core.c| 41 
 drivers/rpmsg/rpmsg_internal.h|  5 +++
 include/linux/rpmsg.h | 25 
 4 files changed, 151 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index f6988fd..ff8751b 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2016-2017, Linaro Ltd
+ * Copyright (c) 2018, The Linux Foundation.
  */
 
 #include 
@@ -150,6 +151,8 @@ enum {
  * @intent_req_lock: Synchronises multiple intent requests
  * @intent_req_result: Result of intent request
  * @intent_req_comp: Completion for intent_req signalling
+ * @lsigs: Local side signals
+ * @rsigs: Remote side signals
  */
 struct glink_channel {
struct rpmsg_endpoint ept;
@@ -181,6 +184,9 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
struct completion intent_req_comp;
+
+   unsigned int lsigs;
+   unsigned int rsigs;
 };
 
 #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@@ -201,6 +207,7 @@ struct glink_channel {
 #define RPM_CMD_TX_DATA_CONT   12
 #define RPM_CMD_READ_NOTIF 13
 #define RPM_CMD_RX_DONE_W_REUSE14
+#define RPM_CMD_SIGNALS15
 
 #define GLINK_FEATURE_INTENTLESS   BIT(1)
 
@@ -954,6 +961,52 @@ static int qcom_glink_rx_open_ack(struct qcom_glink 
*glink, unsigned int lcid)
return 0;
 }
 
+/**
+ * qcom_glink_send_signals() - convert a signal  cmd to wire format and 
transmit
+ * @glink: The transport to transmit on.
+ * @channel:   The glink channel
+ * @sigs:  The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int qcom_glink_send_signals(struct qcom_glink *glink,
+  struct glink_channel *channel,
+  u32 sigs)
+{
+   struct glink_msg msg;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_SIGNALS);
+   msg.param1 = cpu_to_le16(channel->lcid);
+   msg.param2 = cpu_to_le32(sigs);
+
+   return qcom_glink_tx(glink, , sizeof(msg), NULL, 0, true);
+}
+
+static int qcom_glink_handle_signals(struct qcom_glink *glink,
+unsigned int rcid, unsigned int signals)
+{
+   struct glink_channel *channel;
+   unsigned long flags;
+   u32 old;
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "signal for non-existing channel\n");
+   return -EINVAL;
+   }
+
+   old = channel->rsigs;
+   channel->rsigs = signals;
+
+   if (channel->ept.sig_cb)
+   channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
+   old, channel->rsigs);
+
+   return 0;
+}
+
 static irqreturn_t qcom_glink_native_intr(int irq, void *data)
 {
struct qcom_glink *glink = data;
@@ -1015,6 +1068,10 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
qcom_glink_handle_intent_req_ack(glink, param1, param2);
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
break;
+   case RPM_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;
@@ -1312,6 +1369,27 @@ static int qcom_glink_trysend(struct rpmsg_endpoint 
*ept, void *data, int len)
return __qcom_glink_send(channel, data, len, false);
 }
 
+static int qcom_glink_get_sigs(struct rpmsg_endpoint *ept,
+  u32 *lsigs, u32 *rsigs)
+{
+   struct glink_channel *channel = to_glink_channel(ept);
+
+   *lsigs = channel->lsigs;
+   *rsigs = channel->rsigs;
+
+   return 0;
+}
+
+static int qcom_glink_set_sigs(struct rpmsg_endpoint *ept, u32 sigs)
+{
+   struct glink_channel *channel = to_glink_channel(ept);
+   struct qcom_glink *glink = channel->glink;
+
+   channel->lsigs = sigs;
+
+   return qcom_glink_send_signals(glink, channel, sigs);
+}
+
 /*
  * Finds the device_node for the glink chi

[PATCH V4 8/9] rpmsg: glink: unregister rpmsg device during endpoint destroy

2018-07-27 Thread Arun Kumar Neelakantam
Rpmsg device unregister is not happening if channel close is triggered
from local side and causing re-registration of device failures.

Unregister rpmsg device for local close in endpoint destroy path.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 484b427..d849bc4 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1184,6 +1184,7 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
 {
struct glink_channel *channel = to_glink_channel(ept);
struct qcom_glink *glink = channel->glink;
+   struct rpmsg_channel_info chinfo;
unsigned long flags;
 
spin_lock_irqsave(>recv_lock, flags);
@@ -1191,6 +1192,13 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
spin_unlock_irqrestore(>recv_lock, flags);
 
/* Decouple the potential rpdev from the channel */
+   if (channel->rpdev) {
+   strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+   chinfo.src = RPMSG_ADDR_ANY;
+   chinfo.dst = RPMSG_ADDR_ANY;
+
+   rpmsg_unregister_device(glink->dev, );
+   }
channel->rpdev = NULL;
 
qcom_glink_send_close_req(glink, channel);
@@ -1456,6 +1464,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, 
unsigned int rcid)
 
rpmsg_unregister_device(glink->dev, );
}
+   channel->rpdev = NULL;
 
qcom_glink_send_close_ack(glink, channel->rcid);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 8/9] rpmsg: glink: unregister rpmsg device during endpoint destroy

2018-07-27 Thread Arun Kumar Neelakantam
Rpmsg device unregister is not happening if channel close is triggered
from local side and causing re-registration of device failures.

Unregister rpmsg device for local close in endpoint destroy path.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 484b427..d849bc4 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1184,6 +1184,7 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
 {
struct glink_channel *channel = to_glink_channel(ept);
struct qcom_glink *glink = channel->glink;
+   struct rpmsg_channel_info chinfo;
unsigned long flags;
 
spin_lock_irqsave(>recv_lock, flags);
@@ -1191,6 +1192,13 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
spin_unlock_irqrestore(>recv_lock, flags);
 
/* Decouple the potential rpdev from the channel */
+   if (channel->rpdev) {
+   strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+   chinfo.src = RPMSG_ADDR_ANY;
+   chinfo.dst = RPMSG_ADDR_ANY;
+
+   rpmsg_unregister_device(glink->dev, );
+   }
channel->rpdev = NULL;
 
qcom_glink_send_close_req(glink, channel);
@@ -1456,6 +1464,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, 
unsigned int rcid)
 
rpmsg_unregister_device(glink->dev, );
}
+   channel->rpdev = NULL;
 
qcom_glink_send_close_ack(glink, channel->rcid);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 9/9] rpmsg: Add compat ioctl for rpmsg char driver

2018-07-27 Thread Arun Kumar Neelakantam
Add compat ioctl callback to support 32bit user space applications.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 76a4477..a76b963 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -285,6 +285,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
.write = rpmsg_eptdev_write,
.poll = rpmsg_eptdev_poll,
.unlocked_ioctl = rpmsg_eptdev_ioctl,
+   .compat_ioctl = rpmsg_eptdev_ioctl,
 };
 
 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
@@ -445,6 +446,7 @@ static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned 
int cmd,
.open = rpmsg_ctrldev_open,
.release = rpmsg_ctrldev_release,
.unlocked_ioctl = rpmsg_ctrldev_ioctl,
+   .compat_ioctl = rpmsg_ctrldev_ioctl,
 };
 
 static void rpmsg_ctrldev_release_device(struct device *dev)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 3/9] rpmsg: glink: Use complete_all for open states

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

The open_req and open_ack completion variables are the state variables
to represet a remote channel as open. Use complete_all so there are no
races with waiters and using completion_done.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 22a3cac..f43341d 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -949,7 +949,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, 
unsigned int lcid)
return -EINVAL;
}
 
-   complete(>open_ack);
+   complete_all(>open_ack);
 
return 0;
 }
@@ -1393,7 +1393,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, 
unsigned int rcid,
channel->rcid = ret;
spin_unlock_irqrestore(>idr_lock, flags);
 
-   complete(>open_req);
+   complete_all(>open_req);
 
if (create_device) {
rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 9/9] rpmsg: Add compat ioctl for rpmsg char driver

2018-07-27 Thread Arun Kumar Neelakantam
Add compat ioctl callback to support 32bit user space applications.

Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_char.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 76a4477..a76b963 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -285,6 +285,7 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned 
int cmd,
.write = rpmsg_eptdev_write,
.poll = rpmsg_eptdev_poll,
.unlocked_ioctl = rpmsg_eptdev_ioctl,
+   .compat_ioctl = rpmsg_eptdev_ioctl,
 };
 
 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
@@ -445,6 +446,7 @@ static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned 
int cmd,
.open = rpmsg_ctrldev_open,
.release = rpmsg_ctrldev_release,
.unlocked_ioctl = rpmsg_ctrldev_ioctl,
+   .compat_ioctl = rpmsg_ctrldev_ioctl,
 };
 
 static void rpmsg_ctrldev_release_device(struct device *dev)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 3/9] rpmsg: glink: Use complete_all for open states

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

The open_req and open_ack completion variables are the state variables
to represet a remote channel as open. Use complete_all so there are no
races with waiters and using completion_done.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 22a3cac..f43341d 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -949,7 +949,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, 
unsigned int lcid)
return -EINVAL;
}
 
-   complete(>open_ack);
+   complete_all(>open_ack);
 
return 0;
 }
@@ -1393,7 +1393,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, 
unsigned int rcid,
channel->rcid = ret;
spin_unlock_irqrestore(>idr_lock, flags);
 
-   complete(>open_req);
+   complete_all(>open_req);
 
if (create_device) {
rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 6/9] rpmsg: glink: Expose rpmsg name attr for glink

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

Expose the name field as an attr so clients listening to uevents for
rpmsg can identify the edge the events correspond to.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 9f3d026..7b4ffa0 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1544,6 +1544,26 @@ static void qcom_glink_work(struct work_struct *work)
}
 }
 
+static ssize_t rpmsg_name_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   int ret = 0;
+   const char *name;
+
+   ret = of_property_read_string(dev->of_node, "label", );
+   if (ret < 0)
+   name = dev->of_node->name;
+
+   return snprintf(buf, RPMSG_NAME_SIZE, "%s\n", name);
+}
+static DEVICE_ATTR_RO(rpmsg_name);
+
+static struct attribute *qcom_glink_attrs[] = {
+   _attr_rpmsg_name.attr,
+   NULL
+};
+ATTRIBUTE_GROUPS(qcom_glink);
+
 static void qcom_glink_device_release(struct device *dev)
 {
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
@@ -1593,6 +1613,12 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
return ERR_PTR(-ENOMEM);
 
glink->dev = dev;
+   glink->dev->groups = qcom_glink_groups;
+
+   ret = device_add_groups(dev, qcom_glink_groups);
+   if (ret)
+   dev_err(dev, "failed to add groups\n");
+
glink->tx_pipe = tx;
glink->rx_pipe = rx;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 2/9] rpmsg: glink: Store edge name for glink device

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

Channels may need to identify the edge their channel was probed for.
Store the edge name by reading the label property from device tree or
default to the node name.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index f505f58..22a3cac 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -93,6 +93,8 @@ struct glink_core_rx_intent {
 struct qcom_glink {
struct device *dev;
 
+   const char *name;
+
struct mbox_client mbox_client;
struct mbox_chan *mbox_chan;
 
@@ -1572,6 +1574,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
idr_init(>lcids);
idr_init(>rcids);
 
+   ret = of_property_read_string(dev->of_node, "label", >name);
+   if (ret < 0)
+   glink->name = dev->of_node->name;
+
glink->mbox_client.dev = dev;
glink->mbox_client.knows_txdone = true;
glink->mbox_chan = mbox_request_channel(>mbox_client, 0);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 7/9] rpmsg: glink: Remove chunk size word align warning

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

It is possible for the chunk sizes coming from the non RPM remote procs
to not be word aligned. Remove the alignment warning and continue to
read from the FIFO so execution is not stalled.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 7b4ffa0..484b427 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -789,9 +789,6 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return -EAGAIN;
}
 
-   if (WARN(chunk_size % 4, "Incoming data must be word aligned\n"))
-   return -EINVAL;
-
rcid = le16_to_cpu(hdr.msg.param1);
spin_lock_irqsave(>idr_lock, flags);
channel = idr_find(>rcids, rcid);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 6/9] rpmsg: glink: Expose rpmsg name attr for glink

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

Expose the name field as an attr so clients listening to uevents for
rpmsg can identify the edge the events correspond to.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 9f3d026..7b4ffa0 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1544,6 +1544,26 @@ static void qcom_glink_work(struct work_struct *work)
}
 }
 
+static ssize_t rpmsg_name_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   int ret = 0;
+   const char *name;
+
+   ret = of_property_read_string(dev->of_node, "label", );
+   if (ret < 0)
+   name = dev->of_node->name;
+
+   return snprintf(buf, RPMSG_NAME_SIZE, "%s\n", name);
+}
+static DEVICE_ATTR_RO(rpmsg_name);
+
+static struct attribute *qcom_glink_attrs[] = {
+   _attr_rpmsg_name.attr,
+   NULL
+};
+ATTRIBUTE_GROUPS(qcom_glink);
+
 static void qcom_glink_device_release(struct device *dev)
 {
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
@@ -1593,6 +1613,12 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
return ERR_PTR(-ENOMEM);
 
glink->dev = dev;
+   glink->dev->groups = qcom_glink_groups;
+
+   ret = device_add_groups(dev, qcom_glink_groups);
+   if (ret)
+   dev_err(dev, "failed to add groups\n");
+
glink->tx_pipe = tx;
glink->rx_pipe = rx;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 2/9] rpmsg: glink: Store edge name for glink device

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

Channels may need to identify the edge their channel was probed for.
Store the edge name by reading the label property from device tree or
default to the node name.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index f505f58..22a3cac 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -93,6 +93,8 @@ struct glink_core_rx_intent {
 struct qcom_glink {
struct device *dev;
 
+   const char *name;
+
struct mbox_client mbox_client;
struct mbox_chan *mbox_chan;
 
@@ -1572,6 +1574,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
idr_init(>lcids);
idr_init(>rcids);
 
+   ret = of_property_read_string(dev->of_node, "label", >name);
+   if (ret < 0)
+   glink->name = dev->of_node->name;
+
glink->mbox_client.dev = dev;
glink->mbox_client.knows_txdone = true;
glink->mbox_chan = mbox_request_channel(>mbox_client, 0);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 7/9] rpmsg: glink: Remove chunk size word align warning

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

It is possible for the chunk sizes coming from the non RPM remote procs
to not be word aligned. Remove the alignment warning and continue to
read from the FIFO so execution is not stalled.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 7b4ffa0..484b427 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -789,9 +789,6 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return -EAGAIN;
}
 
-   if (WARN(chunk_size % 4, "Incoming data must be word aligned\n"))
-   return -EINVAL;
-
rcid = le16_to_cpu(hdr.msg.param1);
spin_lock_irqsave(>idr_lock, flags);
channel = idr_find(>rcids, rcid);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 4/9] rpmsg: Guard against null endpoint ops in destroy

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

In RPMSG GLINK the chrdev device will allocate an ept as part of the
rpdev creation. This device will not register endpoint ops even though
it has an allocated ept. Protect against the case where the device is
being destroyed.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index b714a54..0860328 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -80,7 +80,7 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device 
*rpdev,
  */
 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-   if (ept)
+   if (ept && ept->ops)
ept->ops->destroy_ept(ept);
 }
 EXPORT_SYMBOL(rpmsg_destroy_ept);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 5/9] rpmsg: glink: Add support for rpmsg glink chrdev

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

RPMSG provides a char device interface to userspace. Probe the rpmsg
chrdev channel to enable the rpmsg_ctrl device creation on glink
transports.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 40 ++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index f43341d..9f3d026 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1158,7 +1158,7 @@ static int qcom_glink_announce_create(struct rpmsg_device 
*rpdev)
__be32 *val = defaults;
int size;
 
-   if (glink->intentless)
+   if (glink->intentless || !completion_done(>open_ack))
return 0;
 
prop = of_find_property(np, "qcom,intents", NULL);
@@ -1544,6 +1544,40 @@ static void qcom_glink_work(struct work_struct *work)
}
 }
 
+static void qcom_glink_device_release(struct device *dev)
+{
+   struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+   struct glink_channel *channel = to_glink_channel(rpdev->ept);
+
+   /* Release qcom_glink_alloc_channel() reference */
+   kref_put(>refcount, qcom_glink_channel_release);
+   kfree(rpdev);
+}
+
+static int qcom_glink_create_chrdev(struct qcom_glink *glink)
+{
+   struct rpmsg_device *rpdev;
+   struct glink_channel *channel;
+
+   rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
+   if (!rpdev)
+   return -ENOMEM;
+
+   channel = qcom_glink_alloc_channel(glink, "rpmsg_chrdev");
+   if (IS_ERR(channel)) {
+   kfree(rpdev);
+   return PTR_ERR(channel);
+   }
+   channel->rpdev = rpdev;
+
+   rpdev->ept = >ept;
+   rpdev->ops = _device_ops;
+   rpdev->dev.parent = glink->dev;
+   rpdev->dev.release = qcom_glink_device_release;
+
+   return rpmsg_chrdev_register_device(rpdev);
+}
+
 struct qcom_glink *qcom_glink_native_probe(struct device *dev,
   unsigned long features,
   struct qcom_glink_pipe *rx,
@@ -1603,6 +1637,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
if (ret)
return ERR_PTR(ret);
 
+   ret = qcom_glink_create_chrdev(glink);
+   if (ret)
+   dev_err(glink->dev, "failed to register chrdev\n");
+
return glink;
 }
 EXPORT_SYMBOL_GPL(qcom_glink_native_probe);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 1/9] dt-bindings: soc: qcom: Add label for GLINK bindings

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

There are GLINK clients who open the same channel on multiple GLINK
links. These clients need a way to distinguish which remoteproc they
are communicating to. Add a label property to identify the edge this
node represents.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt | 5 +
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt 
b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
index 9663cab..0b8cc53 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
@@ -10,6 +10,11 @@ edge.
Value type: 
Definition: must be "qcom,glink-rpm"
 
+- label:
+   Usage: optional
+   Value type: 
+   Definition: should specify the subsystem name this edge corresponds to.
+
 - interrupts:
Usage: required
Value type: 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 4/9] rpmsg: Guard against null endpoint ops in destroy

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

In RPMSG GLINK the chrdev device will allocate an ept as part of the
rpdev creation. This device will not register endpoint ops even though
it has an allocated ept. Protect against the case where the device is
being destroyed.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/rpmsg_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index b714a54..0860328 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -80,7 +80,7 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device 
*rpdev,
  */
 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-   if (ept)
+   if (ept && ept->ops)
ept->ops->destroy_ept(ept);
 }
 EXPORT_SYMBOL(rpmsg_destroy_ept);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 5/9] rpmsg: glink: Add support for rpmsg glink chrdev

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

RPMSG provides a char device interface to userspace. Probe the rpmsg
chrdev channel to enable the rpmsg_ctrl device creation on glink
transports.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 40 ++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index f43341d..9f3d026 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1158,7 +1158,7 @@ static int qcom_glink_announce_create(struct rpmsg_device 
*rpdev)
__be32 *val = defaults;
int size;
 
-   if (glink->intentless)
+   if (glink->intentless || !completion_done(>open_ack))
return 0;
 
prop = of_find_property(np, "qcom,intents", NULL);
@@ -1544,6 +1544,40 @@ static void qcom_glink_work(struct work_struct *work)
}
 }
 
+static void qcom_glink_device_release(struct device *dev)
+{
+   struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+   struct glink_channel *channel = to_glink_channel(rpdev->ept);
+
+   /* Release qcom_glink_alloc_channel() reference */
+   kref_put(>refcount, qcom_glink_channel_release);
+   kfree(rpdev);
+}
+
+static int qcom_glink_create_chrdev(struct qcom_glink *glink)
+{
+   struct rpmsg_device *rpdev;
+   struct glink_channel *channel;
+
+   rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
+   if (!rpdev)
+   return -ENOMEM;
+
+   channel = qcom_glink_alloc_channel(glink, "rpmsg_chrdev");
+   if (IS_ERR(channel)) {
+   kfree(rpdev);
+   return PTR_ERR(channel);
+   }
+   channel->rpdev = rpdev;
+
+   rpdev->ept = >ept;
+   rpdev->ops = _device_ops;
+   rpdev->dev.parent = glink->dev;
+   rpdev->dev.release = qcom_glink_device_release;
+
+   return rpmsg_chrdev_register_device(rpdev);
+}
+
 struct qcom_glink *qcom_glink_native_probe(struct device *dev,
   unsigned long features,
   struct qcom_glink_pipe *rx,
@@ -1603,6 +1637,10 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
if (ret)
return ERR_PTR(ret);
 
+   ret = qcom_glink_create_chrdev(glink);
+   if (ret)
+   dev_err(glink->dev, "failed to register chrdev\n");
+
return glink;
 }
 EXPORT_SYMBOL_GPL(qcom_glink_native_probe);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 1/9] dt-bindings: soc: qcom: Add label for GLINK bindings

2018-07-27 Thread Arun Kumar Neelakantam
From: Chris Lew 

There are GLINK clients who open the same channel on multiple GLINK
links. These clients need a way to distinguish which remoteproc they
are communicating to. Add a label property to identify the edge this
node represents.

Signed-off-by: Chris Lew 
Signed-off-by: Arun Kumar Neelakantam 
---
 Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt | 5 +
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt 
b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
index 9663cab..0b8cc53 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
@@ -10,6 +10,11 @@ edge.
Value type: 
Definition: must be "qcom,glink-rpm"
 
+- label:
+   Usage: optional
+   Value type: 
+   Definition: should specify the subsystem name this edge corresponds to.
+
 - interrupts:
Usage: required
Value type: 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V4 0/9] Add chrdev and name query support for GLINK

2018-07-27 Thread Arun Kumar Neelakantam
Add support for the GLINK rpmsg transport to register a rpmsg chrdev.
This will create the rpmsg_ctrl nodes for userspace clients to open 
rpmsg epts. Create a label property that will help userspace clients
distinguish between the different GLINK links. The rpmsg chrdev 
allocation is done by allocating a local channel which also allocates
an ept. We need to add some guards against edge cases for this chrdev
because it will never fully open.

Changes since v3:
- Change to device_add_group for rpmsg name attr
- Add patch to unregister the rpmsg device
- Add patch to support compat ioctl for rpmsg char driver

Changes since v2:
- Revert change to make glink attribute table const

Changes since v1:
- Add explanation to dt-bindings commit message
- Add patch complete_all the open_req/ack variables
- Add patch to prevent null pointer dereference in chrdev channel release
- Change chrdev allocation to use glink channel allocation
- Change glink attr struct to const

Arun Kumar Neelakantam (2):
  rpmsg: glink: unregister rpmsg device during endpoint destroy
  rpmsg: Add compat ioctl for rpmsg char driver

Chris Lew (7):
  dt-bindings: soc: qcom: Add label for GLINK bindings
  rpmsg: glink: Store edge name for glink device
  rpmsg: glink: Use complete_all for open states
  rpmsg: Guard against null endpoint ops in destroy
  rpmsg: glink: Add support for rpmsg glink chrdev
  rpmsg: glink: Expose rpmsg name attr for glink
  rpmsg: glink: Remove chunk size word align warning

 .../devicetree/bindings/soc/qcom/qcom,glink.txt|  5 ++
 drivers/rpmsg/qcom_glink_native.c  | 88 --
 drivers/rpmsg/rpmsg_char.c |  2 +
 drivers/rpmsg/rpmsg_core.c |  2 +-
 4 files changed, 90 insertions(+), 7 deletions(-)

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



[PATCH V4 0/9] Add chrdev and name query support for GLINK

2018-07-27 Thread Arun Kumar Neelakantam
Add support for the GLINK rpmsg transport to register a rpmsg chrdev.
This will create the rpmsg_ctrl nodes for userspace clients to open 
rpmsg epts. Create a label property that will help userspace clients
distinguish between the different GLINK links. The rpmsg chrdev 
allocation is done by allocating a local channel which also allocates
an ept. We need to add some guards against edge cases for this chrdev
because it will never fully open.

Changes since v3:
- Change to device_add_group for rpmsg name attr
- Add patch to unregister the rpmsg device
- Add patch to support compat ioctl for rpmsg char driver

Changes since v2:
- Revert change to make glink attribute table const

Changes since v1:
- Add explanation to dt-bindings commit message
- Add patch complete_all the open_req/ack variables
- Add patch to prevent null pointer dereference in chrdev channel release
- Change chrdev allocation to use glink channel allocation
- Change glink attr struct to const

Arun Kumar Neelakantam (2):
  rpmsg: glink: unregister rpmsg device during endpoint destroy
  rpmsg: Add compat ioctl for rpmsg char driver

Chris Lew (7):
  dt-bindings: soc: qcom: Add label for GLINK bindings
  rpmsg: glink: Store edge name for glink device
  rpmsg: glink: Use complete_all for open states
  rpmsg: Guard against null endpoint ops in destroy
  rpmsg: glink: Add support for rpmsg glink chrdev
  rpmsg: glink: Expose rpmsg name attr for glink
  rpmsg: glink: Remove chunk size word align warning

 .../devicetree/bindings/soc/qcom/qcom,glink.txt|  5 ++
 drivers/rpmsg/qcom_glink_native.c  | 88 --
 drivers/rpmsg/rpmsg_char.c |  2 +
 drivers/rpmsg/rpmsg_core.c |  2 +-
 4 files changed, 90 insertions(+), 7 deletions(-)

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



Re: [PATCH] soc: qcom: smp2p: Access APCS as mailbox client

2017-11-16 Thread Arun Kumar Neelakantam



On 11/16/2017 12:48 PM, Bjorn Andersson wrote:

Attempt to acquire the APCS IPC through the mailbox framework and fall
back to the old syscon based approach, to allow us to move away from
using the syscon.

Signed-off-by: Bjorn Andersson 
---
  drivers/soc/qcom/Kconfig |  1 +
  drivers/soc/qcom/smp2p.c | 38 --
  2 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index b00bccddcd3b..e67d9534fca0 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -64,6 +64,7 @@ config QCOM_SMEM_STATE
  
  config QCOM_SMP2P

tristate "Qualcomm Shared Memory Point to Point support"
+   depends on MAILBOX
depends on QCOM_SMEM
select QCOM_SMEM_STATE
help
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index f51fb2ea7200..7fdbb64142a0 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -18,6 +18,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -126,6 +127,8 @@ struct smp2p_entry {
   * @ipc_regmap:   regmap for the outbound ipc
   * @ipc_offset:   offset within the regmap
   * @ipc_bit:  bit in regmap@offset to kick to signal remote processor
+ * @mbox_client: mailbox client handle
+ * @mbox_chan: apcs ipc mailbox channel handle
   * @inbound:  list of inbound entries
   * @outbound: list of outbound entries
   */
@@ -146,6 +149,9 @@ struct qcom_smp2p {
int ipc_offset;
int ipc_bit;
  
+	struct mbox_client mbox_client;

+   struct mbox_chan *mbox_chan;
+
struct list_head inbound;
struct list_head outbound;
  };
@@ -154,7 +160,13 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
  {
/* Make sure any updated data is written before the kick */
wmb();
-   regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, BIT(smp2p->ipc_bit));
+
+   if (smp2p->mbox_chan) {
+   mbox_send_message(smp2p->mbox_chan, NULL);
+   mbox_client_txdone(smp2p->mbox_chan, 0);
+   } else {
+   regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, 
BIT(smp2p->ipc_bit));
+   }
  }
  
  /**

@@ -453,10 +465,6 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
  
  	platform_set_drvdata(pdev, smp2p);
  
-	ret = smp2p_parse_ipc(smp2p);

-   if (ret)
-   return ret;
-
key = "qcom,smem";
ret = of_property_read_u32_array(pdev->dev.of_node, key,
 smp2p->smem_items, 2);
@@ -483,9 +491,22 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
return irq;
}
  
+	smp2p->mbox_client.dev = >dev;

+   smp2p->mbox_chan = mbox_request_channel(>mbox_client, 0);
any reason why we are not using "knows_txdone = true" for SMP2P but 
using for only SMD drivers

+   if (IS_ERR(smp2p->mbox_chan)) {
+   if (PTR_ERR(smp2p->mbox_chan) != -ENODEV)
+   return PTR_ERR(smp2p->mbox_chan);
+
+   smp2p->mbox_chan = NULL;
+
+   ret = smp2p_parse_ipc(smp2p);
+   if (ret)
+   return ret;
+   }
+
ret = qcom_smp2p_alloc_outbound_item(smp2p);
if (ret < 0)
-   return ret;
+   goto release_mbox;
  
  	for_each_available_child_of_node(pdev->dev.of_node, node) {

entry = devm_kzalloc(>dev, sizeof(*entry), GFP_KERNEL);
@@ -540,6 +561,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
  
  	smp2p->out->valid_entries = 0;
  
+release_mbox:

+   mbox_free_channel(smp2p->mbox_chan);
+
return ret;
  }
  
@@ -554,6 +578,8 @@ static int qcom_smp2p_remove(struct platform_device *pdev)

list_for_each_entry(entry, >outbound, node)
qcom_smem_state_unregister(entry->state);
  
+	mbox_free_channel(smp2p->mbox_chan);

+
smp2p->out->valid_entries = 0;
  
  	return 0;




Re: [PATCH] soc: qcom: smp2p: Access APCS as mailbox client

2017-11-16 Thread Arun Kumar Neelakantam



On 11/16/2017 12:48 PM, Bjorn Andersson wrote:

Attempt to acquire the APCS IPC through the mailbox framework and fall
back to the old syscon based approach, to allow us to move away from
using the syscon.

Signed-off-by: Bjorn Andersson 
---
  drivers/soc/qcom/Kconfig |  1 +
  drivers/soc/qcom/smp2p.c | 38 --
  2 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index b00bccddcd3b..e67d9534fca0 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -64,6 +64,7 @@ config QCOM_SMEM_STATE
  
  config QCOM_SMP2P

tristate "Qualcomm Shared Memory Point to Point support"
+   depends on MAILBOX
depends on QCOM_SMEM
select QCOM_SMEM_STATE
help
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index f51fb2ea7200..7fdbb64142a0 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -18,6 +18,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -126,6 +127,8 @@ struct smp2p_entry {
   * @ipc_regmap:   regmap for the outbound ipc
   * @ipc_offset:   offset within the regmap
   * @ipc_bit:  bit in regmap@offset to kick to signal remote processor
+ * @mbox_client: mailbox client handle
+ * @mbox_chan: apcs ipc mailbox channel handle
   * @inbound:  list of inbound entries
   * @outbound: list of outbound entries
   */
@@ -146,6 +149,9 @@ struct qcom_smp2p {
int ipc_offset;
int ipc_bit;
  
+	struct mbox_client mbox_client;

+   struct mbox_chan *mbox_chan;
+
struct list_head inbound;
struct list_head outbound;
  };
@@ -154,7 +160,13 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
  {
/* Make sure any updated data is written before the kick */
wmb();
-   regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, BIT(smp2p->ipc_bit));
+
+   if (smp2p->mbox_chan) {
+   mbox_send_message(smp2p->mbox_chan, NULL);
+   mbox_client_txdone(smp2p->mbox_chan, 0);
+   } else {
+   regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, 
BIT(smp2p->ipc_bit));
+   }
  }
  
  /**

@@ -453,10 +465,6 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
  
  	platform_set_drvdata(pdev, smp2p);
  
-	ret = smp2p_parse_ipc(smp2p);

-   if (ret)
-   return ret;
-
key = "qcom,smem";
ret = of_property_read_u32_array(pdev->dev.of_node, key,
 smp2p->smem_items, 2);
@@ -483,9 +491,22 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
return irq;
}
  
+	smp2p->mbox_client.dev = >dev;

+   smp2p->mbox_chan = mbox_request_channel(>mbox_client, 0);
any reason why we are not using "knows_txdone = true" for SMP2P but 
using for only SMD drivers

+   if (IS_ERR(smp2p->mbox_chan)) {
+   if (PTR_ERR(smp2p->mbox_chan) != -ENODEV)
+   return PTR_ERR(smp2p->mbox_chan);
+
+   smp2p->mbox_chan = NULL;
+
+   ret = smp2p_parse_ipc(smp2p);
+   if (ret)
+   return ret;
+   }
+
ret = qcom_smp2p_alloc_outbound_item(smp2p);
if (ret < 0)
-   return ret;
+   goto release_mbox;
  
  	for_each_available_child_of_node(pdev->dev.of_node, node) {

entry = devm_kzalloc(>dev, sizeof(*entry), GFP_KERNEL);
@@ -540,6 +561,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
  
  	smp2p->out->valid_entries = 0;
  
+release_mbox:

+   mbox_free_channel(smp2p->mbox_chan);
+
return ret;
  }
  
@@ -554,6 +578,8 @@ static int qcom_smp2p_remove(struct platform_device *pdev)

list_for_each_entry(entry, >outbound, node)
qcom_smem_state_unregister(entry->state);
  
+	mbox_free_channel(smp2p->mbox_chan);

+
smp2p->out->valid_entries = 0;
  
  	return 0;




Re: [PATCH] rpmsg: qcom_smd: Access APCS through mailbox framework

2017-11-16 Thread Arun Kumar Neelakantam



On 11/16/2017 12:38 PM, Bjorn Andersson wrote:

Attempt to acquire the APCS IPC through the mailbox framework and fall
back to the old syscon based approach, to allow us to move away from
using the syscon.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>


Reviewed-by: Arun Kumar Neelakantam <ane...@codeaurora.org>


---
  drivers/rpmsg/qcom_smd.c | 62 +---
  1 file changed, 43 insertions(+), 19 deletions(-)

diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index b01774e9fac0..ef2a526ebc8f 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -14,6 +14,7 @@
  
  #include 

  #include 
+#include 
  #include 
  #include 
  #include 
@@ -107,6 +108,8 @@ static const struct {
   * @ipc_regmap:   regmap handle holding the outgoing ipc register
   * @ipc_offset:   offset within @ipc_regmap of the register for 
ipc
   * @ipc_bit:  bit in the register at @ipc_offset of @ipc_regmap
+ * @mbox_client:   mailbox client handle
+ * @mbox_chan: apcs ipc mailbox channel handle
   * @channels: list of all channels detected on this edge
   * @channels_lock:guard for modifications of @channels
   * @allocated:array of bitmaps representing already allocated 
channels
@@ -129,6 +132,9 @@ struct qcom_smd_edge {
int ipc_offset;
int ipc_bit;
  
+	struct mbox_client mbox_client;

+   struct mbox_chan *mbox_chan;
+
struct list_head channels;
spinlock_t channels_lock;
  
@@ -365,7 +371,12 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)

  {
struct qcom_smd_edge *edge = channel->edge;
  
-	regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit));

+   if (edge->mbox_chan) {
+   mbox_send_message(edge->mbox_chan, NULL);
+   mbox_client_txdone(edge->mbox_chan, 0);
+   } else {
+   regmap_write(edge->ipc_regmap, edge->ipc_offset, 
BIT(edge->ipc_bit));
+   }
  }
  
  /*

@@ -1268,27 +1279,37 @@ static int qcom_smd_parse_edge(struct device *dev,
key = "qcom,remote-pid";
of_property_read_u32(node, key, >remote_pid);
  
-	syscon_np = of_parse_phandle(node, "qcom,ipc", 0);

-   if (!syscon_np) {
-   dev_err(dev, "no qcom,ipc node\n");
-   return -ENODEV;
-   }
+   edge->mbox_client.dev = dev;
+   edge->mbox_client.knows_txdone = true;
+   edge->mbox_chan = mbox_request_channel(>mbox_client, 0);
+   if (IS_ERR(edge->mbox_chan)) {
+   if (PTR_ERR(edge->mbox_chan) != -ENODEV)
+   return PTR_ERR(edge->mbox_chan);
  
-	edge->ipc_regmap = syscon_node_to_regmap(syscon_np);

-   if (IS_ERR(edge->ipc_regmap))
-   return PTR_ERR(edge->ipc_regmap);
+   edge->mbox_chan = NULL;
  
-	key = "qcom,ipc";

-   ret = of_property_read_u32_index(node, key, 1, >ipc_offset);
-   if (ret < 0) {
-   dev_err(dev, "no offset in %s\n", key);
-   return -EINVAL;
-   }
+   syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
+   if (!syscon_np) {
+   dev_err(dev, "no qcom,ipc node\n");
+   return -ENODEV;
+   }
  
-	ret = of_property_read_u32_index(node, key, 2, >ipc_bit);

-   if (ret < 0) {
-   dev_err(dev, "no bit in %s\n", key);
-   return -EINVAL;
+   edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
+   if (IS_ERR(edge->ipc_regmap))
+   return PTR_ERR(edge->ipc_regmap);
+
+   key = "qcom,ipc";
+   ret = of_property_read_u32_index(node, key, 1, 
>ipc_offset);
+   if (ret < 0) {
+   dev_err(dev, "no offset in %s\n", key);
+   return -EINVAL;
+   }
+
+   ret = of_property_read_u32_index(node, key, 2, >ipc_bit);
+   if (ret < 0) {
+   dev_err(dev, "no bit in %s\n", key);
+   return -EINVAL;
+   }
}
  
  	ret = of_property_read_string(node, "label", >name);

@@ -1394,6 +1415,8 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct 
device *parent,
return edge;
  
  unregister_dev:

+   if (!IS_ERR_OR_NULL(edge->mbox_chan))
+   mbox_free_channel(edge->mbox_chan);
put_device(>dev);
return ERR_PTR(ret);
  }
@@ -1422,6 +1445,7 @@ int qcom_smd_unregister_edge(struct qcom_smd_edge *edge)
if (ret)
dev_warn(>dev, "can't remove smd device: %d\n", ret);
  
+	mbox_free_channel(edge->mbox_chan);

device_unregister(>dev);
  
  	return 0;




Re: [PATCH] rpmsg: qcom_smd: Access APCS through mailbox framework

2017-11-16 Thread Arun Kumar Neelakantam



On 11/16/2017 12:38 PM, Bjorn Andersson wrote:

Attempt to acquire the APCS IPC through the mailbox framework and fall
back to the old syscon based approach, to allow us to move away from
using the syscon.

Signed-off-by: Bjorn Andersson 


Reviewed-by: Arun Kumar Neelakantam 


---
  drivers/rpmsg/qcom_smd.c | 62 +---
  1 file changed, 43 insertions(+), 19 deletions(-)

diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index b01774e9fac0..ef2a526ebc8f 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -14,6 +14,7 @@
  
  #include 

  #include 
+#include 
  #include 
  #include 
  #include 
@@ -107,6 +108,8 @@ static const struct {
   * @ipc_regmap:   regmap handle holding the outgoing ipc register
   * @ipc_offset:   offset within @ipc_regmap of the register for 
ipc
   * @ipc_bit:  bit in the register at @ipc_offset of @ipc_regmap
+ * @mbox_client:   mailbox client handle
+ * @mbox_chan: apcs ipc mailbox channel handle
   * @channels: list of all channels detected on this edge
   * @channels_lock:guard for modifications of @channels
   * @allocated:array of bitmaps representing already allocated 
channels
@@ -129,6 +132,9 @@ struct qcom_smd_edge {
int ipc_offset;
int ipc_bit;
  
+	struct mbox_client mbox_client;

+   struct mbox_chan *mbox_chan;
+
struct list_head channels;
spinlock_t channels_lock;
  
@@ -365,7 +371,12 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)

  {
struct qcom_smd_edge *edge = channel->edge;
  
-	regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit));

+   if (edge->mbox_chan) {
+   mbox_send_message(edge->mbox_chan, NULL);
+   mbox_client_txdone(edge->mbox_chan, 0);
+   } else {
+   regmap_write(edge->ipc_regmap, edge->ipc_offset, 
BIT(edge->ipc_bit));
+   }
  }
  
  /*

@@ -1268,27 +1279,37 @@ static int qcom_smd_parse_edge(struct device *dev,
key = "qcom,remote-pid";
of_property_read_u32(node, key, >remote_pid);
  
-	syscon_np = of_parse_phandle(node, "qcom,ipc", 0);

-   if (!syscon_np) {
-   dev_err(dev, "no qcom,ipc node\n");
-   return -ENODEV;
-   }
+   edge->mbox_client.dev = dev;
+   edge->mbox_client.knows_txdone = true;
+   edge->mbox_chan = mbox_request_channel(>mbox_client, 0);
+   if (IS_ERR(edge->mbox_chan)) {
+   if (PTR_ERR(edge->mbox_chan) != -ENODEV)
+   return PTR_ERR(edge->mbox_chan);
  
-	edge->ipc_regmap = syscon_node_to_regmap(syscon_np);

-   if (IS_ERR(edge->ipc_regmap))
-   return PTR_ERR(edge->ipc_regmap);
+   edge->mbox_chan = NULL;
  
-	key = "qcom,ipc";

-   ret = of_property_read_u32_index(node, key, 1, >ipc_offset);
-   if (ret < 0) {
-   dev_err(dev, "no offset in %s\n", key);
-   return -EINVAL;
-   }
+   syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
+   if (!syscon_np) {
+   dev_err(dev, "no qcom,ipc node\n");
+   return -ENODEV;
+   }
  
-	ret = of_property_read_u32_index(node, key, 2, >ipc_bit);

-   if (ret < 0) {
-   dev_err(dev, "no bit in %s\n", key);
-   return -EINVAL;
+   edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
+   if (IS_ERR(edge->ipc_regmap))
+   return PTR_ERR(edge->ipc_regmap);
+
+   key = "qcom,ipc";
+   ret = of_property_read_u32_index(node, key, 1, 
>ipc_offset);
+   if (ret < 0) {
+   dev_err(dev, "no offset in %s\n", key);
+   return -EINVAL;
+   }
+
+   ret = of_property_read_u32_index(node, key, 2, >ipc_bit);
+   if (ret < 0) {
+   dev_err(dev, "no bit in %s\n", key);
+   return -EINVAL;
+   }
}
  
  	ret = of_property_read_string(node, "label", >name);

@@ -1394,6 +1415,8 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct 
device *parent,
return edge;
  
  unregister_dev:

+   if (!IS_ERR_OR_NULL(edge->mbox_chan))
+   mbox_free_channel(edge->mbox_chan);
put_device(>dev);
return ERR_PTR(ret);
  }
@@ -1422,6 +1445,7 @@ int qcom_smd_unregister_edge(struct qcom_smd_edge *edge)
if (ret)
dev_warn(>dev, "can't remove smd device: %d\n", ret);
  
+	mbox_free_channel(edge->mbox_chan);

device_unregister(>dev);
  
  	return 0;




Re: [PATCH v2 2/5] soc: qcom: Introduce QMI helpers

2017-11-07 Thread Arun Kumar Neelakantam



On 11/7/2017 10:50 AM, Bjorn Andersson wrote:

Drivers that needs to communicate with a remote QMI service all has to
perform the operations of discovering the service, encoding and decoding
the messages and operate the socket. This introduces an abstraction for
these common operations, reducing most of the duplication in such cases.

Signed-off-by: Bjorn Andersson 
---

Changes since v1:
- Squashed notion of qmi vs qrtr in interface, to simplify client code
- Lookup and service registration is cached and handled by core on ENETRESET
- Introduce callbacks for BYE and DEL_CLIENT control messages
- Revisited locking for socket and transaction objects, squashed a few races
   and made it possible to send "indication" messages from message handlers.
- kerneldoc updates
- Moved handling of net_reset from clients to this code, greatly simplifies
   typical drivers and reduces duplication
- Pass transaction id of QMI message to handlers even though it's not a
   response, allows sending a response with the txn id of an incoming request.
- Split qmi_send_message() in three, instead of passing type as parameter - to
   clean up handling of "indication" messages.

  drivers/soc/qcom/Kconfig |   1 +
  drivers/soc/qcom/Makefile|   1 +
  drivers/soc/qcom/qmi_interface.c | 849 +++
  include/linux/soc/qcom/qmi.h | 157 
  4 files changed, 1008 insertions(+)
  create mode 100644 drivers/soc/qcom/qmi_interface.c

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 91b70b170a82..9718f1c41e3d 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -37,6 +37,7 @@ config QCOM_PM
  
  config QCOM_QMI_HELPERS

tristate
+   depends on ARCH_QCOM

I feel It should depend on QRTR instead of ARCH_QCOM

help
  Helper library for handling QMI encoded messages.  QMI encoded
  messages are used in communication between the majority of QRTR
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 625750acfeef..b04b5044775f 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_QCOM_MDT_LOADER)   += mdt_loader.o
  obj-$(CONFIG_QCOM_PM) +=  spm.o
  obj-$(CONFIG_QCOM_QMI_HELPERS)+= qmi_helpers.o
  qmi_helpers-y += qmi_encdec.o
+qmi_helpers-y  += qmi_interface.o
  obj-$(CONFIG_QCOM_SMD_RPM)+= smd-rpm.o
  obj-$(CONFIG_QCOM_SMEM) +=smem.o
  obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
new file mode 100644
index ..d7885f9b072b
--- /dev/null
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -0,0 +1,849 @@
+/*
+ * Copyright (C) 2017 Linaro Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static struct socket *qmi_sock_create(struct qmi_handle *qmi,
+ struct sockaddr_qrtr *sq);
+
+/**
+ * qmi_recv_new_server() - handler of NEW_SERVER control message
+ * @qmi:   qmi handle
+ * @node:  node of the new server
+ * @port:  port of the new server
+ *
+ * Calls the new_server callback to inform the client about a newly registered
+ * server matching the currently registered service lookup.
+ */
+static void qmi_recv_new_server(struct qmi_handle *qmi,
+  unsigned int service, unsigned int instance,
+  unsigned int node, unsigned int port)
+{
+   struct qmi_ops *ops = >ops;
+   struct qmi_service *svc;
+   int ret;
+
+   if (!ops->new_server)
+   return;
+
+   /* Ignore EOF marker */
+   if (!node && !port)
+   return;
+
+   svc = kzalloc(sizeof(*svc), GFP_KERNEL);
+   if (!svc)
+   return;
+
+   svc->service = service;
+   svc->version = instance & 0xff;
+   svc->instance = instance >> 8;
+   svc->node = node;
+   svc->port = port;
+
+   ret = ops->new_server(qmi, svc);
+   if (ret < 0)
+   kfree(svc);
+   else
+   list_add(>list_node, >lookup_results);
+}
+
+/**
+ * qmi_recv_del_server() - handler of DEL_SERVER control message
+ * @qmi:   qmi handle
+ * @node:  node of the dying server, a value of -1 matches all nodes
+ * @port:  port of the dying server, a value of -1 matches all ports
+ *
+ * Calls the del_server callback for 

Re: [PATCH v2 2/5] soc: qcom: Introduce QMI helpers

2017-11-07 Thread Arun Kumar Neelakantam



On 11/7/2017 10:50 AM, Bjorn Andersson wrote:

Drivers that needs to communicate with a remote QMI service all has to
perform the operations of discovering the service, encoding and decoding
the messages and operate the socket. This introduces an abstraction for
these common operations, reducing most of the duplication in such cases.

Signed-off-by: Bjorn Andersson 
---

Changes since v1:
- Squashed notion of qmi vs qrtr in interface, to simplify client code
- Lookup and service registration is cached and handled by core on ENETRESET
- Introduce callbacks for BYE and DEL_CLIENT control messages
- Revisited locking for socket and transaction objects, squashed a few races
   and made it possible to send "indication" messages from message handlers.
- kerneldoc updates
- Moved handling of net_reset from clients to this code, greatly simplifies
   typical drivers and reduces duplication
- Pass transaction id of QMI message to handlers even though it's not a
   response, allows sending a response with the txn id of an incoming request.
- Split qmi_send_message() in three, instead of passing type as parameter - to
   clean up handling of "indication" messages.

  drivers/soc/qcom/Kconfig |   1 +
  drivers/soc/qcom/Makefile|   1 +
  drivers/soc/qcom/qmi_interface.c | 849 +++
  include/linux/soc/qcom/qmi.h | 157 
  4 files changed, 1008 insertions(+)
  create mode 100644 drivers/soc/qcom/qmi_interface.c

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 91b70b170a82..9718f1c41e3d 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -37,6 +37,7 @@ config QCOM_PM
  
  config QCOM_QMI_HELPERS

tristate
+   depends on ARCH_QCOM

I feel It should depend on QRTR instead of ARCH_QCOM

help
  Helper library for handling QMI encoded messages.  QMI encoded
  messages are used in communication between the majority of QRTR
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 625750acfeef..b04b5044775f 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_QCOM_MDT_LOADER)   += mdt_loader.o
  obj-$(CONFIG_QCOM_PM) +=  spm.o
  obj-$(CONFIG_QCOM_QMI_HELPERS)+= qmi_helpers.o
  qmi_helpers-y += qmi_encdec.o
+qmi_helpers-y  += qmi_interface.o
  obj-$(CONFIG_QCOM_SMD_RPM)+= smd-rpm.o
  obj-$(CONFIG_QCOM_SMEM) +=smem.o
  obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
new file mode 100644
index ..d7885f9b072b
--- /dev/null
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -0,0 +1,849 @@
+/*
+ * Copyright (C) 2017 Linaro Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static struct socket *qmi_sock_create(struct qmi_handle *qmi,
+ struct sockaddr_qrtr *sq);
+
+/**
+ * qmi_recv_new_server() - handler of NEW_SERVER control message
+ * @qmi:   qmi handle
+ * @node:  node of the new server
+ * @port:  port of the new server
+ *
+ * Calls the new_server callback to inform the client about a newly registered
+ * server matching the currently registered service lookup.
+ */
+static void qmi_recv_new_server(struct qmi_handle *qmi,
+  unsigned int service, unsigned int instance,
+  unsigned int node, unsigned int port)
+{
+   struct qmi_ops *ops = >ops;
+   struct qmi_service *svc;
+   int ret;
+
+   if (!ops->new_server)
+   return;
+
+   /* Ignore EOF marker */
+   if (!node && !port)
+   return;
+
+   svc = kzalloc(sizeof(*svc), GFP_KERNEL);
+   if (!svc)
+   return;
+
+   svc->service = service;
+   svc->version = instance & 0xff;
+   svc->instance = instance >> 8;
+   svc->node = node;
+   svc->port = port;
+
+   ret = ops->new_server(qmi, svc);
+   if (ret < 0)
+   kfree(svc);
+   else
+   list_add(>list_node, >lookup_results);
+}
+
+/**
+ * qmi_recv_del_server() - handler of DEL_SERVER control message
+ * @qmi:   qmi handle
+ * @node:  node of the dying server, a value of -1 matches all nodes
+ * @port:  port of the dying server, a value of -1 matches all ports
+ *
+ * Calls the del_server callback for each previously seen server, 

[PATCH V1] rpmsg: glink: Initialize the "intent_req_comp" completion variable

2017-10-29 Thread Arun Kumar Neelakantam
The "intent_req_comp" variable is used without initialization which
results in NULL pointer dereference in qcom_glink_request_intent().

we need to initialize the completion variable before using it.

Fixes: 27b9c5b66b23 ("rpmsg: glink: Request for intents when unavailable")
Signed-off-by: Arun Kumar Neelakantam <ane...@codeaurora.org>
---
 drivers/rpmsg/qcom_glink_native.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 5dcc9bf..fcd46ab 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -227,6 +227,7 @@ static struct glink_channel 
*qcom_glink_alloc_channel(struct qcom_glink *glink,
 
init_completion(>open_req);
init_completion(>open_ack);
+   init_completion(>intent_req_comp);
 
INIT_LIST_HEAD(>done_intents);
INIT_WORK(>intent_work, qcom_glink_rx_done_work);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1] rpmsg: glink: Initialize the "intent_req_comp" completion variable

2017-10-29 Thread Arun Kumar Neelakantam
The "intent_req_comp" variable is used without initialization which
results in NULL pointer dereference in qcom_glink_request_intent().

we need to initialize the completion variable before using it.

Fixes: 27b9c5b66b23 ("rpmsg: glink: Request for intents when unavailable")
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 5dcc9bf..fcd46ab 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -227,6 +227,7 @@ static struct glink_channel 
*qcom_glink_alloc_channel(struct qcom_glink *glink,
 
init_completion(>open_req);
init_completion(>open_ack);
+   init_completion(>intent_req_comp);
 
INIT_LIST_HEAD(>done_intents);
INIT_WORK(>intent_work, qcom_glink_rx_done_work);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] rpmsg: glink: Initialize the "intent_req_comp" completion variable

2017-10-27 Thread Arun Kumar Neelakantam
The "intent_req_comp" variable is used without initialization which
results in NULL pointer derefernce in qcom_glink_request_intent().

we need to initialize the completion variable before using it.

Fixes: 27b9c5b66b23 ("rpmsg: glink: Request for intents when unavailable")
Signed-off-by: Arun Kumar Neelakantam <ane...@codeaurora.org>
---
 drivers/rpmsg/qcom_glink_native.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 5dcc9bf..fcd46ab 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -227,6 +227,7 @@ static struct glink_channel 
*qcom_glink_alloc_channel(struct qcom_glink *glink,
 
init_completion(>open_req);
init_completion(>open_ack);
+   init_completion(>intent_req_comp);
 
INIT_LIST_HEAD(>done_intents);
INIT_WORK(>intent_work, qcom_glink_rx_done_work);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] rpmsg: glink: Initialize the "intent_req_comp" completion variable

2017-10-27 Thread Arun Kumar Neelakantam
The "intent_req_comp" variable is used without initialization which
results in NULL pointer derefernce in qcom_glink_request_intent().

we need to initialize the completion variable before using it.

Fixes: 27b9c5b66b23 ("rpmsg: glink: Request for intents when unavailable")
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 5dcc9bf..fcd46ab 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -227,6 +227,7 @@ static struct glink_channel 
*qcom_glink_alloc_channel(struct qcom_glink *glink,
 
init_completion(>open_req);
init_completion(>open_ack);
+   init_completion(>intent_req_comp);
 
INIT_LIST_HEAD(>done_intents);
INIT_WORK(>intent_work, qcom_glink_rx_done_work);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v2 17/20] rpmsg: glink: Receive and store the remote intent buffers

2017-08-28 Thread Arun Kumar Neelakantam



On 8/24/2017 12:51 PM, Sricharan R wrote:

Just like we allocating and sending intent ids to remote,
remote side allocates and sends us the intents as well.
So save the intent ids and use it later while sending
data targeting the appropriate intents based on the size.

Signed-off-by: Sricharan R <sricha...@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Acked-by: Arun Kumar Neelakantam <ane...@codeaurora.org>

Regards,
Arun N

---
  drivers/rpmsg/qcom_glink_native.c | 71 ++-
  1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 76ee86e..d93d651 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -139,8 +139,9 @@ enum {
   * @name: unique channel name/identifier
   * @lcid: channel id, in local space
   * @rcid: channel id, in remote space
- * @intent_lock: lock for protection of @liids
+ * @intent_lock: lock for protection of @liids, @riids
   * @liids:idr of all local intents
+ * @riids: idr of all remote intents
   * @intent_work: worker responsible for transmitting rx_done packets
   * @done_intents: list of intents that needs to be announced rx_done
   * @buf:  receive buffer, for gathering fragments
@@ -165,6 +166,7 @@ struct glink_channel {
  
  	spinlock_t intent_lock;

struct idr liids;
+   struct idr riids;
struct work_struct intent_work;
struct list_head done_intents;
  
@@ -222,6 +224,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,

INIT_WORK(>intent_work, qcom_glink_rx_done_work);
  
  	idr_init(>liids);

+   idr_init(>riids);
kref_init(>refcount);
  
  	return channel;

@@ -235,6 +238,7 @@ static void qcom_glink_channel_release(struct kref *ref)
  
  	spin_lock_irqsave(>intent_lock, flags);

idr_destroy(>liids);
+   idr_destroy(>riids);
spin_unlock_irqrestore(>intent_lock, flags);
  
  	kfree(channel->name);

@@ -806,6 +810,68 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return ret;
  }
  
+static void qcom_glink_handle_intent(struct qcom_glink *glink,

+unsigned int cid,
+unsigned int count,
+size_t avail)
+{
+   struct glink_core_rx_intent *intent;
+   struct glink_channel *channel;
+   struct intent_pair {
+   __le32 size;
+   __le32 iid;
+   };
+
+   struct {
+   struct glink_msg msg;
+   struct intent_pair intents[];
+   } __packed * msg;
+
+   const size_t msglen = sizeof(*msg) + sizeof(struct intent_pair) * count;
+   int ret;
+   int i;
+   unsigned long flags;
+
+   if (avail < msglen) {
+   dev_dbg(glink->dev, "Not enough data in fifo\n");
+   return;
+   }
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, cid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "intents for non-existing channel\n");
+   return;
+   }
+
+   msg = kmalloc(msglen, GFP_ATOMIC);
+   if (!msg)
+   return;
+
+   qcom_glink_rx_peak(glink, msg, 0, msglen);
+
+   for (i = 0; i < count; ++i) {
+   intent = kzalloc(sizeof(*intent), GFP_ATOMIC);
+   if (!intent)
+   break;
+
+   intent->id = le32_to_cpu(msg->intents[i].iid);
+   intent->size = le32_to_cpu(msg->intents[i].size);
+
+   spin_lock_irqsave(>intent_lock, flags);
+   ret = idr_alloc(>riids, intent,
+   intent->id, intent->id + 1, GFP_ATOMIC);
+   spin_unlock_irqrestore(>intent_lock, flags);
+
+   if (ret < 0)
+   dev_err(glink->dev, "failed to store remote intent\n");
+   }
+
+   kfree(msg);
+   qcom_glink_rx_advance(glink, ALIGN(msglen, 8));
+}
+
  static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
  {
struct glink_channel *channel;
@@ -871,6 +937,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
  
  			ret = 0;

break;
+   case RPM_CMD_INTENT:
+   qcom_glink_handle_intent(glink, param1, param2, avail);
+   break;
default:
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd);




Re: [PATCH v2 17/20] rpmsg: glink: Receive and store the remote intent buffers

2017-08-28 Thread Arun Kumar Neelakantam



On 8/24/2017 12:51 PM, Sricharan R wrote:

Just like we allocating and sending intent ids to remote,
remote side allocates and sends us the intents as well.
So save the intent ids and use it later while sending
data targeting the appropriate intents based on the size.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 

Acked-by: Arun Kumar Neelakantam 

Regards,
Arun N

---
  drivers/rpmsg/qcom_glink_native.c | 71 ++-
  1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 76ee86e..d93d651 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -139,8 +139,9 @@ enum {
   * @name: unique channel name/identifier
   * @lcid: channel id, in local space
   * @rcid: channel id, in remote space
- * @intent_lock: lock for protection of @liids
+ * @intent_lock: lock for protection of @liids, @riids
   * @liids:idr of all local intents
+ * @riids: idr of all remote intents
   * @intent_work: worker responsible for transmitting rx_done packets
   * @done_intents: list of intents that needs to be announced rx_done
   * @buf:  receive buffer, for gathering fragments
@@ -165,6 +166,7 @@ struct glink_channel {
  
  	spinlock_t intent_lock;

struct idr liids;
+   struct idr riids;
struct work_struct intent_work;
struct list_head done_intents;
  
@@ -222,6 +224,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,

INIT_WORK(>intent_work, qcom_glink_rx_done_work);
  
  	idr_init(>liids);

+   idr_init(>riids);
kref_init(>refcount);
  
  	return channel;

@@ -235,6 +238,7 @@ static void qcom_glink_channel_release(struct kref *ref)
  
  	spin_lock_irqsave(>intent_lock, flags);

idr_destroy(>liids);
+   idr_destroy(>riids);
spin_unlock_irqrestore(>intent_lock, flags);
  
  	kfree(channel->name);

@@ -806,6 +810,68 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return ret;
  }
  
+static void qcom_glink_handle_intent(struct qcom_glink *glink,

+unsigned int cid,
+unsigned int count,
+size_t avail)
+{
+   struct glink_core_rx_intent *intent;
+   struct glink_channel *channel;
+   struct intent_pair {
+   __le32 size;
+   __le32 iid;
+   };
+
+   struct {
+   struct glink_msg msg;
+   struct intent_pair intents[];
+   } __packed * msg;
+
+   const size_t msglen = sizeof(*msg) + sizeof(struct intent_pair) * count;
+   int ret;
+   int i;
+   unsigned long flags;
+
+   if (avail < msglen) {
+   dev_dbg(glink->dev, "Not enough data in fifo\n");
+   return;
+   }
+
+   spin_lock_irqsave(>idr_lock, flags);
+   channel = idr_find(>rcids, cid);
+   spin_unlock_irqrestore(>idr_lock, flags);
+   if (!channel) {
+   dev_err(glink->dev, "intents for non-existing channel\n");
+   return;
+   }
+
+   msg = kmalloc(msglen, GFP_ATOMIC);
+   if (!msg)
+   return;
+
+   qcom_glink_rx_peak(glink, msg, 0, msglen);
+
+   for (i = 0; i < count; ++i) {
+   intent = kzalloc(sizeof(*intent), GFP_ATOMIC);
+   if (!intent)
+   break;
+
+   intent->id = le32_to_cpu(msg->intents[i].iid);
+   intent->size = le32_to_cpu(msg->intents[i].size);
+
+   spin_lock_irqsave(>intent_lock, flags);
+   ret = idr_alloc(>riids, intent,
+   intent->id, intent->id + 1, GFP_ATOMIC);
+   spin_unlock_irqrestore(>intent_lock, flags);
+
+   if (ret < 0)
+   dev_err(glink->dev, "failed to store remote intent\n");
+   }
+
+   kfree(msg);
+   qcom_glink_rx_advance(glink, ALIGN(msglen, 8));
+}
+
  static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
  {
struct glink_channel *channel;
@@ -871,6 +937,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
  
  			ret = 0;

break;
+   case RPM_CMD_INTENT:
+   qcom_glink_handle_intent(glink, param1, param2, avail);
+   break;
default:
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd);




Re: [PATCH v2 11/20] rpmsg: glink: Fix idr_lock from mutex to spinlock

2017-08-28 Thread Arun Kumar Neelakantam



On 8/24/2017 12:51 PM, Sricharan R wrote:

The channel members lcids, rcids synchronised using
the idr_lock is accessed in both atomic/non-atomic
contexts. The readers are not currently synchronised.
That no correct, so add the readers as well under the
lock and use a spinlock.

Signed-off-by: Sricharan R <sricha...@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Acked-by: Arun Kumar Neelakantam <ane...@codeaurora.org>

Regards,
Arun N

---
  drivers/rpmsg/qcom_glink_native.c | 58 +++
  1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 777ac6b..588a56c 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -92,7 +92,7 @@ struct qcom_glink {
  
  	struct mutex tx_lock;
  
-	struct mutex idr_lock;

+   spinlock_t idr_lock;
struct idr lcids;
struct idr rcids;
unsigned long features;
@@ -309,14 +309,15 @@ static int qcom_glink_send_open_req(struct qcom_glink 
*glink,
int name_len = strlen(channel->name) + 1;
int req_len = ALIGN(sizeof(req.msg) + name_len, 8);
int ret;
+   unsigned long flags;
  
  	kref_get(>refcount);
  
-	mutex_lock(>idr_lock);

+   spin_lock_irqsave(>idr_lock, flags);
ret = idr_alloc_cyclic(>lcids, channel,
   RPM_GLINK_CID_MIN, RPM_GLINK_CID_MAX,
   GFP_KERNEL);
-   mutex_unlock(>idr_lock);
+   spin_unlock_irqrestore(>idr_lock, flags);
if (ret < 0)
return ret;
  
@@ -334,10 +335,10 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink,

return 0;
  
  remove_idr:

-   mutex_lock(>idr_lock);
+   spin_lock_irqsave(>idr_lock, flags);
idr_remove(>lcids, channel->lcid);
channel->lcid = 0;
-   mutex_unlock(>idr_lock);
+   spin_unlock_irqrestore(>idr_lock, flags);
  
  	return ret;

  }
@@ -463,6 +464,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
unsigned int chunk_size;
unsigned int left_size;
unsigned int rcid;
+   unsigned long flags;
  
  	if (avail < sizeof(hdr)) {

dev_dbg(glink->dev, "Not enough data in fifo\n");
@@ -482,7 +484,9 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return -EINVAL;
  
  	rcid = le16_to_cpu(hdr.msg.param1);

+   spin_lock_irqsave(>idr_lock, flags);
channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
if (!channel) {
dev_dbg(glink->dev, "Data on non-existing channel\n");
  
@@ -543,11 +547,13 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)

  {
struct glink_channel *channel;
  
+	spin_lock(>idr_lock);

channel = idr_find(>lcids, lcid);
if (!channel) {
dev_err(glink->dev, "Invalid open ack packet\n");
return -EINVAL;
}
+   spin_unlock(>idr_lock);
  
  	complete(>open_ack);
  
@@ -621,6 +627,7 @@ static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink,

  {
struct glink_channel *channel;
int ret;
+   unsigned long flags;
  
  	channel = qcom_glink_alloc_channel(glink, name);

if (IS_ERR(channel))
@@ -644,9 +651,9 @@ static struct glink_channel *qcom_glink_create_local(struct 
qcom_glink *glink,
  
  err_timeout:

/* qcom_glink_send_open_req() did register the channel in lcids*/
-   mutex_lock(>idr_lock);
+   spin_lock_irqsave(>idr_lock, flags);
idr_remove(>lcids, channel->lcid);
-   mutex_unlock(>idr_lock);
+   spin_unlock_irqrestore(>idr_lock, flags);
  
  release_channel:

/* Release qcom_glink_send_open_req() reference */
@@ -703,11 +710,14 @@ static struct rpmsg_endpoint 
*qcom_glink_create_ept(struct rpmsg_device *rpdev,
const char *name = chinfo.name;
int cid;
int ret;
+   unsigned long flags;
  
+	spin_lock_irqsave(>idr_lock, flags);

idr_for_each_entry(>rcids, channel, cid) {
if (!strcmp(channel->name, name))
break;
}
+   spin_unlock_irqrestore(>idr_lock, flags);
  
  	if (!channel) {

channel = qcom_glink_create_local(glink, name);
@@ -829,11 +839,14 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, 
unsigned int rcid,
struct device_node *node;
int lcid;
int ret;
+   unsigned long flags;
  
+	spin_lock_irqsave(>idr_lock, flags);

idr_for_each_entry(>lcids, channel, lcid) {
if (!strcmp(channel->name, name))
break;
}
+   spin_unlock_irqr

Re: [PATCH v2 11/20] rpmsg: glink: Fix idr_lock from mutex to spinlock

2017-08-28 Thread Arun Kumar Neelakantam



On 8/24/2017 12:51 PM, Sricharan R wrote:

The channel members lcids, rcids synchronised using
the idr_lock is accessed in both atomic/non-atomic
contexts. The readers are not currently synchronised.
That no correct, so add the readers as well under the
lock and use a spinlock.

Signed-off-by: Sricharan R 
Signed-off-by: Bjorn Andersson 

Acked-by: Arun Kumar Neelakantam 

Regards,
Arun N

---
  drivers/rpmsg/qcom_glink_native.c | 58 +++
  1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 777ac6b..588a56c 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -92,7 +92,7 @@ struct qcom_glink {
  
  	struct mutex tx_lock;
  
-	struct mutex idr_lock;

+   spinlock_t idr_lock;
struct idr lcids;
struct idr rcids;
unsigned long features;
@@ -309,14 +309,15 @@ static int qcom_glink_send_open_req(struct qcom_glink 
*glink,
int name_len = strlen(channel->name) + 1;
int req_len = ALIGN(sizeof(req.msg) + name_len, 8);
int ret;
+   unsigned long flags;
  
  	kref_get(>refcount);
  
-	mutex_lock(>idr_lock);

+   spin_lock_irqsave(>idr_lock, flags);
ret = idr_alloc_cyclic(>lcids, channel,
   RPM_GLINK_CID_MIN, RPM_GLINK_CID_MAX,
   GFP_KERNEL);
-   mutex_unlock(>idr_lock);
+   spin_unlock_irqrestore(>idr_lock, flags);
if (ret < 0)
return ret;
  
@@ -334,10 +335,10 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink,

return 0;
  
  remove_idr:

-   mutex_lock(>idr_lock);
+   spin_lock_irqsave(>idr_lock, flags);
idr_remove(>lcids, channel->lcid);
channel->lcid = 0;
-   mutex_unlock(>idr_lock);
+   spin_unlock_irqrestore(>idr_lock, flags);
  
  	return ret;

  }
@@ -463,6 +464,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
unsigned int chunk_size;
unsigned int left_size;
unsigned int rcid;
+   unsigned long flags;
  
  	if (avail < sizeof(hdr)) {

dev_dbg(glink->dev, "Not enough data in fifo\n");
@@ -482,7 +484,9 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, 
size_t avail)
return -EINVAL;
  
  	rcid = le16_to_cpu(hdr.msg.param1);

+   spin_lock_irqsave(>idr_lock, flags);
channel = idr_find(>rcids, rcid);
+   spin_unlock_irqrestore(>idr_lock, flags);
if (!channel) {
dev_dbg(glink->dev, "Data on non-existing channel\n");
  
@@ -543,11 +547,13 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)

  {
struct glink_channel *channel;
  
+	spin_lock(>idr_lock);

channel = idr_find(>lcids, lcid);
if (!channel) {
dev_err(glink->dev, "Invalid open ack packet\n");
return -EINVAL;
}
+   spin_unlock(>idr_lock);
  
  	complete(>open_ack);
  
@@ -621,6 +627,7 @@ static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink,

  {
struct glink_channel *channel;
int ret;
+   unsigned long flags;
  
  	channel = qcom_glink_alloc_channel(glink, name);

if (IS_ERR(channel))
@@ -644,9 +651,9 @@ static struct glink_channel *qcom_glink_create_local(struct 
qcom_glink *glink,
  
  err_timeout:

/* qcom_glink_send_open_req() did register the channel in lcids*/
-   mutex_lock(>idr_lock);
+   spin_lock_irqsave(>idr_lock, flags);
idr_remove(>lcids, channel->lcid);
-   mutex_unlock(>idr_lock);
+   spin_unlock_irqrestore(>idr_lock, flags);
  
  release_channel:

/* Release qcom_glink_send_open_req() reference */
@@ -703,11 +710,14 @@ static struct rpmsg_endpoint 
*qcom_glink_create_ept(struct rpmsg_device *rpdev,
const char *name = chinfo.name;
int cid;
int ret;
+   unsigned long flags;
  
+	spin_lock_irqsave(>idr_lock, flags);

idr_for_each_entry(>rcids, channel, cid) {
if (!strcmp(channel->name, name))
break;
}
+   spin_unlock_irqrestore(>idr_lock, flags);
  
  	if (!channel) {

channel = qcom_glink_create_local(glink, name);
@@ -829,11 +839,14 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, 
unsigned int rcid,
struct device_node *node;
int lcid;
int ret;
+   unsigned long flags;
  
+	spin_lock_irqsave(>idr_lock, flags);

idr_for_each_entry(>lcids, channel, lcid) {
if (!strcmp(channel->name, name))
break;
}
+   spin_unlock_irqrestore(>idr_lock, flags);
  
  	if (!channel) {

channel = qcom_glink_alloc

  1   2   >