diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 2037a4692b84..dc9e9d2e30bd 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -319,6 +319,29 @@ int rpmsg_set_signals(struct rpmsg_endpoint *ept, u32 set, u32 clear) } EXPORT_SYMBOL(rpmsg_set_signals); +#ifdef CONFIG_NO_GKI +/** + * rpmsg_get_mtu() - get maximum transmission buffer size for sending message. + * @ept: the rpmsg endpoint + * + * This function returns maximum buffer size available for a single outgoing message. + * + * Return: the maximum transmission size on success and an appropriate error + * value on failure. + */ + +ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept) +{ + if (WARN_ON(!ept)) + return -EINVAL; + if (!ept->ops->get_mtu) + return -ENOTSUPP; + + return ept->ops->get_mtu(ept); +} +EXPORT_SYMBOL(rpmsg_get_mtu); +#endif + /* * match a 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 03356e883b27..70f5667160d5 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h @@ -50,6 +50,7 @@ struct rpmsg_device_ops { * @poll: see @rpmsg_poll(), optional * @get_signals: see @rpmsg_get_signals(), optional * @set_signals: see @rpmsg_set_signals(), optional + * @get_mtu: see @rpmsg_get_mtu(), 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 @@ -71,6 +72,9 @@ struct rpmsg_endpoint_ops { poll_table *wait); int (*get_signals)(struct rpmsg_endpoint *ept); int (*set_signals)(struct rpmsg_endpoint *ept, u32 set, u32 clear); +#ifdef CONFIG_NO_GKI + ssize_t (*get_mtu)(struct rpmsg_endpoint *ept); +#endif }; 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 7d7ed4e5cce7..4abc86162da3 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -181,6 +181,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 ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept); static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { .destroy_ept = virtio_rpmsg_destroy_ept, @@ -190,6 +191,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_mtu = virtio_rpmsg_get_mtu, }; /** @@ -705,6 +707,14 @@ static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); } +static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept) +{ + struct rpmsg_device *rpdev = ept->rpdev; + struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); + + return vch->vrp->buf_size - sizeof(struct rpmsg_hdr); +} + 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 7cbb0fbf7d8f..f4e0cd6039e5 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -145,6 +145,8 @@ __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, int rpmsg_get_signals(struct rpmsg_endpoint *ept); int rpmsg_set_signals(struct rpmsg_endpoint *ept, u32 set, u32 clear); +ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept); + #else static inline int register_rpmsg_device(struct rpmsg_device *dev) @@ -269,6 +271,14 @@ static inline int rpmsg_set_signals(struct rpmsg_endpoint *ept, return -ENXIO; } +static inline ssize_t rpmsg_get_mtu(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 */