This patch set introduces a TTY console on top of the RPMsg framework which
enables the following use cases:
- Provide a console to communicate easily with the remote processor
application.
- Provide an interface to get the remote processor log traces without
ring buffer limitation.
- Ease the migration from MPU + MCU processors to multi core processors
(MPU and MCU integrated in one processor)
An alternative of this proposed solution would consist in using the virtio
console:
The drawback with that solution is that it requires a specific virtio buffer
(in addition to the one already used for RPMsg) which does not fit with remote
processors with little memory. The proposed solution allows to multiplex the
console with the other rpmsg services, optimizing the memory.
The first patch adds an API to the rpmsg framework ('get buffer size') and the
second one is the rpmsg tty driver itself.
History:
-V2 to V3:
- suppress error return on rpmsg callback as not tested in rpmsg framework
- change some flow messages level to debug
- add missing out of memory checks
-V1 to V2:
- modify message structure to allow to data transmission but also
flow control
- add documentation file to describe message structure for remote
implementation
- add dtr/rts management
- disable termios modes that generates non optimized behavior on RPMsg
transfers
- replace rpmsg_send by rpmsg_trysend to not block the write
- suppress useless spinlock on read
- miscellaneous fixes to improve robustness
Arnaud Pouliquen (2):
rpmsg: core: add possibility to get message payload length
tty: add rpmsg driver
Documentation/serial/tty_rpmsg.txt | 38 +++
drivers/rpmsg/rpmsg_core.c | 20 ++
drivers/rpmsg/rpmsg_internal.h | 2 +
drivers/rpmsg/virtio_rpmsg_bus.c | 11 +
drivers/tty/Kconfig | 9 +
drivers/tty/Makefile | 1 +
drivers/tty/rpmsg_tty.c | 479 +++++++++++++++++++++++++++++++++++++
include/linux/rpmsg.h | 10 +
8 files changed, 570 insertions(+)
create mode 100644 Documentation/serial/tty_rpmsg.txt
create mode 100644 drivers/tty/rpmsg_tty.c
--
2.7.4
Return the rpmsg buffer payload size for sending message, so rpmsg users
can split a long message in several sub rpmsg buffers.
Signed-off-by: Arnaud Pouliquen <[email protected]>
Signed-off-by: Fabien Dessenne <[email protected]>
---
drivers/rpmsg/rpmsg_core.c | 20 ++++++++++++++++++++
drivers/rpmsg/rpmsg_internal.h | 2 ++
drivers/rpmsg/virtio_rpmsg_bus.c | 11 +++++++++++
include/linux/rpmsg.h | 10 ++++++++++
4 files changed, 43 insertions(+)
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 8122807db380..75c8c403ffe5 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -283,6 +283,26 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
}
EXPORT_SYMBOL(rpmsg_trysend_offchannel);
+/**
+ * rpmsg_get_buf_payload_size()
+ * This function returns buffer payload size available for sending messages.
+ *
+ * @ept: the rpmsg endpoint
+ *
+ * Returns buffer payload size on success and an appropriate error value on
+ * failure.
+ */
+int rpmsg_get_buf_payload_size(struct rpmsg_endpoint *ept)
+{
+ if (WARN_ON(!ept))
+ return -EINVAL;
+ if (!ept->ops->get_buf_payload_size)
+ return -ENXIO;
+
+ return ept->ops->get_buf_payload_size(ept);
+}
+EXPORT_SYMBOL(rpmsg_get_buf_payload_size);
+
/*
* match an rpmsg channel with a channel info struct.
* this is used to make sure we're not creating rpmsg devices for channels
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 0d791c30b7ea..6f733a556139 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -46,6 +46,7 @@ struct rpmsg_device_ops {
* @trysend: see @rpmsg_trysend(), required
* @trysendto: see @rpmsg_trysendto(), optional
* @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional
+ * @get_buf_payload_size: see @rpmsg_get_buf_payload_size(), optional
*
* Indirection table for the operations that a rpmsg backend should implement.
* In addition to @destroy_ept, the backend must at least implement @send and
@@ -65,6 +66,7 @@ struct rpmsg_endpoint_ops {
void *data, int len);
__poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp,
poll_table *wait);
+ int (*get_buf_payload_size)(struct rpmsg_endpoint *ept);
};
int rpmsg_register_device(struct rpmsg_device *rpdev);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 5d3685bd76a2..82753e76e377 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -175,6 +175,7 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
int len, u32 dst);
static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
u32 dst, void *data, int len);
+static int virtio_get_buf_payload_size(struct rpmsg_endpoint *ept);
static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
.destroy_ept = virtio_rpmsg_destroy_ept,
@@ -184,6 +185,7 @@ static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
.trysend = virtio_rpmsg_trysend,
.trysendto = virtio_rpmsg_trysendto,
.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
+ .get_buf_payload_size = virtio_get_buf_payload_size,
};
/**
@@ -699,6 +701,15 @@ static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
}
+static int virtio_get_buf_payload_size(struct rpmsg_endpoint *ept)
+{
+ struct rpmsg_device *rpdev = ept->rpdev;
+ struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
+ int size = vch->vrp->buf_size - sizeof(struct rpmsg_hdr);
+
+ return size < 0 ? -EMSGSIZE : size;
+}
+
static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
struct rpmsg_hdr *msg, unsigned int len)
{
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 9fe156d1c018..250df2165086 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -135,6 +135,8 @@ 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_buf_payload_size(struct rpmsg_endpoint *ept);
+
#else
static inline int register_rpmsg_device(struct rpmsg_device *dev)
@@ -242,6 +244,14 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept,
return 0;
}
+static int rpmsg_get_buf_payload_size(struct rpmsg_endpoint *ept)
+{
+ /* 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 */
--
2.7.4