Re: [PATCH V3 2/2] soc: qcom: smp2p: Introduce tracepoint support

2024-06-28 Thread Deepak Kumar Singh




On 6/27/2024 4:18 PM, Sudeepgoud Patil wrote:

This commit introduces tracepoint support for smp2p, enabling
logging of communication between local and remote processors.
These tracepoints include information about the remote subsystem
name, negotiation details, supported features, bit change
notifications, and ssr activity. These logs are useful for
debugging issues between subsystems.

Signed-off-by: Sudeepgoud Patil 

Reviewed-by: Deepak Kumar Singh 

---
  drivers/soc/qcom/Makefile  |  1 +
  drivers/soc/qcom/smp2p.c   |  9 
  drivers/soc/qcom/trace-smp2p.h | 98 ++
  3 files changed, 108 insertions(+)
  create mode 100644 drivers/soc/qcom/trace-smp2p.h

diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index ca0bece0dfff..30c1bf645501 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -23,6 +23,7 @@ qcom_rpmh-y   += rpmh.o
  obj-$(CONFIG_QCOM_SMD_RPM)+= rpm-proc.o smd-rpm.o
  obj-$(CONFIG_QCOM_SMEM) +=smem.o
  obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
+CFLAGS_smp2p.o := -I$(src)
  obj-$(CONFIG_QCOM_SMP2P)  += smp2p.o
  obj-$(CONFIG_QCOM_SMSM)   += smsm.o
  obj-$(CONFIG_QCOM_SOCINFO)+= socinfo.o
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index 696c2a8387d0..4aa61b0f11ad 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -161,6 +161,9 @@ struct qcom_smp2p {
struct list_head outbound;
  };
  
+#define CREATE_TRACE_POINTS

+#include "trace-smp2p.h"
+
  static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
  {
/* Make sure any updated data is written before the kick */
@@ -192,6 +195,7 @@ static void qcom_smp2p_do_ssr_ack(struct qcom_smp2p *smp2p)
struct smp2p_smem_item *out = smp2p->out;
u32 val;
  
+	trace_smp2p_ssr_ack(smp2p->dev);

smp2p->ssr_ack = !smp2p->ssr_ack;
  
  	val = out->flags & ~BIT(SMP2P_FLAGS_RESTART_ACK_BIT);

@@ -214,6 +218,7 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p)
smp2p->ssr_ack_enabled = true;
  
  		smp2p->negotiation_done = true;

+   trace_smp2p_negotiate(smp2p->dev, out->features);
}
  }
  
@@ -252,6 +257,8 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)

status = val ^ entry->last_value;
entry->last_value = val;
  
+		trace_smp2p_notify_in(entry, status, val);

+
/* No changes of this entry? */
if (!status)
continue;
@@ -415,6 +422,8 @@ static int smp2p_update_bits(void *data, u32 mask, u32 
value)
writel(val, entry->value);
spin_unlock_irqrestore(>lock, flags);
  
+	trace_smp2p_update_bits(entry, orig, val);

+
if (val != orig)
qcom_smp2p_kick(entry->smp2p);
  
diff --git a/drivers/soc/qcom/trace-smp2p.h b/drivers/soc/qcom/trace-smp2p.h

new file mode 100644
index ..fa985a0d7615
--- /dev/null
+++ b/drivers/soc/qcom/trace-smp2p.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM qcom_smp2p
+
+#if !defined(__QCOM_SMP2P_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __QCOM_SMP2P_TRACE_H__
+
+#include 
+#include 
+
+TRACE_EVENT(smp2p_ssr_ack,
+   TP_PROTO(const struct device *dev),
+   TP_ARGS(dev),
+   TP_STRUCT__entry(
+   __string(dev_name, dev_name(dev))
+   ),
+   TP_fast_assign(
+   __assign_str(dev_name, dev_name(dev));
+   ),
+   TP_printk("%s: SSR detected", __get_str(dev_name))
+);
+
+TRACE_EVENT(smp2p_negotiate,
+   TP_PROTO(const struct device *dev, unsigned int features),
+   TP_ARGS(dev, features),
+   TP_STRUCT__entry(
+   __string(dev_name, dev_name(dev))
+   __field(u32, out_features)
+   ),
+   TP_fast_assign(
+   __assign_str(dev_name, dev_name(dev));
+   __entry->out_features = features;
+   ),
+   TP_printk("%s: state=open out_features=%s", __get_str(dev_name),
+   __print_flags(__entry->out_features, "|",
+   {SMP2P_FEATURE_SSR_ACK, "SMP2P_FEATURE_SSR_ACK"})
+   )
+);
+
+TRACE_EVENT(smp2p_notify_in,
+   TP_PROTO(struct smp2p_entry *smp2p_entry, unsigned long status, u32 
val),
+   TP_ARGS(smp2p_entry, status, val),
+   TP_STRUCT__entry(
+   __string(dev_name, dev_name(smp2p_entry->smp2p->dev))
+   __string(client_name, smp2p_entry->name)
+   __field(unsigned long, status)
+   __field(u32, val)
+   ),
+   TP_fast_assign(
+   __assign_str(dev_name, dev_name(smp2p_entry->smp2p->dev));
+   __assign_str(client_name, smp2p_entry->n

Re: [PATCH V1] rpmsg: glink: Make glink smem interrupt wakeup capable

2024-06-13 Thread Deepak Kumar Singh




On 6/3/2024 3:07 PM, Caleb Connolly wrote:

Hi Deepak,

On 03/06/2024 09:36, Deepak Kumar Singh wrote:

There are certain usecases which require glink interrupt to be
wakeup capable. For example if handset is in sleep state and
usb charger is plugged in, dsp wakes up and sends glink interrupt
to host for glink pmic channel communication. Glink is suppose to
wakeup host processor completely for further glink data handling.
IRQF_NO_SUSPEND does not gurantee complete wakeup, system may again
enter sleep after interrupt handling and glink data may not be
handled by pmic client driver.

To ensure data handling by client configure glink smem device as
wakeup source and attach glink interrupt as wakeup irq. Remove
IRQF_NO_SUSPEND flag as it is no longer required.


I'm not sure I agree with this approach, glink is used for lots of 
things -- like QRTR, where the sensor DSP and modem may also need to 
wake the system up (e.g. for "wake on pickup" on mobile, or for incoming 
calls/sms).


Configuring this to always wake up the system fully will result in a lot 
of spurious wakeups for arbitrary modem notifications (e.g. signal 
strength changes) if userspace hasn't properly configured these 
(something ModemManager currently lacks support for).


In internal testing at least we don't see such issues, may be downstream 
modem manager is configuring things properly. Also with devices having 
proper auto suspend feature this change may not be affecting power 
numbers significantly.


Additionally my understanding is by definition glink interrupt should be 
wakeup capable. May be Bjorn can comment more on this.


Thanks,
Deepak


IRQF_NO_SUSPEND is presumably necessary to keep the DSPs happy? iirc 
downstream Qualcomm kernels have historically taken this approach to 
avoid spurious wakeups.


I proposed an alternative approach some time back that would allow the 
wakeup to be configured on a per-channel basis.


https://lore.kernel.org/linux-arm-msm/20230117142414.983946-1-caleb.conno...@linaro.org/

Back then Bjorn proposed using some socket specific mechanism to handle 
this for QRTR, but given this is now a common issue for multiple glink 
channels, maybe it's something we could revisit.


Requiring the wakeup be enabled by userspace clearly doesn't make sense 
for your proposed usecase, perhaps there's a way to configure this on a 
per-channel basis in-kernel (maybe as the rpmsg API?).


Thanks and regards,


Signed-off-by: Deepak Kumar Singh 
---
  drivers/rpmsg/qcom_glink_smem.c | 8 ++--
  1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_smem.c 
b/drivers/rpmsg/qcom_glink_smem.c

index 7a982c60a8dd..f1b553efab13 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -22,6 +22,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
@@ -306,8 +307,7 @@ struct qcom_glink_smem 
*qcom_glink_smem_register(struct device *parent,

  smem->irq = of_irq_get(smem->dev.of_node, 0);
  ret = devm_request_irq(>dev, smem->irq, qcom_glink_smem_intr,
-   IRQF_NO_SUSPEND | IRQF_NO_AUTOEN,
-   "glink-smem", smem);
+   IRQF_NO_AUTOEN, "glink-smem", smem);
  if (ret) {
  dev_err(>dev, "failed to request IRQ\n");
  goto err_put_dev;
@@ -346,6 +346,8 @@ struct qcom_glink_smem 
*qcom_glink_smem_register(struct device *parent,

  smem->glink = glink;
+    device_init_wakeup(dev, true);
+    dev_pm_set_wake_irq(dev, smem->irq);
  enable_irq(smem->irq);
  return smem;
@@ -365,6 +367,8 @@ void qcom_glink_smem_unregister(struct 
qcom_glink_smem *smem)

  struct qcom_glink *glink = smem->glink;
  disable_irq(smem->irq);
+    dev_pm_clear_wake_irq(>dev);
+    device_init_wakeup(>dev, false);
  qcom_glink_native_remove(glink);






Re: [PATCH V2 2/2] soc: qcom: smp2p: Introduce tracepoint support

2024-06-12 Thread Deepak Kumar Singh




On 6/12/2024 4:35 AM, Chris Lew wrote:



On 6/11/2024 5:33 AM, Sudeepgoud Patil wrote:

This commit introduces tracepoint support for smp2p,
enabling logging of communication between local and remote processors.
The tracepoints include information about the remote processor ID,
remote subsystem name, negotiation details, supported features,
bit change notifications, and ssr activity.
These tracepoints are valuable for debugging issues between subsystems.

Signed-off-by: Sudeepgoud Patil 
---

...
diff --git a/drivers/soc/qcom/trace-smp2p.h 
b/drivers/soc/qcom/trace-smp2p.h

new file mode 100644
index ..833782460b57
--- /dev/null
+++ b/drivers/soc/qcom/trace-smp2p.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights 
reserved.

+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM qcom_smp2p
+
+#if !defined(__QCOM_SMP2P_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __QCOM_SMP2P_TRACE_H__
+
+#include 
+
+#define SMP2P_FEATURE_SSR_ACK 0x1


Now that I see it, redefining the the feature flag here seems a bit out 
of place. I'm not sure if it's worth kicking off a header file for this 
single define though.


I think it is ok to have this define in smp2p.c, as that is the only 
place where it is being used.

+
+TRACE_EVENT(smp2p_ssr_ack,
+    TP_PROTO(unsigned int remote_pid, char *irq_devname),
+    TP_ARGS(remote_pid, irq_devname),
+    TP_STRUCT__entry(
+    __field(u32, remote_pid)
+    __string(irq_devname, irq_devname)
+    ),
+    TP_fast_assign(
+    __entry->remote_pid = remote_pid;
+    __assign_str(irq_devname, irq_devname);
+    ),
+    TP_printk("%d: %s: SSR detected, doing SSR Handshake",
+    __entry->remote_pid,
+    __get_str(irq_devname)
+    )
+);
+


I don't think we need to pass remote_pid into all of the traces if we 
have a unique name "irq_devname" to identify the remote now. We could 
remove remote_pid from all the trace event arguments.


We can probably drop the "doing SSR Handshake" part of this print. I 
think it can be assumed that we're doing the handshake once we've 
detected SSR.




[PATCH V1] rpmsg: glink: Make glink smem interrupt wakeup capable

2024-06-03 Thread Deepak Kumar Singh
There are certain usecases which require glink interrupt to be
wakeup capable. For example if handset is in sleep state and
usb charger is plugged in, dsp wakes up and sends glink interrupt
to host for glink pmic channel communication. Glink is suppose to
wakeup host processor completely for further glink data handling.
IRQF_NO_SUSPEND does not gurantee complete wakeup, system may again
enter sleep after interrupt handling and glink data may not be
handled by pmic client driver.

To ensure data handling by client configure glink smem device as
wakeup source and attach glink interrupt as wakeup irq. Remove
IRQF_NO_SUSPEND flag as it is no longer required.

Signed-off-by: Deepak Kumar Singh 
---
 drivers/rpmsg/qcom_glink_smem.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index 7a982c60a8dd..f1b553efab13 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -306,8 +307,7 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct 
device *parent,
 
smem->irq = of_irq_get(smem->dev.of_node, 0);
ret = devm_request_irq(>dev, smem->irq, qcom_glink_smem_intr,
-  IRQF_NO_SUSPEND | IRQF_NO_AUTOEN,
-  "glink-smem", smem);
+  IRQF_NO_AUTOEN, "glink-smem", smem);
if (ret) {
dev_err(>dev, "failed to request IRQ\n");
goto err_put_dev;
@@ -346,6 +346,8 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct 
device *parent,
 
smem->glink = glink;
 
+   device_init_wakeup(dev, true);
+   dev_pm_set_wake_irq(dev, smem->irq);
enable_irq(smem->irq);
 
return smem;
@@ -365,6 +367,8 @@ void qcom_glink_smem_unregister(struct qcom_glink_smem 
*smem)
struct qcom_glink *glink = smem->glink;
 
disable_irq(smem->irq);
+   dev_pm_clear_wake_irq(>dev);
+   device_init_wakeup(>dev, false);
 
qcom_glink_native_remove(glink);
 
-- 
2.34.1




Re: [RFC PATCH] rpmsg: glink: Add bounds check on tx path

2024-03-20 Thread Deepak Kumar Singh




On 1/29/2024 10:03 PM, Michal Koutný wrote:

On Mon, Jan 29, 2024 at 04:18:36PM +0530, Deepak Kumar Singh 
 wrote:

There is already a patch posted for similar problem -
https://lore.kernel.org/all/20231201110631.669085-1-quic_dee...@quicinc.com/


I was not aware, thanks for the pointer.

Do you plan to update your patch to "just" bail-out/zero instead of
using slightly random values (as pointed out by Bjorn)?

Michal

Hi Michal,
Yes, i will be fixing those comments and re post patch.



Re: [RFC PATCH] rpmsg: glink: Add bounds check on tx path

2024-01-29 Thread Deepak Kumar Singh




On 1/13/2024 5:55 AM, Michal Koutný wrote:

Add bounds check on values read from shared memory in the tx path. In
cases where the VM is misbehaving, the transport should exit and print a
warning when bogus values may cause out of bounds to be read.

Link: 
https://git.codelinaro.org/clo/la/kernel/msm-5.10/-/commit/32d9c3a2f2b6a4d1fc48d6871194f3faf3184e8b
Suggested-by: Chris Lew 
Suggested-by: Sarannya S 
Signed-off-by: Michal Koutný 
---
  drivers/rpmsg/qcom_glink_smem.c | 9 +
  1 file changed, 9 insertions(+)

Why RFC? The patch is adopted from the link above. It would be good to
asses whether such conditions can also happen with rpmsg glink.
(And if so, whether the zeroed values are the best correction.)


Hi Michal,

There is already a patch posted for similar problem -
https://lore.kernel.org/all/20231201110631.669085-1-quic_dee...@quicinc.com/


diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index 7a982c60a8dd..3e786e590c03 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -146,6 +146,11 @@ static size_t glink_smem_tx_avail(struct qcom_glink_pipe 
*np)
else
avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE;
  
+	if (avail > pipe->native.length) {

+   pr_warn_once("%s: avail clamped\n", __func__);
+   avail = 0;
+   }
+
return avail;
  }
  
@@ -177,6 +182,10 @@ static void glink_smem_tx_write(struct qcom_glink_pipe *glink_pipe,

unsigned int head;
  
  	head = le32_to_cpu(*pipe->head);

+   if (head > pipe->native.length) {
+   pr_warn_once("%s: head overflow\n", __func__);
+   return;
+   }
  
  	head = glink_smem_tx_write_one(pipe, head, hdr, hlen);

head = glink_smem_tx_write_one(pipe, head, data, dlen);




[PATCH V1] rpmsg: glink: smem: validate index before fifo read write

2023-12-01 Thread Deepak Kumar Singh
Fifo head and tail index can be modified with wrong values from
untrusted remote procs. Glink smem is not validating these index
before using to read or write fifo. This can result in out of
bound memory access if head and tail have incorrect values.

Add check for validation of head and tail index. This check will
put index within fifo boundaries, so that no invalid memory access
is made. Further this may result in certain packet drops unless
glink finds a valid packet header in fifo again and recovers.

Crash signature and calltrace with wrong head and tail values:

Internal error: Oops: 9607 [#1] PREEMPT SMP
pc : __memcpy_fromio+0x34/0xb4
lr : glink_smem_rx_peak+0x68/0x94

__memcpy_fromio+0x34/0xb4
glink_smem_rx_peak+0x68/0x94
qcom_glink_native_intr+0x90/0x888

Signed-off-by: Deepak Kumar Singh 
---
 drivers/rpmsg/qcom_glink_smem.c | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index 7a982c60a8dd..9eba0aaae916 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -86,9 +86,14 @@ static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np)
tail = le32_to_cpu(*pipe->tail);
 
if (head < tail)
-   return pipe->native.length - tail + head;
+   len = pipe->native.length - tail + head;
else
-   return head - tail;
+   len = head - tail;
+
+   if (WARN_ON_ONCE(len > pipe->native.length))
+   len = 0;
+
+   return len;
 }
 
 static void glink_smem_rx_peek(struct qcom_glink_pipe *np,
@@ -99,6 +104,10 @@ static void glink_smem_rx_peek(struct qcom_glink_pipe *np,
u32 tail;
 
tail = le32_to_cpu(*pipe->tail);
+
+   if (WARN_ON_ONCE(tail > pipe->native.length))
+   return;
+
tail += offset;
if (tail >= pipe->native.length)
tail -= pipe->native.length;
@@ -121,7 +130,7 @@ static void glink_smem_rx_advance(struct qcom_glink_pipe 
*np,
 
tail += count;
if (tail >= pipe->native.length)
-   tail -= pipe->native.length;
+   tail %= pipe->native.length;
 
*pipe->tail = cpu_to_le32(tail);
 }
@@ -146,6 +155,9 @@ static size_t glink_smem_tx_avail(struct qcom_glink_pipe 
*np)
else
avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE;
 
+   if (WARN_ON_ONCE(avail > pipe->native.length))
+   avail = 0;
+
return avail;
 }
 
@@ -155,6 +167,9 @@ static unsigned int glink_smem_tx_write_one(struct 
glink_smem_pipe *pipe,
 {
size_t len;
 
+   if (WARN_ON_ONCE(head > pipe->native.length))
+   return head;
+
len = min_t(size_t, count, pipe->native.length - head);
if (len)
memcpy(pipe->fifo + head, data, len);
-- 
2.34.1




[PATCH V2 2/2] soc: qcom: aoss: Add debugfs entry

2021-04-08 Thread Deepak Kumar Singh
It can be useful to control the different power states of various
parts of hardware for device testing. Add a debugfs node for qmp so
messages can be sent to aoss for debugging and testing purposes.

Signed-off-by: Chris Lew 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/soc/qcom/qcom_aoss.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index 0e397a7..6057bbe 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -4,6 +4,7 @@
  */
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -88,6 +89,9 @@ struct qmp {
struct clk_hw qdss_clk;
struct genpd_onecell_data pd_data;
struct qmp_cooling_device *cooling_devs;
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+   struct dentry *debugfs_file;
+#endif /* CONFIG_DEBUG_FS */
 };
 
 struct qmp_pd {
@@ -560,6 +564,34 @@ void qmp_put(struct platform_device *pdev)
 }
 EXPORT_SYMBOL(qmp_put);
 
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+static ssize_t aoss_dbg_write(struct file *file, const char __user *userstr,
+ size_t len, loff_t *pos)
+{
+   struct qmp *qmp = file->private_data;
+   char buf[QMP_MSG_LEN] = {};
+   int ret;
+
+   if (!len || len >= QMP_MSG_LEN)
+   return -EINVAL;
+
+   ret  = copy_from_user(buf, userstr, len);
+   if (ret) {
+   dev_err(qmp->dev, "copy from user failed, ret:%d\n", ret);
+   return -EFAULT;
+   }
+
+   ret = qmp_send(qmp, buf, QMP_MSG_LEN);
+
+   return ret ? ret : len;
+}
+
+static const struct file_operations aoss_dbg_fops = {
+   .open = simple_open,
+   .write = aoss_dbg_write,
+};
+#endif /* CONFIG_DEBUG_FS */
+
 static int qmp_probe(struct platform_device *pdev)
 {
struct resource *res;
@@ -616,6 +648,11 @@ static int qmp_probe(struct platform_device *pdev)
 
atomic_set(>orphan, 0);
 
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+   qmp->debugfs_file = debugfs_create_file("aoss_send_message", 0220, NULL,
+   qmp, _dbg_fops);
+#endif /* CONFIG_DEBUG_FS */
+
return 0;
 
 err_remove_qdss_clk:
@@ -632,6 +669,10 @@ static int qmp_remove(struct platform_device *pdev)
 {
struct qmp *qmp = platform_get_drvdata(pdev);
 
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+   debugfs_remove(qmp->debugfs_file);
+#endif /* CONFIG_DEBUG_FS */
+
qmp_qdss_clk_remove(qmp);
qmp_pd_remove(qmp);
qmp_cooling_devices_remove(qmp);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V2 1/2] soc: qcom: aoss: Expose send for generic usecase

2021-04-08 Thread Deepak Kumar Singh
From: Deepak Kumar Singh 

Not all upcoming usecases will have an interface to allow the aoss
driver to hook onto. Expose the send api and create a get function to
enable drivers to send their own messages to aoss.

Signed-off-by: Chris Lew 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/soc/qcom/qcom_aoss.c   | 50 +-
 include/linux/soc/qcom/qcom_aoss.h | 33 +
 2 files changed, 82 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/soc/qcom/qcom_aoss.h

diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index 53acb94..0e397a7 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -8,10 +8,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #define QMP_DESC_MAGIC 0x0
 #define QMP_DESC_VERSION   0x4
@@ -61,6 +63,7 @@ struct qmp_cooling_device {
  * @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
+ * @orphan: tarcks whether qmp handle is valid
  * @event: wait_queue for synchronization with the IRQ
  * @tx_lock: provides synchronization between multiple callers of qmp_send()
  * @qdss_clk: QDSS clock hw struct
@@ -76,6 +79,7 @@ struct qmp {
 
size_t offset;
size_t size;
+   atomic_t  orphan;
 
wait_queue_head_t event;
 
@@ -223,11 +227,17 @@ static bool qmp_message_empty(struct qmp *qmp)
  *
  * Return: 0 on success, negative errno on failure
  */
-static int qmp_send(struct qmp *qmp, const void *data, size_t len)
+int qmp_send(struct qmp *qmp, const void *data, size_t len)
 {
long time_left;
int ret;
 
+   if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data))
+   return -EINVAL;
+
+   if (atomic_read(>orphan))
+   return -EINVAL;
+
if (WARN_ON(len + sizeof(u32) > qmp->size))
return -EINVAL;
 
@@ -261,6 +271,7 @@ static int qmp_send(struct qmp *qmp, const void *data, 
size_t len)
 
return ret;
 }
+EXPORT_SYMBOL(qmp_send);
 
 static int qmp_qdss_clk_prepare(struct clk_hw *hw)
 {
@@ -515,6 +526,40 @@ static void qmp_cooling_devices_remove(struct qmp *qmp)
thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev);
 }
 
+/**
+ * qmp_get() - get a qmp handle from a device
+ * @dev: client device pointer
+ *
+ * Return: handle to qmp device on success, ERR_PTR() on failure
+ */
+struct qmp *qmp_get(struct device *dev)
+{
+   struct platform_device *pdev;
+   struct device_node *np;
+   struct qmp *qmp;
+
+   if (!dev || !dev->of_node)
+   return ERR_PTR(-EINVAL);
+
+   np = of_parse_phandle(dev->of_node, "qcom,qmp", 0);
+   if (!np)
+   return ERR_PTR(-ENODEV);
+
+   pdev = of_find_device_by_node(np);
+   if (!pdev)
+   return ERR_PTR(-EINVAL);
+
+   qmp = platform_get_drvdata(pdev);
+   return qmp ? qmp : ERR_PTR(-EPROBE_DEFER);
+}
+EXPORT_SYMBOL(qmp_get);
+
+void qmp_put(struct platform_device *pdev)
+{
+   platform_device_put(pdev);
+}
+EXPORT_SYMBOL(qmp_put);
+
 static int qmp_probe(struct platform_device *pdev)
 {
struct resource *res;
@@ -569,6 +614,8 @@ static int qmp_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, qmp);
 
+   atomic_set(>orphan, 0);
+
return 0;
 
 err_remove_qdss_clk:
@@ -590,6 +637,7 @@ static int qmp_remove(struct platform_device *pdev)
qmp_cooling_devices_remove(qmp);
 
qmp_close(qmp);
+   atomic_set(>orphan, 1);
mbox_free_channel(qmp->mbox_chan);
 
return 0;
diff --git a/include/linux/soc/qcom/qcom_aoss.h 
b/include/linux/soc/qcom/qcom_aoss.h
new file mode 100644
index 000..27d00f7
--- /dev/null
+++ b/include/linux/soc/qcom/qcom_aoss.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __QCOM_AOSS_H__
+#define __QCOM_AOSS_H__
+
+#include 
+#include 
+
+struct qmp;
+
+#if IS_ENABLED(CONFIG_QCOM_AOSS_QMP)
+
+int qmp_send(struct qmp *qmp, const void *data, size_t len);
+struct qmp *qmp_get(struct device *dev);
+
+#else
+
+static inline int qmp_send(struct qmp *qmp, const void *data, size_t len)
+{
+   return -ENODEV;
+}
+
+static inline struct qmp *qmp_get(struct device *dev)
+{
+   return ERR_PTR(-ENODEV);
+}
+
+#endif
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V2 0/2] soc: qcom: aoss: Expose send for generic usecase

2021-04-08 Thread Deepak Kumar Singh
Change from V1
Addressesed all review comments in previous set.

Deepak Kumar Singh (2):
  soc: qcom: aoss: Expose send for generic usecase
  soc: qcom: aoss: Add debugfs entry

 drivers/soc/qcom/qcom_aoss.c   | 91 +-
 include/linux/soc/qcom/qcom_aoss.h | 33 ++
 2 files changed, 123 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/soc/qcom/qcom_aoss.h

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



[PATCH V1 2/2] soc: qcom: aoss: Add debugfs entry

2021-04-02 Thread Deepak Kumar Singh
It can be useful to control the different power states of various
parts of hardware for device testing. Add a debugfs node for qmp so
messages can be sent to aoss for debugging and testing purposes.

Signed-off-by: Chris Lew 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/soc/qcom/qcom_aoss.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index 5c643f0..1789880 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -4,6 +4,7 @@
  */
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -86,6 +87,9 @@ struct qmp {
struct clk_hw qdss_clk;
struct genpd_onecell_data pd_data;
struct qmp_cooling_device *cooling_devs;
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+   struct dentry *debugfs_file;
+#endif /* CONFIG_DEBUG_FS */
 };
 
 struct qmp_pd {
@@ -549,6 +553,34 @@ struct qmp *qmp_get(struct device *dev)
 }
 EXPORT_SYMBOL(qmp_get);
 
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+static ssize_t aoss_dbg_write(struct file *file, const char __user *userstr,
+ size_t len, loff_t *pos)
+{
+   struct qmp *qmp = file->private_data;
+   char buf[QMP_MSG_LEN] = {};
+   int ret;
+
+   if (!len || len >= QMP_MSG_LEN)
+   return len;
+
+   ret  = copy_from_user(buf, userstr, len);
+   if (ret) {
+   dev_err(qmp->dev, "copy from user failed, ret:%d\n", ret);
+   return len;
+   }
+
+   ret = qmp_send(qmp, buf, QMP_MSG_LEN);
+
+   return ret ? ret : len;
+}
+
+static const struct file_operations aoss_dbg_fops = {
+   .open = simple_open,
+   .write = aoss_dbg_write,
+};
+#endif /* CONFIG_DEBUG_FS */
+
 static int qmp_probe(struct platform_device *pdev)
 {
struct resource *res;
@@ -603,6 +635,11 @@ static int qmp_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, qmp);
 
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+   qmp->debugfs_file = debugfs_create_file("aoss_send_message", 0220, NULL,
+   qmp, _dbg_fops);
+#endif /* CONFIG_DEBUG_FS */
+
return 0;
 
 err_remove_qdss_clk:
@@ -619,6 +656,10 @@ static int qmp_remove(struct platform_device *pdev)
 {
struct qmp *qmp = platform_get_drvdata(pdev);
 
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+   debugfs_remove(qmp->debugfs_file);
+#endif /* CONFIG_DEBUG_FS */
+
qmp_qdss_clk_remove(qmp);
qmp_pd_remove(qmp);
qmp_cooling_devices_remove(qmp);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 1/2] soc: qcom: aoss: Expose send for generic usecase

2021-04-02 Thread Deepak Kumar Singh
Not all upcoming usecases will have an interface to allow the aoss
driver to hook onto. Expose the send api and create a get function to
enable drivers to send their own messages to aoss.

Signed-off-by: Chris Lew 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/soc/qcom/qcom_aoss.c | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index 53acb94..5c643f0 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -8,10 +8,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #define QMP_DESC_MAGIC 0x0
 #define QMP_DESC_VERSION   0x4
@@ -223,11 +225,14 @@ static bool qmp_message_empty(struct qmp *qmp)
  *
  * Return: 0 on success, negative errno on failure
  */
-static int qmp_send(struct qmp *qmp, const void *data, size_t len)
+int qmp_send(struct qmp *qmp, const void *data, size_t len)
 {
long time_left;
int ret;
 
+   if (!qmp || !data)
+   return -EINVAL;
+
if (WARN_ON(len + sizeof(u32) > qmp->size))
return -EINVAL;
 
@@ -261,6 +266,7 @@ static int qmp_send(struct qmp *qmp, const void *data, 
size_t len)
 
return ret;
 }
+EXPORT_SYMBOL(qmp_send);
 
 static int qmp_qdss_clk_prepare(struct clk_hw *hw)
 {
@@ -515,6 +521,34 @@ static void qmp_cooling_devices_remove(struct qmp *qmp)
thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev);
 }
 
+/**
+ * qmp_get() - get a qmp handle from a device
+ * @dev: client device pointer
+ *
+ * Return: handle to qmp device on success, ERR_PTR() on failure
+ */
+struct qmp *qmp_get(struct device *dev)
+{
+   struct platform_device *pdev;
+   struct device_node *np;
+   struct qmp *qmp;
+
+   if (!dev || !dev->of_node)
+   return ERR_PTR(-ENODEV);
+
+   np = of_parse_phandle(dev->of_node, "qcom,qmp", 0);
+   if (!np)
+   return ERR_PTR(-ENODEV);
+
+   pdev = of_find_device_by_node(np);
+   if (!pdev)
+   return ERR_PTR(-EINVAL);
+
+   qmp = platform_get_drvdata(pdev);
+   return qmp ? qmp : ERR_PTR(-EPROBE_DEFER);
+}
+EXPORT_SYMBOL(qmp_get);
+
 static int qmp_probe(struct platform_device *pdev)
 {
struct resource *res;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 0/2] soc: qcom: aoss: Expose send for generic usecase

2021-04-02 Thread Deepak Kumar Singh
[Change from V0]
Update qmp_get to parse qmp handle with binding qcom,qmp

Deepak Kumar Singh (2):
  soc: qcom: aoss: Expose send for generic usecase
  soc: qcom: aoss: Add debugfs entry

 drivers/soc/qcom/qcom_aoss.c | 77 +++-
 1 file changed, 76 insertions(+), 1 deletion(-)

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



[PATCH V1 1/1] soc: qcom: smp2p: Add enable_irq_wake to SMP2P IRQ

2021-03-18 Thread Deepak Kumar Singh
SMP2P interrupts are expected to wake the processor from suspend.
Use enable_irq_wake to mark it wakeup capable from suspend.

Signed-off-by: Chris Lew 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/soc/qcom/smp2p.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index 2df4883..df47ee6 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -538,6 +538,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
goto unwind_interfaces;
}
 
+   enable_irq_wake(irq);
 
return 0;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH V5 0/4] Signaling api support in glink/rpmsg clients

2020-09-02 Thread Deepak Kumar Singh



On 7/6/2020 11:34 PM, Mathieu Poirier wrote:

Hi Deepak,

On Fri, Jun 26, 2020 at 08:16:55PM +0530, Deepak Kumar Singh wrote:

Change from version 5
[V5,4/4] rpmsg: char: Add signal callback and POLLPRI support
Updated for sparse warning. Replaced POLLPRI => EPOLLPRI to fix
warning.

Change from version 4
I am taking over these patches from ane...@codeaurora.org
Fixed all the trivial review comments.

Signal conversion to and from native signal as done in patch V4,2/4
is intentional.

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

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

I'm confused here - V5 (or what I think it is) was sent out on June 24th without
a cover letter.  This set has a cover letter but it is labeled V5.  So is this
the cover letter that should have been sent out on the 24th and the content
herein relevent to that set?  Or is it accurate and the label on the cover
letter of this set is wrong and should have been V6?

I have little confidence in both sets and as such won't be reviewing them.
Please send a new revision that is properly labeled.

Thanks,
Mathieu


Mistakenly i forgot to update label for cover letter to V6.

I have uploaded patch set V7 with updated cover letter.

There is no change in patches.


  drivers/rpmsg/qcom_glink_native.c | 125 ++
  drivers/rpmsg/rpmsg_char.c|  76 ++-
  drivers/rpmsg/rpmsg_core.c|  40 
  drivers/rpmsg/rpmsg_internal.h|   5 ++
  include/linux/rpmsg.h |  27 
  5 files changed, 270 insertions(+), 3 deletions(-)

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


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



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

2020-09-02 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
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 4bbbacd..43ceac0 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,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;
+   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);
+   break;
+   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 V7 1/4] rpmsg: core: Add signal API support

2020-09-02 Thread Deepak Kumar Singh
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.
Local glink client drivers can send and receive signals to glink
clients running on remote processors.

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

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

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index a6361ca..06733a6 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -283,6 +283,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 -ENXIO;
+
+   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 -ENXIO;
+
+   return ept->ops->set_signals(ept, set, clear);
+}
+EXPORT_SYMBOL(rpmsg_set_signals);
+
 /*
  * match a rpmsg channel with a channel info struct.
  * this is used to make sure we're not creating rpmsg devices for channels
@@ -468,6 +504,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..c4dbb47 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 channe

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

2020-09-02 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
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 43ceac0..64506ca 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 |= EPOLLPRI;
+
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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



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

2020-09-02 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 125 ++
 1 file changed, 125 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index f40312b..499381a 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #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,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 +208,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 +988,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 +1119,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 V7 0/4] Signaling api support in glink/rpmsg clients

2020-09-02 Thread Deepak Kumar Singh
Change from version 6
In last series(v6) i had put wrong version(v5) for cover note.
Which led to confusion for patch set series.

In this series i have updated the label for cover letter(v7).
There is no change in patches. Only cover note label is updated.

Change from version 5
[V6,4/4] rpmsg: char: Add signal callback and POLLPRI support
Updated for sparse warning. Replaced POLLPRI => EPOLLPRI to fix
warning.

Change from version 4
I am taking over these patches from ane...@codeaurora.org
Fixed all the trivial review comments.

Signal conversion to and from native signal as done in patch V4,2/4
is intentional.

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

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

 drivers/rpmsg/qcom_glink_native.c | 125 ++
 drivers/rpmsg/rpmsg_char.c|  76 ++-
 drivers/rpmsg/rpmsg_core.c|  40 
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  27 
 5 files changed, 270 insertions(+), 3 deletions(-)

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



[PATCH V1 1/4] net: qrtr: Do not send packets before hello negotiation

2020-08-30 Thread Deepak Kumar Singh
From: Chris Lew 

There is a race where broadcast packets can be sent to a node that has
not sent the hello message to the remote processor. This breaks the
protocol expectation. Add a status variable to track when the hello
packet has been sent.

An alternative solution attempted was to remove the nodes from the
broadcast list until the hello packet is sent. This is not a valid
solution because hello messages are broadcasted if the ns is restarted
or started late. There needs to be a status variable separate from the
broadcast list.
---
 net/qrtr/qrtr.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index 90c558f8..d9858a1 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -115,6 +115,7 @@ static DEFINE_MUTEX(qrtr_port_lock);
  * @ep: endpoint
  * @ref: reference count for node
  * @nid: node id
+ * @hello_sent: hello packet sent to endpoint
  * @qrtr_tx_flow: tree of qrtr_tx_flow, keyed by node << 32 | port
  * @qrtr_tx_lock: lock for qrtr_tx_flow inserts
  * @rx_queue: receive queue
@@ -125,6 +126,7 @@ struct qrtr_node {
struct qrtr_endpoint *ep;
struct kref ref;
unsigned int nid;
+   atomic_t hello_sent;
 
struct radix_tree_root qrtr_tx_flow;
struct mutex qrtr_tx_lock; /* for qrtr_tx_flow */
@@ -335,6 +337,11 @@ static int qrtr_node_enqueue(struct qrtr_node *node, 
struct sk_buff *skb,
int rc = -ENODEV;
int confirm_rx;
 
+   if (!atomic_read(>hello_sent) && type != QRTR_TYPE_HELLO) {
+   kfree_skb(skb);
+   return rc;
+   }
+
confirm_rx = qrtr_tx_wait(node, to->sq_node, to->sq_port, type);
if (confirm_rx < 0) {
kfree_skb(skb);
@@ -370,6 +377,8 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct 
sk_buff *skb,
 * confirm_rx flag if we dropped this one */
if (rc && confirm_rx)
qrtr_tx_flow_failed(node, to->sq_node, to->sq_port);
+   if (!rc && type == QRTR_TYPE_HELLO)
+   atomic_inc(>hello_sent);
 
return rc;
 }
@@ -563,6 +572,7 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, 
unsigned int nid)
skb_queue_head_init(>rx_queue);
node->nid = QRTR_EP_NID_AUTO;
node->ep = ep;
+   atomic_set(>hello_sent, 0);
 
INIT_RADIX_TREE(>qrtr_tx_flow, GFP_KERNEL);
mutex_init(>qrtr_tx_lock);
@@ -854,6 +864,8 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, 
struct sk_buff *skb,
 
mutex_lock(_node_lock);
list_for_each_entry(node, _all_nodes, item) {
+   if (node->nid == QRTR_EP_NID_AUTO)
+   continue;
skbn = skb_clone(skb, GFP_KERNEL);
if (!skbn)
break;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 4/4] net: qrtr: Check function pointer before calling

2020-08-30 Thread Deepak Kumar Singh
From: Arun Kumar Neelakantam 

sk_error_report callback function called without validating cause the NULL
pointer dereference.

Validate function pointer before using for error report.
---
 net/qrtr/qrtr.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index e2dd38e..01cabd3 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -786,7 +786,8 @@ static void qrtr_reset_ports(void)
 
sock_hold(>sk);
ipc->sk.sk_err = ENETRESET;
-   ipc->sk.sk_error_report(>sk);
+   if (ipc->sk.sk_error_report)
+   ipc->sk.sk_error_report(>sk);
sock_put(>sk);
}
mutex_unlock(_port_lock);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 2/4] net: qrtr: Add socket mode optimization

2020-08-30 Thread Deepak Kumar Singh
From: Chris Lew 

A remote endpoint should not need to know when a client socket is freed
if the socket never established commnication with the endpoint. Add a
mode to keep track of which endpoints a socket communicates with.

There are three modes a socket can be in:
INIT   - Socket has not sent anything or only local messages,
 only send client close to local services.

SINGLE - Socket has sent messages to a single ept, send event
 to this single ept.

MULTI  - Socket has sent messages to multiple epts, broadcast
 release of this socket.

Server state changes should be broadcast throughout the system. Change
the ipc state of a port when it sends a NEW SERVER control packet. This
ensures the DEL CLIENT control packet is propagated correctly for
servers.
---
 net/qrtr/qrtr.c | 72 ++---
 1 file changed, 59 insertions(+), 13 deletions(-)

diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index d9858a1..4496b75 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -21,6 +21,10 @@
 #define QRTR_MIN_EPH_SOCKET 0x4000
 #define QRTR_MAX_EPH_SOCKET 0x7fff
 
+/* qrtr socket states */
+#define QRTR_STATE_MULTI   -2
+#define QRTR_STATE_INIT-1
+
 /**
  * struct qrtr_hdr_v1 - (I|R)PCrouter packet header version 1
  * @version: protocol version
@@ -87,6 +91,8 @@ struct qrtr_sock {
struct sock sk;
struct sockaddr_qrtr us;
struct sockaddr_qrtr peer;
+
+   int state;
 };
 
 static inline struct qrtr_sock *qrtr_sk(struct sock *sk)
@@ -653,29 +659,59 @@ static void qrtr_port_put(struct qrtr_sock *ipc)
sock_put(>sk);
 }
 
-/* Remove port assignment. */
-static void qrtr_port_remove(struct qrtr_sock *ipc)
+static void qrtr_send_del_client(struct qrtr_sock *ipc)
 {
struct qrtr_ctrl_pkt *pkt;
-   struct sk_buff *skb;
-   int port = ipc->us.sq_port;
struct sockaddr_qrtr to;
+   struct qrtr_node *node;
+   struct sk_buff *skbn;
+   struct sk_buff *skb;
+   int type = QRTR_TYPE_DEL_CLIENT;
+
+   skb = qrtr_alloc_ctrl_packet();
+   if (!skb)
+   return;
 
to.sq_family = AF_QIPCRTR;
to.sq_node = QRTR_NODE_BCAST;
to.sq_port = QRTR_PORT_CTRL;
 
-   skb = qrtr_alloc_ctrl_packet();
-   if (skb) {
-   pkt->cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT);
-   pkt->client.node = cpu_to_le32(ipc->us.sq_node);
-   pkt->client.port = cpu_to_le32(ipc->us.sq_port);
+   pkt->cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT);
+   pkt->client.node = cpu_to_le32(ipc->us.sq_node);
+   pkt->client.port = cpu_to_le32(ipc->us.sq_port);
+
+   skb_set_owner_w(skb, >sk);
 
-   skb_set_owner_w(skb, >sk);
-   qrtr_bcast_enqueue(NULL, skb, QRTR_TYPE_DEL_CLIENT, >us,
-  );
+   if (ipc->state == QRTR_STATE_MULTI) {
+   qrtr_bcast_enqueue(NULL, skb, type, >us, );
+   return;
+   }
+
+   if (ipc->state > QRTR_STATE_INIT) {
+   node = qrtr_node_lookup(ipc->state);
+   if (!node)
+   goto exit;
+
+   skbn = skb_clone(skb, GFP_KERNEL);
+   if (!skbn) {
+   qrtr_node_release(node);
+   goto exit;
+   }
+
+   skb_set_owner_w(skbn, >sk);
+   qrtr_node_enqueue(node, skbn, type, >us, );
+   qrtr_node_release(node);
}
+exit:
+   qrtr_local_enqueue(NULL, skb, type, >us, );
+}
 
+/* Remove port assignment. */
+static void qrtr_port_remove(struct qrtr_sock *ipc)
+{
+   int port = ipc->us.sq_port;
+
+   qrtr_send_del_client(ipc);
if (port == QRTR_PORT_CTRL)
port = 0;
 
@@ -941,6 +977,11 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr 
*msg, size_t len)
return -ECONNRESET;
}
enqueue_fn = qrtr_node_enqueue;
+
+   if (ipc->state > QRTR_STATE_INIT && ipc->state != node->nid)
+   ipc->state = QRTR_STATE_MULTI;
+   else if (ipc->state == QRTR_STATE_INIT)
+   ipc->state = node->nid;
}
 
plen = (len + 3) & ~3;
@@ -957,7 +998,8 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr 
*msg, size_t len)
goto out_node;
}
 
-   if (ipc->us.sq_port == QRTR_PORT_CTRL) {
+   if (ipc->us.sq_port == QRTR_PORT_CTRL ||
+   addr->sq_port == QRTR_PORT_CTRL) {
if (len < 4) {
rc = -EINVAL;
kfree_skb(skb);
@@ -969,6 +1011,9 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr 
*msg, size_t len)
}
 
type = le32_to_cpu(qrtr_type);
+   if (addr->sq_port == QRTR_PORT_CTRL && type == QRTR_TYPE_NEW_SERVER)
+   ipc->state = 

[PATCH V1 3/4] net: qrtr: Change port allocation to use cyclic idr

2020-08-30 Thread Deepak Kumar Singh
From: Chris Lew 

There is a race for clients that open sockets before the control port
is bound. If a client gets an idr that was allocated before the control
port is bound, there is a chance the previous address owner sent lookup
packets to the control port. The new address owner will get residual
responses to this the lookup packets.

Change the idr_alloc to idr_alloc_cyclic so new idr's are allocated
instead of trying to reuse the freed idrs.
---
 net/qrtr/qrtr.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index 4496b75..e2dd38e 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -744,7 +744,8 @@ static int qrtr_port_assign(struct qrtr_sock *ipc, int 
*port)
mutex_lock(_port_lock);
if (!*port) {
min_port = QRTR_MIN_EPH_SOCKET;
-   rc = idr_alloc_u32(_ports, ipc, _port, 
QRTR_MAX_EPH_SOCKET, GFP_ATOMIC);
+   rc = idr_alloc_cyclic(_ports, ipc, _port,
+ QRTR_MAX_EPH_SOCKET, GFP_ATOMIC);
if (!rc)
*port = min_port;
} else if (*port < QRTR_MIN_EPH_SOCKET && !capable(CAP_NET_ADMIN)) {
@@ -754,7 +755,8 @@ static int qrtr_port_assign(struct qrtr_sock *ipc, int 
*port)
rc = idr_alloc_u32(_ports, ipc, _port, 0, GFP_ATOMIC);
} else {
min_port = *port;
-   rc = idr_alloc_u32(_ports, ipc, _port, *port, 
GFP_ATOMIC);
+   rc = idr_alloc_cyclic(_ports, ipc, _port,
+ *port, GFP_ATOMIC);
if (!rc)
*port = min_port;
}
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 0/4] General qrtr fixes

2020-08-30 Thread Deepak Kumar Singh
Arun Kumar Neelakantam (1):
  net: qrtr: Check function pointer before calling

Chris Lew (3):
  net: qrtr: Do not send packets before hello negotiation
  net: qrtr: Add socket mode optimization
  net: qrtr: Change port allocation to use cyclic idr

 net/qrtr/qrtr.c | 93 +++--
 1 file changed, 77 insertions(+), 16 deletions(-)

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



[PATCH V1 2/6] rpmsg: glink: Deny intent request if reusable intent fits

2020-07-29 Thread Deepak Kumar Singh
From: Chris Lew 

In high traffic scenarios a remote may request extra intents to send
data faster. If the work thread that handles these intent requests is
starved of cpu time, then these requests can build up. Some remote
procs may not be able to handle this burst of built up intent requests.

In order to prevent intent build up, deny intent requests that can be
fulfilled by default intents that are reusable.

Signed-off-by: Chris Lew 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/rpmsg/qcom_glink_native.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 2668c66..df3c608 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -734,9 +734,11 @@ static void qcom_glink_handle_rx_done(struct qcom_glink 
*glink,
 static void qcom_glink_handle_intent_req(struct qcom_glink *glink,
 u32 cid, size_t size)
 {
-   struct glink_core_rx_intent *intent;
+   struct glink_core_rx_intent *intent = NULL;
+   struct glink_core_rx_intent *tmp;
struct glink_channel *channel;
unsigned long flags;
+   int iid;
 
spin_lock_irqsave(>idr_lock, flags);
channel = idr_find(>rcids, cid);
@@ -747,6 +749,19 @@ static void qcom_glink_handle_intent_req(struct qcom_glink 
*glink,
return;
}
 
+   spin_lock_irqsave(>intent_lock, flags);
+   idr_for_each_entry(>liids, tmp, iid) {
+   if (tmp->size >= size && tmp->reuse) {
+   intent = tmp;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(>intent_lock, flags);
+   if (intent) {
+   qcom_glink_send_intent_req_ack(glink, channel, !!intent);
+   return;
+   }
+
intent = qcom_glink_alloc_intent(glink, channel, size, false);
if (intent)
qcom_glink_advertise_intent(glink, channel, intent);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 4/6] rpmsg: glink: Remove the rpmsg dev in close_ack

2020-07-29 Thread Deepak Kumar Singh
From: Arun Kumar Neelakantam 

Un-register and register of rpmsg driver is sending invalid open_ack
on closed channel.

To avoid sending invalid open_ack case unregister the rpmsg device
after receiving the local_close_ack from remote side.

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

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index ac179b1..031bc1d 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1526,6 +1526,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);
 
@@ -1539,6 +1540,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, 
unsigned int rcid)
 
 static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int 
lcid)
 {
+   struct rpmsg_channel_info chinfo;
struct glink_channel *channel;
unsigned long flags;
 
@@ -1553,6 +1555,16 @@ static void qcom_glink_rx_close_ack(struct qcom_glink 
*glink, unsigned int lcid)
channel->lcid = 0;
spin_unlock_irqrestore(>idr_lock, flags);
 
+   /* Decouple the potential rpdev from the channel */
+   if (channel->rpdev) {
+   strlcpy(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;
+
kref_put(>refcount, qcom_glink_channel_release);
 }
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 3/6] rpmsg: glink: Add TX_DATA_CONT command while sending

2020-07-29 Thread Deepak Kumar Singh
From: Arun Kumar Neelakantam 

With current design the transport can send packets of size upto
FIFO_SIZE which is 16k and return failure for all packets above 16k.

Add TX_DATA_CONT command to send packets greater than 16k by splitting
into 8K chunks.

Signed-off-by: Arun Kumar Neelakantam 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/rpmsg/qcom_glink_native.c | 38 ++
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index df3c608..ac179b1 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1289,6 +1289,8 @@ static int __qcom_glink_send(struct glink_channel 
*channel,
} __packed req;
int ret;
unsigned long flags;
+   int chunk_size = len;
+   int left_size = 0;
 
if (!glink->intentless) {
while (!intent) {
@@ -1322,18 +1324,46 @@ static int __qcom_glink_send(struct glink_channel 
*channel,
iid = intent->id;
}
 
+   if (wait && (chunk_size > SZ_8K)) {
+   chunk_size = SZ_8K;
+   left_size = len - chunk_size;
+   }
req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA);
req.msg.param1 = cpu_to_le16(channel->lcid);
req.msg.param2 = cpu_to_le32(iid);
-   req.chunk_size = cpu_to_le32(len);
-   req.left_size = cpu_to_le32(0);
+   req.chunk_size = cpu_to_le32(chunk_size);
+   req.left_size = cpu_to_le32(left_size);
 
-   ret = qcom_glink_tx(glink, , sizeof(req), data, len, wait);
+   ret = qcom_glink_tx(glink, , sizeof(req), data, chunk_size, wait);
 
/* Mark intent available if we failed */
-   if (ret && intent)
+   if (ret && intent) {
intent->in_use = false;
+   return ret;
+   }
 
+   while (left_size > 0) {
+   data = (void *)((char *)data + chunk_size);
+   chunk_size = left_size;
+   if (chunk_size > SZ_8K)
+   chunk_size = SZ_8K;
+   left_size -= chunk_size;
+
+   req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA_CONT);
+   req.msg.param1 = cpu_to_le16(channel->lcid);
+   req.msg.param2 = cpu_to_le32(iid);
+   req.chunk_size = cpu_to_le32(chunk_size);
+   req.left_size = cpu_to_le32(left_size);
+
+   ret = qcom_glink_tx(glink, , sizeof(req), data,
+   chunk_size, wait);
+
+   /* Mark intent available if we failed */
+   if (ret && intent) {
+   intent->in_use = false;
+   break;
+   }
+   }
return ret;
 }
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 6/6] rpmsg: glink: Send READ_NOTIFY command in FIFO full case

2020-07-29 Thread Deepak Kumar Singh
From: Arun Kumar Neelakantam 

The current design sleeps unconditionally in TX FIFO full case and
wakeup only after sleep timer expires which adds random delays in
clients TX path.

Avoid sleep and use READ_NOTIFY command so that writer can be woken up
when remote notifies about read completion by sending IRQ.

Signed-off-by: Deepak Kumar Singh 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index efaf32d..098039d 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -92,6 +92,8 @@ struct glink_core_rx_intent {
  * @rcids: idr of all channels with a known remote channel id
  * @features:  remote features
  * @intentless:flag to indicate that there is no intent
+ * @tx_avail_notify: Waitqueue for pending tx tasks
+ * @sent_read_notify: flag to check cmd sent or not
  */
 struct qcom_glink {
struct device *dev;
@@ -118,6 +120,8 @@ struct qcom_glink {
unsigned long features;
 
bool intentless;
+   wait_queue_head_t tx_avail_notify;
+   bool sent_read_notify;
 };
 
 enum {
@@ -301,6 +305,20 @@ static void qcom_glink_tx_write(struct qcom_glink *glink,
glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen);
 }
 
+static void qcom_glink_send_read_notify(struct qcom_glink *glink)
+{
+   struct glink_msg msg;
+
+   msg.cmd = cpu_to_le16(RPM_CMD_READ_NOTIF);
+   msg.param1 = 0;
+   msg.param2 = 0;
+
+   qcom_glink_tx_write(glink, , sizeof(msg), NULL, 0);
+
+   mbox_send_message(glink->mbox_chan, NULL);
+   mbox_client_txdone(glink->mbox_chan, 0);
+}
+
 static int qcom_glink_tx(struct qcom_glink *glink,
 const void *hdr, size_t hlen,
 const void *data, size_t dlen, bool wait)
@@ -321,12 +339,21 @@ static int qcom_glink_tx(struct qcom_glink *glink,
goto out;
}
 
+   if (!glink->sent_read_notify) {
+   glink->sent_read_notify = true;
+   qcom_glink_send_read_notify(glink);
+   }
+
/* Wait without holding the tx_lock */
spin_unlock_irqrestore(>tx_lock, flags);
 
-   usleep_range(1, 15000);
+   wait_event_timeout(glink->tx_avail_notify,
+   qcom_glink_tx_avail(glink) >= tlen, 10 * HZ);
 
spin_lock_irqsave(>tx_lock, flags);
+
+   if (qcom_glink_tx_avail(glink) >= tlen)
+   glink->sent_read_notify = false;
}
 
qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
@@ -1000,6 +1027,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void 
*data)
unsigned int cmd;
int ret = 0;
 
+   /* To wakeup any blocking writers */
+   wake_up_all(>tx_avail_notify);
+
for (;;) {
avail = qcom_glink_rx_avail(glink);
if (avail < sizeof(msg))
@@ -1542,6 +1572,9 @@ static void qcom_glink_rx_close_ack(struct qcom_glink 
*glink, unsigned int lcid)
struct glink_channel *channel;
unsigned long flags;
 
+   /* To wakeup any blocking writers */
+   wake_up_all(>tx_avail_notify);
+
spin_lock_irqsave(>idr_lock, flags);
channel = idr_find(>lcids, lcid);
if (WARN(!channel, "close ack on unknown channel\n")) {
@@ -1658,6 +1691,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device 
*dev,
spin_lock_init(>rx_lock);
INIT_LIST_HEAD(>rx_queue);
INIT_WORK(>rx_work, qcom_glink_work);
+   init_waitqueue_head(>tx_avail_notify);
 
spin_lock_init(>idr_lock);
idr_init(>lcids);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 5/6] rpmsg: glink: Remove channel decouple from rpdev release

2020-07-29 Thread Deepak Kumar Singh
From: Chris Lew 

If a channel is being rapidly restarting and the kobj release worker
is busy, there is a chance the the rpdev_release function will run
after the channel struct itself has been released.

There should not be a need to decouple the channel from rpdev in the
rpdev release since that should only happen from the close commands.

Signed-off-by: Chris Lew 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/rpmsg/qcom_glink_native.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 031bc1d..efaf32d 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1419,9 +1419,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops 
= {
 static void qcom_glink_rpdev_release(struct device *dev)
 {
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-   struct glink_channel *channel = to_glink_channel(rpdev->ept);
 
-   channel->rpdev = NULL;
kfree(rpdev);
 }
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 1/6] rpmsg: glink: fix destroy channel endpoint logic

2020-07-29 Thread Deepak Kumar Singh
From: Konstantin Dorfman 

When rpmsg client driver destroys last channel endpoint, remove rpmsg
device is triggered. In both cases (destroy endpoint and remove device)
a glink close command sent to the remote peer.

This change, when for removing rpmsg device endpoint already destroyed
will avoid sending second glink close command.

Signed-off-by: Konstantin Dorfman 
Signed-off-by: Deepak Kumar Singh 
---
 drivers/rpmsg/qcom_glink_native.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 1995f5b..2668c66 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1210,6 +1210,10 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint 
*ept)
unsigned long flags;
 
spin_lock_irqsave(>recv_lock, flags);
+   if (!channel->ept.cb) {
+   spin_unlock_irqrestore(>recv_lock, flags);
+   return;
+   }
channel->ept.cb = NULL;
spin_unlock_irqrestore(>recv_lock, flags);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 0/6] Glink native fixes upstreaming

2020-07-29 Thread Deepak Kumar Singh
Includes fixes for -
Few race conditions while channel release and close
Proper unregistration of rpmsg device to avoid use of stale device
Send notify command to remote when glink fifo is full
Handling packet size larger that 16K

Arun Kumar Neelakantam (3):
  rpmsg: glink: Add TX_DATA_CONT command while sending
  rpmsg: glink: Remove the rpmsg dev in close_ack
  rpmsg: glink: Send READ_NOTIFY command in FIFO full case

Chris Lew (2):
  rpmsg: glink: Deny intent request if reusable intent fits
  rpmsg: glink: Remove channel decouple from rpdev release

Konstantin Dorfman (1):
  rpmsg: glink: fix destroy channel endpoint logic

 drivers/rpmsg/qcom_glink_native.c | 109 +++---
 1 file changed, 101 insertions(+), 8 deletions(-)

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



[PATCH V5 0/4] Signaling api support in glink/rpmsg clients

2020-06-26 Thread Deepak Kumar Singh
Change from version 5
[V5,4/4] rpmsg: char: Add signal callback and POLLPRI support
Updated for sparse warning. Replaced POLLPRI => EPOLLPRI to fix
warning.

Change from version 4
I am taking over these patches from ane...@codeaurora.org
Fixed all the trivial review comments.

Signal conversion to and from native signal as done in patch V4,2/4
is intentional.

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

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

 drivers/rpmsg/qcom_glink_native.c | 125 ++
 drivers/rpmsg/rpmsg_char.c|  76 ++-
 drivers/rpmsg/rpmsg_core.c|  40 
 drivers/rpmsg/rpmsg_internal.h|   5 ++
 include/linux/rpmsg.h |  27 
 5 files changed, 270 insertions(+), 3 deletions(-)

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



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

2020-06-26 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
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 4bbbacd..43ceac0 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,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;
+   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);
+   break;
+   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 V6 4/4] rpmsg: char: Add signal callback and POLLPRI support

2020-06-26 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
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 43ceac0..64506ca 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 |= EPOLLPRI;
+
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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



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

2020-06-26 Thread Deepak Kumar Singh
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.
Local glink client drivers can send and receive signals to glink
clients running on remote processors.

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

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

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 91de940..e6eb5a1 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -283,6 +283,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 -ENXIO;
+
+   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 -ENXIO;
+
+   return ept->ops->set_signals(ept, set, clear);
+}
+EXPORT_SYMBOL(rpmsg_set_signals);
+
 /*
  * match a rpmsg channel with a channel info struct.
  * this is used to make sure we're not creating rpmsg devices for channels
@@ -468,6 +504,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..c4dbb47 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 channe

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

2020-06-26 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 125 ++
 1 file changed, 125 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 0e8a28c0..1bf3235 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #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,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 +208,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 +988,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 +1119,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 V5 2/4] rpmsg: glink: Add support to handle signals command

2020-06-24 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
Signed-off-by: Arun Kumar Neelakantam 
---
 drivers/rpmsg/qcom_glink_native.c | 125 ++
 1 file changed, 125 insertions(+)

diff --git a/drivers/rpmsg/qcom_glink_native.c 
b/drivers/rpmsg/qcom_glink_native.c
index 0e8a28c0..1bf3235 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #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,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 +208,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 +988,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 +1119,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 V5 3/4] rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support

2020-06-24 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
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 4bbbacd..43ceac0 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,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;
+   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);
+   break;
+   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 V5 4/4] rpmsg: char: Add signal callback and POLLPRI support

2020-06-24 Thread Deepak Kumar Singh
From: 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: Deepak Kumar Singh 
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 43ceac0..50a02fb 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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



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

2020-06-24 Thread Deepak Kumar Singh
Some transports like Glink support the state notifications between
clients using signals similar to serial protocol signals.
Local glink client drivers can send and receive signals to glink
clients running on remote processors.

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

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

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 91de940..e6eb5a1 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -283,6 +283,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 -ENXIO;
+
+   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 -ENXIO;
+
+   return ept->ops->set_signals(ept, set, clear);
+}
+EXPORT_SYMBOL(rpmsg_set_signals);
+
 /*
  * match a rpmsg channel with a channel info struct.
  * this is used to make sure we're not creating rpmsg devices for channels
@@ -468,6 +504,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..c4dbb47 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 channe

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

2020-06-24 Thread Deepak Kumar Singh
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: Deepak Kumar Singh 
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;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V7 1/4] rpmsg: glink: Use complete_all for open states

2020-06-24 Thread Deepak Kumar Singh
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: Deepak Kumar Singh 
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..d5114ab 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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V7 3/4] rpmsg: glink: Add support for rpmsg glink chrdev

2020-06-24 Thread Deepak Kumar Singh
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: Deepak Kumar Singh 
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 d5114ab..3a7f87c 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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V7 2/4] rpmsg: Guard against null endpoint ops in destroy

2020-06-24 Thread Deepak Kumar Singh
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: Deepak Kumar Singh 
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 a6361ca..91de940 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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH V1 2/2] soc: qcom: smem: map only partitions used by local HOST

2020-06-09 Thread Deepak Kumar Singh
SMEM driver is IO mapping complete region and CPU is doing a speculative
read into a partition where local HOST does not have permission resulting
in a NOC error.

Map only those partitions which are accessibly to local HOST.

Signed-off-by: Deepak Kumar Singh 
---
 drivers/soc/qcom/smem.c | 226 +++-
 1 file changed, 167 insertions(+), 59 deletions(-)

diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index c1bd310..4a152d6 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -193,6 +193,19 @@ struct smem_partition_header {
__le32 offset_free_cached;
__le32 reserved[3];
 };
+/**
+ * struct smem_partition_desc - descriptor for partition
+ * @virt_base: starting virtual address of partition
+ * @phys_base: starting physical address of partition
+ * @cacheline: alignment for "cached" entries
+ * @size:  size of partition
+ */
+struct smem_partition_desc {
+   void __iomem *virt_base;
+   u32 phys_base;
+   u32 cacheline;
+   u32 size;
+};
 
 static const u8 SMEM_PART_MAGIC[] = { 0x24, 0x50, 0x52, 0x54 };
 
@@ -249,9 +262,9 @@ struct smem_region {
  * struct qcom_smem - device data for the smem device
  * @dev:   device pointer
  * @hwlock:reference to a hwspinlock
- * @global_partition_entry: pointer to global partition entry when in use
- * @ptable_entries: list of pointers to partitions table entry of current
- * processor/host
+ * @ptable_base: virtual base of partition table
+ * @global_partition_desc: descriptor for global partition when in use
+ * @partition_desc: list of partition descriptor of current processor/host
  * @item_count: max accepted item number
  * @num_regions: number of @regions
  * @regions:   list of the memory regions defining the shared memory
@@ -261,9 +274,11 @@ struct qcom_smem {
 
struct hwspinlock *hwlock;
 
-   struct smem_ptable_entry *global_partition_entry;
-   struct smem_ptable_entry *ptable_entries[SMEM_HOST_COUNT];
u32 item_count;
+   struct smem_ptable *ptable_base;
+   struct smem_partition_desc global_partition_desc;
+   struct smem_partition_desc partition_desc[SMEM_HOST_COUNT];
+
struct platform_device *socinfo;
 
unsigned num_regions;
@@ -276,12 +291,6 @@ static struct qcom_smem *__smem;
 /* Timeout (ms) for the trylock of remote spinlocks */
 #define HWSPINLOCK_TIMEOUT 1000
 
-static struct smem_partition_header *
-ptable_entry_to_phdr(struct smem_ptable_entry *entry)
-{
-   return __smem->regions[0].virt_base + le32_to_cpu(entry->offset);
-}
-
 static struct smem_private_entry *
 phdr_to_last_uncached_entry(struct smem_partition_header *phdr)
 {
@@ -348,7 +357,7 @@ static void *cached_entry_to_item(struct smem_private_entry 
*e)
 }
 
 static int qcom_smem_alloc_private(struct qcom_smem *smem,
-  struct smem_ptable_entry *entry,
+  struct smem_partition_desc *p_desc,
   unsigned item,
   size_t size)
 {
@@ -358,8 +367,8 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
void *cached;
void *p_end;
 
-   phdr = ptable_entry_to_phdr(entry);
-   p_end = (void *)phdr + le32_to_cpu(entry->size);
+   phdr = p_desc->virt_base;
+   p_end = (void *)phdr + p_desc->size;
 
hdr = phdr_to_first_uncached_entry(phdr);
end = phdr_to_last_uncached_entry(phdr);
@@ -452,7 +461,7 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
  */
 int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
 {
-   struct smem_ptable_entry *entry;
+   struct smem_partition_desc *p_desc;
unsigned long flags;
int ret;
 
@@ -474,12 +483,12 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t 
size)
if (ret)
return ret;
 
-   if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
-   entry = __smem->ptable_entries[host];
-   ret = qcom_smem_alloc_private(__smem, entry, item, size);
-   } else if (__smem->global_partition_entry) {
-   entry = __smem->global_partition_entry;
-   ret = qcom_smem_alloc_private(__smem, entry, item, size);
+   if (host < SMEM_HOST_COUNT && __smem->partition_desc[host].virt_base) {
+   p_desc = &__smem->partition_desc[host];
+   ret = qcom_smem_alloc_private(__smem, p_desc, item, size);
+   } else if (__smem->global_partition_desc.virt_base) {
+   p_desc = &__smem->global_partition_desc;
+   ret = qcom_smem_alloc_private(__smem, p_desc, item, size);
} else {
ret = qcom_smem_alloc_global(__smem, item, size);
}
@@ -530,22 +539,20 @@ static void *qcom_smem_get_global(struct q

[PATCH V1 1/2] soc: qcom: smem: validate fields of shared structures

2020-06-09 Thread Deepak Kumar Singh
Structures in shared memory that can be modified by remote
processors may have untrusted values, they should be validated
before use.

Adding proper validation before using fields of shared
structures.

Signed-off-by: Deepak Kumar Singh 
---
 drivers/soc/qcom/smem.c | 194 +---
 1 file changed, 133 insertions(+), 61 deletions(-)

diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 28c19bc..c1bd310 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -249,11 +249,9 @@ struct smem_region {
  * struct qcom_smem - device data for the smem device
  * @dev:   device pointer
  * @hwlock:reference to a hwspinlock
- * @global_partition:  pointer to global partition when in use
- * @global_cacheline:  cacheline size for global partition
- * @partitions:list of pointers to partitions affecting the current
+ * @global_partition_entry: pointer to global partition entry when in use
+ * @ptable_entries: list of pointers to partitions table entry of current
  * processor/host
- * @cacheline: list of cacheline sizes for each host
  * @item_count: max accepted item number
  * @num_regions: number of @regions
  * @regions:   list of the memory regions defining the shared memory
@@ -263,10 +261,8 @@ struct qcom_smem {
 
struct hwspinlock *hwlock;
 
-   struct smem_partition_header *global_partition;
-   size_t global_cacheline;
-   struct smem_partition_header *partitions[SMEM_HOST_COUNT];
-   size_t cacheline[SMEM_HOST_COUNT];
+   struct smem_ptable_entry *global_partition_entry;
+   struct smem_ptable_entry *ptable_entries[SMEM_HOST_COUNT];
u32 item_count;
struct platform_device *socinfo;
 
@@ -274,7 +270,19 @@ struct qcom_smem {
struct smem_region regions[];
 };
 
-static void *
+/* Pointer to the one and only smem handle */
+static struct qcom_smem *__smem;
+
+/* Timeout (ms) for the trylock of remote spinlocks */
+#define HWSPINLOCK_TIMEOUT 1000
+
+static struct smem_partition_header *
+ptable_entry_to_phdr(struct smem_ptable_entry *entry)
+{
+   return __smem->regions[0].virt_base + le32_to_cpu(entry->offset);
+}
+
+static struct smem_private_entry *
 phdr_to_last_uncached_entry(struct smem_partition_header *phdr)
 {
void *p = phdr;
@@ -339,25 +347,27 @@ static void *cached_entry_to_item(struct 
smem_private_entry *e)
return p - le32_to_cpu(e->size);
 }
 
-/* Pointer to the one and only smem handle */
-static struct qcom_smem *__smem;
-
-/* Timeout (ms) for the trylock of remote spinlocks */
-#define HWSPINLOCK_TIMEOUT 1000
-
 static int qcom_smem_alloc_private(struct qcom_smem *smem,
-  struct smem_partition_header *phdr,
+  struct smem_ptable_entry *entry,
   unsigned item,
   size_t size)
 {
struct smem_private_entry *hdr, *end;
+   struct smem_partition_header *phdr;
size_t alloc_size;
void *cached;
+   void *p_end;
+
+   phdr = ptable_entry_to_phdr(entry);
+   p_end = (void *)phdr + le32_to_cpu(entry->size);
 
hdr = phdr_to_first_uncached_entry(phdr);
end = phdr_to_last_uncached_entry(phdr);
cached = phdr_to_last_cached_entry(phdr);
 
+   if (WARN_ON((void *)end > p_end || (void *)cached > p_end))
+   return -EINVAL;
+
while (hdr < end) {
if (hdr->canary != SMEM_PRIVATE_CANARY)
goto bad_canary;
@@ -366,6 +376,8 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
 
hdr = uncached_entry_next(hdr);
}
+   if (WARN_ON((void *)hdr > p_end))
+   return -EINVAL;
 
/* Check that we don't grow into the cached region */
alloc_size = sizeof(*hdr) + ALIGN(size, 8);
@@ -440,7 +452,7 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
  */
 int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
 {
-   struct smem_partition_header *phdr;
+   struct smem_ptable_entry *entry;
unsigned long flags;
int ret;
 
@@ -462,12 +474,12 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t 
size)
if (ret)
return ret;
 
-   if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
-   phdr = __smem->partitions[host];
-   ret = qcom_smem_alloc_private(__smem, phdr, item, size);
-   } else if (__smem->global_partition) {
-   phdr = __smem->global_partition;
-   ret = qcom_smem_alloc_private(__smem, phdr, item, size);
+   if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+   entry = __smem->ptable_entries[host];
+   ret = qcom_smem_alloc_private(__smem, entry, item, size);
+   } else if (__smem->global_par