diff --git a/docs/rpmsg-design.md b/docs/rpmsg-design.md index f28b782..2bf2f95 100644 --- a/docs/rpmsg-design.md +++ b/docs/rpmsg-design.md @@ -87,6 +87,12 @@ running on two processors. uint32_t src, uint32_t dst, const void *data, int len)` ``` + +* Releases unused Tx buffer reserved by rpmsg_get_tx_payload_buffer() function: + ``` + int rpmsg_release_tx_buffer(struct rpmsg_endpoint *ept, void *txbuf) + ``` + ## RPMsg User Defined Callbacks * RPMsg endpoint message received callback: ``` diff --git a/lib/include/openamp/rpmsg.h b/lib/include/openamp/rpmsg.h index 149c567..64678cf 100644 --- a/lib/include/openamp/rpmsg.h +++ b/lib/include/openamp/rpmsg.h @@ -42,6 +42,7 @@ extern "C" { #define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5) #define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) #define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) +#define RPMSG_ERR_PERM (RPMSG_ERROR_BASE - 8) struct rpmsg_endpoint; struct rpmsg_device; @@ -87,6 +88,7 @@ struct rpmsg_endpoint { * @release_rx_buffer: release RPMsg RX buffer * @get_tx_payload_buffer: get RPMsg TX buffer * @send_offchannel_nocopy: send RPMsg data without copy + * @release_tx_buffer: release RPMsg TX buffer */ struct rpmsg_device_ops { int (*send_offchannel_raw)(struct rpmsg_device *rdev, @@ -99,6 +101,7 @@ struct rpmsg_device_ops { int (*send_offchannel_nocopy)(struct rpmsg_device *rdev, uint32_t src, uint32_t dst, const void *data, int len); + int (*release_tx_buffer)(struct rpmsg_device *rdev, void *txbuf); }; /** @@ -346,6 +349,28 @@ void rpmsg_release_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf); void *rpmsg_get_tx_payload_buffer(struct rpmsg_endpoint *ept, uint32_t *len, int wait); +/** + * @brief Releases unused buffer. + * + * This API can be called when the Tx buffer reserved by rpmsg_get_tx_payload_buffer + * needs to be released without having been sent to the remote side. + * + * Note that the rpmsg virtio is not able to detect if a buffer has already been released. + * The user must prevent a double release (e.g. by resetting its buffer pointer to zero after + * the release). + * + * @ept: the rpmsg endpoint + * @txbuf: tx buffer with message payload + * + * @return: + * - RPMSG_SUCCESS on success + * - RPMSG_ERR_PARAM on invalid parameter + * - RPMSG_ERR_PERM if service not implemented + * + * @see rpmsg_get_tx_payload_buffer + */ +int rpmsg_release_tx_buffer(struct rpmsg_endpoint *ept, void *txbuf); + /** * rpmsg_send_offchannel_nocopy() - send a message in tx buffer reserved by * rpmsg_get_tx_payload_buffer() across to the remote processor. diff --git a/lib/rpmsg/rpmsg.c b/lib/rpmsg/rpmsg.c index 9322c3d..0d3e1d0 100644 --- a/lib/rpmsg/rpmsg.c +++ b/lib/rpmsg/rpmsg.c @@ -170,6 +170,21 @@ void rpmsg_release_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf) rdev->ops.release_rx_buffer(rdev, rxbuf); } +int rpmsg_release_tx_buffer(struct rpmsg_endpoint *ept, void *buf) +{ + struct rpmsg_device *rdev; + + if (!ept || !ept->rdev || !buf) + return RPMSG_ERR_PARAM; + + rdev = ept->rdev; + + if (rdev->ops.release_tx_buffer) + return rdev->ops.release_tx_buffer(rdev, buf); + + return RPMSG_ERR_PERM; +} + void *rpmsg_get_tx_payload_buffer(struct rpmsg_endpoint *ept, uint32_t *len, int wait) {