Signaling api support in glink/rpmsg clients
v5 cover Signaling api support in glink/rpmsg clients
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 [email protected] 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(-)
Signature · 2 lines
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
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.
--- drivers/rpmsg/rpmsg_core.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/rpmsg/rpmsg_internal.h | 5 +++++ include/linux/rpmsg.h | 27 +++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)
drivers/rpmsg/rpmsg_core.c +40 -0
@@ -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);
drivers/rpmsg/rpmsg_internal.h +5 -0
@@ -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);
include/linux/rpmsg.h +27 -0
@@ -2,6 +2,7 @@/* * Remote processor messaging * +* Copyright (c) 2018 The Linux Foundation. * Copyright (C) 2011 Texas Instruments, Inc. * Copyright (C) 2011 Google, Inc. * All rights reserved.
@@ -60,6 +61,7 @@ struct rpmsg_device { };typedef int (*rpmsg_rx_cb_t )(struct rpmsg_device *,void *,int ,void *,u32 ); +typedef int (*rpmsg_rx_sig_t )(struct rpmsg_device *,void *,u32 ,u32 );/** * struct rpmsg_endpoint - binds a local rpmsg address to its user
@@ -67,6 +69,7 @@ typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);* @refcount: when this drops to zero, the ept is deallocated * @cb: rx callback handler * @cb_lock: must be taken before accessing/changing @cb +* @sig_cb: rx serial signal handler * @addr: local rpmsg address * @priv: private data for the driver's use *
@@ -89,6 +92,7 @@ struct rpmsg_endpoint {struct kref refcount;rpmsg_rx_cb_t cb;struct mutex cb_lock; +rpmsg_rx_sig_t sig_cb;u32 addr;void *priv;
@@ -102,6 +106,7 @@ struct rpmsg_endpoint {* @probe: invoked when a matching rpmsg channel (i.e. device) is found * @remove: invoked when the rpmsg channel is removed * @callback: invoked when an inbound message is received on the channel +* @signals: invoked when a serial signal change is received on the channel */ struct rpmsg_driver {struct device_driver drv;
@@ -109,6 +114,8 @@ struct rpmsg_driver {int (*probe)(struct rpmsg_device *dev);void (*remove)(struct rpmsg_device *dev);int (*callback)(struct rpmsg_device *,void *,int ,void *,u32 ); +int (*signals)(struct rpmsg_device *rpdev, +void *priv,u32 old,u32 new); };#if IS_ENABLED (CONFIG_RPMSG )
@@ -135,6 +142,9 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,__poll_t rpmsg_poll (struct rpmsg_endpoint *ept,struct file *filp,poll_table *wait); +int rpmsg_get_signals (struct rpmsg_endpoint *ept); +int rpmsg_set_signals (struct rpmsg_endpoint *ept,u32 set,u32 clear); +#else static inline int register_rpmsg_device (struct rpmsg_device *dev)
@@ -242,6 +252,23 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, return 0; } +static inline int rpmsg_get_signals (struct rpmsg_endpoint *ept) +{ +/* This shouldn't be possible */ +WARN_ON (1 ); + +return -ENXIO ; +} + +static inline int rpmsg_set_signals (struct rpmsg_endpoint *ept, +u32 set,u32 clear) +{ +/* This shouldn't be possible */ +WARN_ON (1 ); + +return -ENXIO ; +} +#endif /* IS_ENABLED(CONFIG_RPMSG) */ /* use a macro to avoid include chaining to get THIS_MODULE */
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH V6 1/4] rpmsg: core: Add signal API support
Please ignore V6 patch set for rpmsg: core: Add signal API support.
Wrongly pushed.
Quoted 192 lines · 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 <[email protected]>Signed-off-by Deepak Kumar Singh <[email protected]>Signed-off-by Arun Kumar Neelakantam <[email protected]>--- drivers/rpmsg/rpmsg_core.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/rpmsg/rpmsg_internal.h | 5 +++++ include/linux/rpmsg.h | 27 +++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)drivers/rpmsg/rpmsg_core.c +40
-0@@ -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);drivers/rpmsg/rpmsg_internal.h +5
-0@@ -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);include/linux/rpmsg.h +27
-0@@ -2,6 +2,7 @@/* * Remote processor messaging * +* Copyright (c) 2018 The Linux Foundation. * Copyright (C) 2011 Texas Instruments, Inc. * Copyright (C) 2011 Google, Inc. * All rights reserved. @@ -60,6 +61,7 @@ struct rpmsg_device { };typedef int (*rpmsg_rx_cb_t )(struct rpmsg_device *,void *,int ,void *,u32 ); +typedef int (*rpmsg_rx_sig_t )(struct rpmsg_device *,void *,u32 ,u32 );/** * struct rpmsg_endpoint - binds a local rpmsg address to its user @@ -67,6 +69,7 @@ typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);* @refcount: when this drops to zero, the ept is deallocated * @cb: rx callback handler * @cb_lock: must be taken before accessing/changing @cb +* @sig_cb: rx serial signal handler * @addr: local rpmsg address * @priv: private data for the driver's use * @@ -89,6 +92,7 @@ struct rpmsg_endpoint {struct kref refcount;rpmsg_rx_cb_t cb;struct mutex cb_lock; +rpmsg_rx_sig_t sig_cb;u32 addr;void *priv;@@ -102,6 +106,7 @@ struct rpmsg_endpoint {* @probe: invoked when a matching rpmsg channel (i.e. device) is found * @remove: invoked when the rpmsg channel is removed * @callback: invoked when an inbound message is received on the channel +* @signals: invoked when a serial signal change is received on the channel */ struct rpmsg_driver {struct device_driver drv;@@ -109,6 +114,8 @@ struct rpmsg_driver {int (*probe)(struct rpmsg_device *dev);void (*remove)(struct rpmsg_device *dev);int (*callback)(struct rpmsg_device *,void *,int ,void *,u32 ); +int (*signals)(struct rpmsg_device *rpdev, +void *priv,u32 old,u32 new); };#if IS_ENABLED (CONFIG_RPMSG )@@ -135,6 +142,9 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,__poll_t rpmsg_poll (struct rpmsg_endpoint *ept,struct file *filp,poll_table *wait); +int rpmsg_get_signals (struct rpmsg_endpoint *ept); +int rpmsg_set_signals (struct rpmsg_endpoint *ept,u32 set,u32 clear); +#else static inline int register_rpmsg_device (struct rpmsg_device *dev)@@ -242,6 +252,23 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, return 0; } +static inline int rpmsg_get_signals (struct rpmsg_endpoint *ept) +{ +/* This shouldn't be possible */ +WARN_ON (1 ); + +return -ENXIO ; +} + +static inline int rpmsg_set_signals (struct rpmsg_endpoint *ept, +u32 set,u32 clear) +{ +/* This shouldn't be possible */ +WARN_ON (1 ); + +return -ENXIO ; +} +#endif /* IS_ENABLED(CONFIG_RPMSG) */ /* use a macro to avoid include chaining to get THIS_MODULE */
PATCH v6 2/4 rpmsg: glink: Add support to handle signals command
In reply to Deepak Kumar SinghFrom: Arun Kumar Neelakantam <[email protected]>
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.
--- drivers/rpmsg/qcom_glink_native.c | 125 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+)
drivers/rpmsg/qcom_glink_native.c +125 -0
@@ -17,6 +17,7 @@#include <linux/rpmsg.h> #include <linux/sizes.h> #include <linux/slab.h> +#include <linux/termios.h> #include <linux/workqueue.h> #include <linux/mailbox_client.h>
@@ -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_REUSE 14 +#define RPM_CMD_SIGNALS 15#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, &msg,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 (&glink->idr_lock, flags); + channel =idr_find (&glink->rcids, rcid); +spin_unlock_irqrestore (&glink->idr_lock, flags); +if (!channel) { +dev_err (glink->dev,"signal for non-existing channel\n" ); +return -EINVAL ; + } + + 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 (glink,ALIGN (sizeof (msg),8 )); +break ;default :dev_err (glink->dev,"unhandled rx cmd: %d\n" , cmd); ret = -EINVAL ;
@@ -1332,6 +1419,42 @@ static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len)return __qcom_glink_send (channel, data, len, false); } +static int qcom_glink_get_sigs (struct rpmsg_endpoint *ept) +{ +struct glink_channel *channel =to_glink_channel (ept); + +return channel->rsigs; +} + +static int qcom_glink_set_sigs (struct rpmsg_endpoint *ept,u32 set,u32 clear) +{ +struct glink_channel *channel =to_glink_channel (ept); +struct qcom_glink *glink = channel->glink; +u32 sigs = channel->lsigs; + +if (set &TIOCM_DTR ) + sigs |=TIOCM_DTR ; +if (set &TIOCM_RTS ) + sigs |=TIOCM_RTS ; +if (set &TIOCM_CD ) + sigs |=TIOCM_CD ; +if (set &TIOCM_RI ) + sigs |=TIOCM_RI ; + +if (clear &TIOCM_DTR ) + sigs &= ~TIOCM_DTR ; +if (clear &TIOCM_RTS ) + sigs &= ~TIOCM_RTS ; +if (clear &TIOCM_CD ) + sigs &= ~TIOCM_CD ; +if (clear &TIOCM_RI ) + sigs &= ~TIOCM_RI ; + + channel->lsigs = sigs; + +return qcom_glink_send_signals (glink, channel, sigs); +} +/* * Finds the device_node for the glink child interested in this channel. */
@@ -1365,6 +1488,8 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops = { .destroy_ept = qcom_glink_destroy_ept, .send = qcom_glink_send, .trysend = qcom_glink_trysend, + .get_signals = qcom_glink_get_sigs, + .set_signals = qcom_glink_set_sigs, };static void qcom_glink_rpdev_release (struct device *dev)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH V6 2/4] rpmsg: glink: Add support to handle signals command
Please ignore this instance. Wrongly pushed.
Quoted 203 lines · Deepak Kumar Singh
From: Arun Kumar Neelakantam <[email protected]>
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 <[email protected]>Signed-off-by Deepak Kumar Singh <[email protected]>Signed-off-by Arun Kumar Neelakantam <[email protected]>--- drivers/rpmsg/qcom_glink_native.c | 125 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+)drivers/rpmsg/qcom_glink_native.c +125
-0@@ -17,6 +17,7 @@#include <linux/rpmsg.h> #include <linux/sizes.h> #include <linux/slab.h> +#include <linux/termios.h> #include <linux/workqueue.h> #include <linux/mailbox_client.h> @@ -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_REUSE 14 +#define RPM_CMD_SIGNALS 15#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, &msg,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 (&glink->idr_lock, flags); + channel =idr_find (&glink->rcids, rcid); +spin_unlock_irqrestore (&glink->idr_lock, flags); +if (!channel) { +dev_err (glink->dev,"signal for non-existing channel\n" ); +return -EINVAL ; + } + + 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 (glink,ALIGN (sizeof (msg),8 )); +break ;default :dev_err (glink->dev,"unhandled rx cmd: %d\n" , cmd); ret = -EINVAL ;@@ -1332,6 +1419,42 @@ static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len)return __qcom_glink_send (channel, data, len, false); } +static int qcom_glink_get_sigs (struct rpmsg_endpoint *ept) +{ +struct glink_channel *channel =to_glink_channel (ept); + +return channel->rsigs; +} + +static int qcom_glink_set_sigs (struct rpmsg_endpoint *ept,u32 set,u32 clear) +{ +struct glink_channel *channel =to_glink_channel (ept); +struct qcom_glink *glink = channel->glink; +u32 sigs = channel->lsigs; + +if (set &TIOCM_DTR ) + sigs |=TIOCM_DTR ; +if (set &TIOCM_RTS ) + sigs |=TIOCM_RTS ; +if (set &TIOCM_CD ) + sigs |=TIOCM_CD ; +if (set &TIOCM_RI ) + sigs |=TIOCM_RI ; + +if (clear &TIOCM_DTR ) + sigs &= ~TIOCM_DTR ; +if (clear &TIOCM_RTS ) + sigs &= ~TIOCM_RTS ; +if (clear &TIOCM_CD ) + sigs &= ~TIOCM_CD ; +if (clear &TIOCM_RI ) + sigs &= ~TIOCM_RI ; + + channel->lsigs = sigs; + +return qcom_glink_send_signals (glink, channel, sigs); +} +/* * Finds the device_node for the glink child interested in this channel. */ @@ -1365,6 +1488,8 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops = { .destroy_ept = qcom_glink_destroy_ept, .send = qcom_glink_send, .trysend = qcom_glink_trysend, + .get_signals = qcom_glink_get_sigs, + .set_signals = qcom_glink_set_sigs, };static void qcom_glink_rpdev_release (struct device *dev)
PATCH v6 3/4 rpmsg: char: Add TIOCMGET/TIOCMSET ioctl support
In reply to Deepak Kumar SinghFrom: Arun Kumar Neelakantam <[email protected]>
Add TICOMGET and TIOCMSET ioctl support for rpmsg char device nodes to get/set the low level transport signals.
--- drivers/rpmsg/rpmsg_char.c | 54 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-)
drivers/rpmsg/rpmsg_char.c +51 -3
@@ -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 <[email protected]> * Copyright (c) 2012, PetaLogix
@@ -19,6 +20,7 @@#include <linux/rpmsg.h> #include <linux/skbuff.h> #include <linux/slab.h> +#include <linux/termios.h> #include <linux/uaccess.h> #include <uapi/linux/rpmsg.h>
@@ -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 (&eptdev->dev,NULL ); +break ; +default : + ret = -EINVAL ; + } -return rpmsg_eptdev_destroy (&eptdev->dev,NULL ); +return ret; }static const struct file_operations rpmsg_eptdev_fops = {
Signature · 2 lines
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
In reply to Deepak Kumar SinghFrom: Arun Kumar Neelakantam <[email protected]>
Register a callback to get the signal notifications from rpmsg and send POLLPRI mask to indicate the signal change in POLL system call.
--- drivers/rpmsg/rpmsg_char.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
drivers/rpmsg/rpmsg_char.c +22 -0
@@ -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 (&eptdev->readq); +return 0 ; +} + +static int rpmsg_eptdev_open (struct inode *inode,struct file *filp) {struct rpmsg_eptdev *eptdev =cdev_to_eptdev (inode->i_cdev);
@@ -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 (&eptdev->ept_lock); + eptdev->sig_pending = false;/* Discard all SKBs */ skb_queue_purge (&eptdev->queue);
@@ -266,6 +284,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait)if (!skb_queue_empty (&eptdev->queue)) mask |=EPOLLIN |EPOLLRDNORM ; +if (eptdev->sig_pending) + mask |=EPOLLPRI ; + mask |=rpmsg_poll (eptdev->ept, filp, wait);return mask;
@@ -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);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Mathieu Poirier
maintainerHi Deepak,
Quoted 12 lines · 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 [email protected] Fixed all the trivial review comments.Signal conversion to and from native signal as done in patch V4,2/4 is intentional.
Quoted 7 lines
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 supportDeepak 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
Quoted 12 lines
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(-)Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Quoted 28 lines · Mathieu Poirier
Hi Deepak,
Quoted 12 lines · 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 [email protected] Fixed all the trivial review comments.Signal conversion to and from native signal as done in patch V4,2/4 is intentional.
Quoted 7 lines
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 supportDeepak Kumar Singh (1):
rpmsg: core: Add signal API supportI'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?
Quoted 6 lines
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.
Quoted 11 lines
Quoted 11 lines
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(-)Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Mathieu Poirier
maintainerQuoted 34 lines · Deepak Kumar Singh
Quoted 31 lines · Mathieu Poirier
Hi Deepak,
Quoted 12 lines · 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 [email protected] Fixed all the trivial review comments.Signal conversion to and from native signal as done in patch V4,2/4 is intentional.
Quoted 7 lines
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 supportDeepak Kumar Singh (1):
rpmsg: core: Add signal API supportI'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.
Quoted 6 lines
Quoted 3 lines
Thanks,
MathieuMistakenly i forgot to update label for cover letter to V6.
I have uploaded patch set V7 with updated cover letter.
Thank you for doing that - I have added your set to my list of patches to review. Note that I have a fair amount of patches to go over lately and as such getting to yours will take some time.
Regards,
Mathieu
Quoted 17 lines
There is no change in patches.
Quoted 11 lines
Quoted 11 lines
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
v3 cover soc: qcom: aoss: Expose send for generic usecase
[Change from V2]
Remove devm memory allocation
Use refcount for qmp handle
Update qmp_get/qmp_put/qmp_remove function with refcount logic
Deepak Kumar Singh (2):
soc: qcom: aoss: Expose send for generic usecase
soc: qcom: aoss: Add debugfs entry
drivers/soc/qcom/qcom_aoss.c | 109 ++++++++++++++++++++++++++++++++++++- include/linux/soc/qcom/qcom_aoss.h | 33 +++++++++++ 2 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 include/linux/soc/qcom/qcom_aoss.h
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v3 1/2 soc: qcom: aoss: Expose send for generic usecase
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.
--- drivers/soc/qcom/qcom_aoss.c | 70 ++++++++++++++++++++++++++++++++++++-- include/linux/soc/qcom/qcom_aoss.h | 33 ++++++++++++++++++ 2 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 include/linux/soc/qcom/qcom_aoss.h
drivers/soc/qcom/qcom_aoss.c +68 -2
@@ -8,10 +8,12 @@#include <linux/io.h> #include <linux/mailbox_client.h> #include <linux/module.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/thermal.h> #include <linux/slab.h> +#include <linux/soc/qcom/qcom_aoss.h> #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,8 @@ struct qmp {size_t offset;size_t size; +atomic_t orphan; +struct kref refcount;wait_queue_head_t event;
@@ -223,11 +228,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 (&qmp->orphan)) +return -EINVAL ; +if (WARN_ON (len +sizeof (u32) > qmp->size))return -EINVAL ;
@@ -261,6 +272,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 +527,54 @@ 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); +of_node_put (np); +if (!pdev) +return ERR_PTR (-EINVAL ); + + qmp =platform_get_drvdata (pdev); +platform_device_put (pdev); + +if (qmp) +kref_get (&qmp->refcount); + +return qmp ? qmp :ERR_PTR (-EPROBE_DEFER ); +} +EXPORT_SYMBOL (qmp_get); + +static void qmp_handle_release (struct kref *ref) +{ + struct qmp *qmp = container_of(ref, struct qmp, refcount); + +kfree (qmp); +} + +void qmp_put (struct qmp *qmp) +{ +if (!IS_ERR_OR_NULL (qmp)) +kref_put (&qmp->refcount, qmp_handle_release); +} +EXPORT_SYMBOL (qmp_put); +static int qmp_probe (struct platform_device *pdev) {struct resource *res;
@@ -522,13 +582,14 @@ static int qmp_probe(struct platform_device *pdev)int irq;int ret; - qmp =devm_kzalloc (&pdev->dev,sizeof (*qmp),GFP_KERNEL ); + qmp =kzalloc (sizeof (*qmp),GFP_KERNEL );if (!qmp)return -ENOMEM ; qmp->dev = &pdev->dev;init_waitqueue_head (&qmp->event);mutex_init (&qmp->tx_lock); +kref_init (&qmp->refcount); res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); qmp->msgram =devm_ioremap_resource (&pdev->dev, res);
@@ -569,6 +630,8 @@ static int qmp_probe(struct platform_device *pdev)platform_set_drvdata (pdev, qmp); +atomic_set (&qmp->orphan,0 ); +return 0 ; err_remove_qdss_clk:
@@ -577,6 +640,7 @@ static int qmp_probe(struct platform_device *pdev)qmp_close (qmp); err_free_mbox:mbox_free_channel (qmp->mbox_chan); +kfree (qmp);return ret; }
@@ -590,7 +654,9 @@ static int qmp_remove(struct platform_device *pdev)qmp_cooling_devices_remove (qmp);qmp_close (qmp); +atomic_set (&qmp->orphan,1 );mbox_free_channel (qmp->mbox_chan); +kref_put (&qmp->refcount, qmp_handle_release);return 0 ; }
include/linux/soc/qcom/qcom_aoss.h new file +33 -0
@@ -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 <linux/err.h> +#include <linux/device.h> + +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
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH V3 1/2] soc: qcom: aoss: Expose send for generic usecase
Quoted 6 lines · 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 <[email protected]>Signed-off-by Deepak Kumar Singh <[email protected]>
Regards,
Bjorn
Quoted 208 lines
--- drivers/soc/qcom/qcom_aoss.c | 70 ++++++++++++++++++++++++++++++++++++-- include/linux/soc/qcom/qcom_aoss.h | 33 ++++++++++++++++++ 2 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 include/linux/soc/qcom/qcom_aoss.hdrivers/soc/qcom/qcom_aoss.c +68
-2@@ -8,10 +8,12 @@#include <linux/io.h> #include <linux/mailbox_client.h> #include <linux/module.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/thermal.h> #include <linux/slab.h> +#include <linux/soc/qcom/qcom_aoss.h> #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,8 @@ struct qmp {size_t offset;size_t size; +atomic_t orphan; +struct kref refcount;wait_queue_head_t event;@@ -223,11 +228,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 (&qmp->orphan)) +return -EINVAL ; +if (WARN_ON (len +sizeof (u32) > qmp->size))return -EINVAL ;@@ -261,6 +272,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 +527,54 @@ 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); +of_node_put (np); +if (!pdev) +return ERR_PTR (-EINVAL ); + + qmp =platform_get_drvdata (pdev); +platform_device_put (pdev); + +if (qmp) +kref_get (&qmp->refcount); + +return qmp ? qmp :ERR_PTR (-EPROBE_DEFER ); +} +EXPORT_SYMBOL (qmp_get); + +static void qmp_handle_release (struct kref *ref) +{ + struct qmp *qmp = container_of(ref, struct qmp, refcount); + +kfree (qmp); +} + +void qmp_put (struct qmp *qmp) +{ +if (!IS_ERR_OR_NULL (qmp)) +kref_put (&qmp->refcount, qmp_handle_release); +} +EXPORT_SYMBOL (qmp_put); +static int qmp_probe (struct platform_device *pdev) {struct resource *res;@@ -522,13 +582,14 @@ static int qmp_probe(struct platform_device *pdev)int irq;int ret; - qmp =devm_kzalloc (&pdev->dev,sizeof (*qmp),GFP_KERNEL ); + qmp =kzalloc (sizeof (*qmp),GFP_KERNEL );if (!qmp)return -ENOMEM ; qmp->dev = &pdev->dev;init_waitqueue_head (&qmp->event);mutex_init (&qmp->tx_lock); +kref_init (&qmp->refcount); res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); qmp->msgram =devm_ioremap_resource (&pdev->dev, res);@@ -569,6 +630,8 @@ static int qmp_probe(struct platform_device *pdev)platform_set_drvdata (pdev, qmp); +atomic_set (&qmp->orphan,0 ); +return 0 ; err_remove_qdss_clk:@@ -577,6 +640,7 @@ static int qmp_probe(struct platform_device *pdev)qmp_close (qmp); err_free_mbox:mbox_free_channel (qmp->mbox_chan); +kfree (qmp);return ret; }@@ -590,7 +654,9 @@ static int qmp_remove(struct platform_device *pdev)qmp_cooling_devices_remove (qmp);qmp_close (qmp); +atomic_set (&qmp->orphan,1 );mbox_free_channel (qmp->mbox_chan); +kref_put (&qmp->refcount, qmp_handle_release);return 0 ; }include/linux/soc/qcom/qcom_aoss.h new file +33
-0@@ -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 <linux/err.h> +#include <linux/device.h> + +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 Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH V3 1/2] soc: qcom: aoss: Expose send for generic usecase
In reply to Deepak Kumar SinghHey Deepak,
Thanks for the patch!
Quoted 190 lines · 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 <[email protected]>Signed-off-by Deepak Kumar Singh <[email protected]>--- drivers/soc/qcom/qcom_aoss.c | 70 ++++++++++++++++++++++++++++++++++++-- include/linux/soc/qcom/qcom_aoss.h | 33 ++++++++++++++++++ 2 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 include/linux/soc/qcom/qcom_aoss.hdrivers/soc/qcom/qcom_aoss.c +3
-0@@ -8,10 +8,12 @@#include <linux/io.h> #include <linux/mailbox_client.h> #include <linux/module.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/thermal.h> #include <linux/slab.h> +#include <linux/soc/qcom/qcom_aoss.h> #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
drivers/soc/qcom/qcom_aoss.c +10
-1@@ -76,6 +79,8 @@ struct qmp {size_t offset;size_t size; +atomic_t orphan; +struct kref refcount;wait_queue_head_t event;@@ -223,11 +228,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 (&qmp->orphan)) +return -EINVAL ; +if (WARN_ON (len +sizeof (u32) > qmp->size))return -EINVAL ;@@ -261,6 +272,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){
drivers/soc/qcom/qcom_aoss.c +48
-0@@ -515,6 +527,54 @@ 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); +of_node_put (np); +if (!pdev) +return ERR_PTR (-EINVAL ); + + qmp =platform_get_drvdata (pdev); +platform_device_put (pdev); + +if (qmp) +kref_get (&qmp->refcount); + +return qmp ? qmp :ERR_PTR (-EPROBE_DEFER ); +} +EXPORT_SYMBOL (qmp_get); + +static void qmp_handle_release (struct kref *ref) +{ + struct qmp *qmp = container_of(ref, struct qmp, refcount); + +kfree (qmp); +} + +void qmp_put (struct qmp *qmp) +{ +if (!IS_ERR_OR_NULL (qmp)) +kref_put (&qmp->refcount, qmp_handle_release); +} +EXPORT_SYMBOL (qmp_put); +static int qmp_probe (struct platform_device *pdev) {drivers/soc/qcom/qcom_aoss.c +2
-1struct resource *res;@@ -522,13 +582,14 @@ static int qmp_probe(struct platform_device *pdev)int irq;int ret; - qmp =devm_kzalloc (&pdev->dev,sizeof (*qmp),GFP_KERNEL ); + qmp =kzalloc (sizeof (*qmp),GFP_KERNEL );if (!qmp)return -ENOMEM ; qmp->dev = &pdev->dev;init_waitqueue_head (&qmp->event);mutex_init (&qmp->tx_lock); +kref_init (&qmp->refcount); res =platform_get_resource (pdev,IORESOURCE_MEM ,0 );drivers/soc/qcom/qcom_aoss.c +5
-0qmp->msgram =devm_ioremap_resource (&pdev->dev, res);@@ -569,6 +630,8 @@ static int qmp_probe(struct platform_device *pdev)platform_set_drvdata (pdev, qmp); +atomic_set (&qmp->orphan,0 ); +return 0 ; err_remove_qdss_clk:@@ -577,6 +640,7 @@ static int qmp_probe(struct platform_device *pdev)qmp_close (qmp); err_free_mbox:mbox_free_channel (qmp->mbox_chan); +kfree (qmp);return ret; }@@ -590,7 +654,9 @@ static int qmp_remove(struct platform_device *pdev)qmp_cooling_devices_remove (qmp);qmp_close (qmp); +atomic_set (&qmp->orphan,1 );mbox_free_channel (qmp->mbox_chan); +kref_put (&qmp->refcount, qmp_handle_release);return 0 ; }include/linux/soc/qcom/qcom_aoss.h new file +7
-0@@ -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/linux/soc/qcom/qcom_aoss.h line 17
Quoted 10 lines
include/linux/soc/qcom/qcom_aoss.h new file +10
-0+ +#include <linux/err.h> +#include <linux/device.h> + +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);
missed adding qmp_put.
include/linux/soc/qcom/qcom_aoss.h line 29
Quoted 13 lines
include/linux/soc/qcom/qcom_aoss.h new file +4
-0+ +#else + +static inline int qmp_send(struct qmp *qmp, const void *data, size_tlen)
include/linux/soc/qcom/qcom_aoss.h new file +8
-0+{ +return -ENODEV ; +} + +static inline struct qmp *qmp_get (struct device *dev) +{ +return ERR_PTR (-ENODEV ); +}
missed adding qmp_put.
Quoted 4 lines
include/linux/soc/qcom/qcom_aoss.h new file +4
-0+ +#endif + +#endif
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH v3 2/2 soc: qcom: aoss: Add debugfs entry
In reply to Deepak Kumar SinghIt 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.
--- drivers/soc/qcom/qcom_aoss.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
drivers/soc/qcom/qcom_aoss.c +39 -0
@@ -4,6 +4,7 @@*/ #include <dt-bindings/power/qcom-aoss-qmp.h> #include <linux/clk-provider.h> +#include <linux/debugfs.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/mailbox_client.h>
@@ -89,6 +90,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 {
@@ -575,6 +579,32 @@ void qmp_put(struct qmp *qmp) }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 len; + + ret =copy_from_user (buf, userstr, len); +if (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;
@@ -632,6 +662,11 @@ static int qmp_probe(struct platform_device *pdev)atomic_set (&qmp->orphan,0 ); +#if IS_ENABLED (CONFIG_DEBUG_FS ) + qmp->debugfs_file =debugfs_create_file ("aoss_send_message" ,0220 ,NULL , + qmp, &aoss_dbg_fops); +#endif /* CONFIG_DEBUG_FS */ +return 0 ; err_remove_qdss_clk:
@@ -649,6 +684,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);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project