rpmsg: glink: Update signals interface

Update the serial signal interface for rpmsg and glink to match the
android common kernel abi.

Change ABI whitelist to use renamed APIs for rpmsg_get/set_signals().

Change-Id: If531efa835b0bfb8405a5dfd265025b5c2754a61
Signed-off-by: Chris Lew <clew@codeaurora.org>
This commit is contained in:
Chris Lew 2020-07-22 16:19:24 -07:00
commit 790be8ba3d
7 changed files with 257 additions and 275 deletions

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016-2017, Linaro Ltd
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/idr.h>
@ -18,6 +18,7 @@
#include <linux/rpmsg.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/termios.h>
#include <linux/workqueue.h>
#include <linux/kthread.h>
#include <linux/mailbox_client.h>
@ -177,6 +178,8 @@ enum {
* @intent_req_result: Result of intent request
* @intent_req_comp: Status of intent request completion
* @intent_req_event: Waitqueue for @intent_req_comp
* @lsigs: local side signals
* @rsigs: remote side signals
*/
struct glink_channel {
struct rpmsg_endpoint ept;
@ -202,9 +205,6 @@ struct glink_channel {
int buf_offset;
int buf_size;
unsigned int lsigs;
unsigned int rsigs;
struct completion open_ack;
struct completion open_req;
@ -212,6 +212,9 @@ struct glink_channel {
bool intent_req_result;
atomic_t intent_req_comp;
wait_queue_head_t intent_req_event;
unsigned int lsigs;
unsigned int rsigs;
};
#define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
@ -236,6 +239,11 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;
#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 kthread_work *work);
static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@ -1089,7 +1097,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
}
/**
* qcom_glink_send_signals() - convert a signal cmd to wire format and transmit
* 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.
@ -1102,6 +1110,17 @@ static int qcom_glink_send_signals(struct qcom_glink *glink,
{
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);
@ -1126,12 +1145,25 @@ static int qcom_glink_handle_signals(struct qcom_glink *glink,
}
old = channel->rsigs;
/* convert signals from NATIVE to TIOCM */
if (signals & NATIVE_DTR_SIG)
signals |= TIOCM_DSR;
if (signals & NATIVE_CTS_SIG)
signals |= TIOCM_CTS;
if (signals & NATIVE_CD_SIG)
signals |= TIOCM_CD;
if (signals & NATIVE_RI_SIG)
signals |= TIOCM_RI;
signals &= 0x0fff;
channel->rsigs = signals;
if (channel->ept.sig_cb)
channel->ept.sig_cb(channel->ept.rpdev, old, channel->rsigs);
CH_INFO(channel, "old:%d new:%d\n", old, channel->rsigs);
if (channel->ept.sig_cb) {
channel->ept.sig_cb(channel->ept.rpdev, channel->ept.priv,
old, channel->rsigs);
}
return 0;
}
@ -1546,21 +1578,36 @@ static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len)
return __qcom_glink_send(channel, data, len, false);
}
static int qcom_glink_get_sigs(struct rpmsg_endpoint *ept,
u32 *lsigs, u32 *rsigs)
static int qcom_glink_get_sigs(struct rpmsg_endpoint *ept)
{
struct glink_channel *channel = to_glink_channel(ept);
*lsigs = channel->lsigs;
*rsigs = channel->rsigs;
return 0;
return channel->rsigs;
}
static int qcom_glink_set_sigs(struct rpmsg_endpoint *ept, u32 sigs)
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;
@ -1600,8 +1647,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_sigs = qcom_glink_get_sigs,
.set_sigs = qcom_glink_set_sigs,
.get_signals = qcom_glink_get_sigs,
.set_signals = qcom_glink_set_sigs,
};
static void qcom_glink_rpdev_release(struct device *dev)

View file

@ -4,7 +4,7 @@
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2011 Google, Inc.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*
* Ohad Ben-Cohen <ohad@wizery.com>
* Brian Swetland <swetland@google.com>
@ -285,40 +285,40 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
EXPORT_SYMBOL(rpmsg_trysend_offchannel);
/**
* rpmsg_get_sigs() - get the signals for this endpoint
* rpmsg_get_signals() - get the signals for this endpoint
* @ept: the rpmsg endpoint
* @sigs: serial signals bitmask
*
* Returns 0 on success and an appropriate error value on failure.
* Returns signal bits on success and an appropriate error value on failure.
*/
int rpmsg_get_sigs(struct rpmsg_endpoint *ept, u32 *lsigs, u32 *rsigs)
int rpmsg_get_signals(struct rpmsg_endpoint *ept)
{
if (WARN_ON(!ept))
return -EINVAL;
if (!ept->ops->get_sigs)
if (!ept->ops->get_signals)
return -ENXIO;
return ept->ops->get_sigs(ept, lsigs, rsigs);
return ept->ops->get_signals(ept);
}
EXPORT_SYMBOL(rpmsg_get_sigs);
EXPORT_SYMBOL(rpmsg_get_signals);
/**
* rpmsg_set_sigs() - set the remote signals for this endpoint
* rpmsg_set_signals() - set the remote signals for this endpoint
* @ept: the rpmsg endpoint
* @sigs: serial signals bitmask
* @set: set mask for signals
* @clear: clear mask for signals
*
* Returns 0 on success and an appropriate error value on failure.
*/
int rpmsg_set_sigs(struct rpmsg_endpoint *ept, u32 sigs)
int rpmsg_set_signals(struct rpmsg_endpoint *ept, u32 set, u32 clear)
{
if (WARN_ON(!ept))
return -EINVAL;
if (!ept->ops->set_sigs)
if (!ept->ops->set_signals)
return -ENXIO;
return ept->ops->set_sigs(ept, sigs);
return ept->ops->set_signals(ept, set, clear);
}
EXPORT_SYMBOL(rpmsg_set_sigs);
EXPORT_SYMBOL(rpmsg_set_signals);
/*
* match an rpmsg channel with a channel info struct.

View file

@ -4,7 +4,7 @@
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2011 Google, Inc.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*
* Ohad Ben-Cohen <ohad@wizery.com>
* Brian Swetland <swetland@google.com>
@ -48,8 +48,8 @@ struct rpmsg_device_ops {
* @trysendto: see @rpmsg_trysendto(), optional
* @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional
* @poll: see @rpmsg_poll(), optional
* @get_sigs: see @rpmsg_get_sigs(), optional
* @set_sigs: see @rpmsg_set_sigs(), 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
@ -69,8 +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_sigs)(struct rpmsg_endpoint *ept, u32 *lsigs, u32 *rsigs);
int (*set_sigs)(struct rpmsg_endpoint *ept, u32 sigs);
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);