ipc: Remove nocopy feature from icmsg_me backend

Remove nocopy feature from icmsg_me backend.
The backend is not meant to be used to send big
data chunks thus no-copy feature is removed.
If one wants to use no-copy it is recommended
to use icmsg_me only for control messages while
allocator will shall be written seperately.

Signed-off-by: Emil Obalski <Emil.Obalski@nordicsemi.no>
This commit is contained in:
Emil Obalski 2023-10-24 16:59:10 +02:00 committed by Fabio Baltieri
parent fbee62d9e3
commit f93243b68f
12 changed files with 14 additions and 586 deletions

View file

@ -134,151 +134,6 @@ int icmsg_send(const struct icmsg_config_t *conf,
struct icmsg_data_t *dev_data,
const void *msg, size_t len);
/** @brief Get an empty TX buffer to be sent using @ref icmsg_send_nocopy
*
* This function can be called to get an empty TX buffer so that the
* application can directly put its data into the sending buffer avoiding copy
* performed by the icmsg library.
*
* It is the application responsibility to correctly fill the allocated TX
* buffer with data and passing correct parameters to @ref
* icmsg_send_nocopy function to perform data no-copy-send mechanism.
*
* The size parameter can be used to request a buffer with a certain size:
* - if the size can be accommodated the function returns no errors and the
* buffer is allocated
* - if the requested size is too big, the function returns -ENOMEM and the
* the buffer is not allocated.
* - if the requested size is '0' the buffer is allocated with the maximum
* allowed size.
*
* In all the cases on return the size parameter contains the maximum size for
* the returned buffer.
*
* When the function returns no errors, the buffer is intended as allocated
* and it is released under one of two conditions: (1) when sending the buffer
* using @ref icmsg_send_nocopy (and in this case the buffer is automatically
* released by the backend), (2) when using @ref icmsg_drop_tx_buffer on a
* buffer not sent.
*
* @param[in] conf Structure containing configuration parameters for the icmsg
* instance.
* @param[inout] dev_data Structure containing run-time data used by the icmsg
* instance.
* @param[out] data Pointer to the empty TX buffer.
* @param[inout] size Pointer to store the requested TX buffer size. If the
* function returns -ENOMEM, this parameter returns the
* maximum allowed size.
*
* @retval -ENOBUFS when there are no TX buffers available.
* @retval -EALREADY when a buffer was already claimed and not yet released.
* @retval -ENOMEM when the requested size is too big (and the size parameter
* contains the maximum allowed size).
*
* @retval 0 on success.
*/
int icmsg_get_tx_buffer(const struct icmsg_config_t *conf,
struct icmsg_data_t *dev_data,
void **data, size_t *size);
/** @brief Drop and release a TX buffer
*
* Drop and release a TX buffer. It is possible to drop only TX buffers
* obtained by using @ref icmsg_get_tx_buffer.
*
* @param[in] conf Structure containing configuration parameters for the icmsg
* instance.
* @param[inout] dev_data Structure containing run-time data used by the icmsg
* instance.
* @param[in] data Pointer to the TX buffer.
*
* @retval -EALREADY when the buffer was already dropped.
* @retval -ENXIO when the buffer was not obtained using @ref
* ipc_service_get_tx_buffer
*
* @retval 0 on success.
*/
int icmsg_drop_tx_buffer(const struct icmsg_config_t *conf,
struct icmsg_data_t *dev_data,
const void *data);
/** @brief Send a message from a buffer obtained by @ref icmsg_get_tx_buffer
* to the remote icmsg instance.
*
* This is equivalent to @ref icmsg_send but in this case the TX buffer must
* have been obtained by using @ref icmsg_get_tx_buffer.
*
* The API user has to take the responsibility for getting the TX buffer using
* @ref icmsg_get_tx_buffer and filling the TX buffer with the data.
*
* After the @ref icmsg_send_nocopy function is issued the TX buffer is no
* more owned by the sending task and must not be touched anymore unless the
* function fails and returns an error.
*
* If this function returns an error, @ref icmsg_drop_tx_buffer can be used
* to drop the TX buffer.
*
* @param[in] conf Structure containing configuration parameters for the icmsg
* instance.
* @param[inout] dev_data Structure containing run-time data used by the icmsg
* instance.
* @param[in] msg Pointer to a buffer containing data to send.
* @param[in] len Size of data in the @p msg buffer.
*
*
* @return Size of sent data on success.
* @retval -EBUSY when the instance has not finished handshake with the remote
* instance.
* @retval -ENODATA when the requested data to send is empty.
* @retval -EBADMSG when the requested data to send is too big.
* @retval -ENXIO when the buffer was not obtained using @ref
* ipc_service_get_tx_buffer
* @retval other errno codes from dependent modules.
*/
int icmsg_send_nocopy(const struct icmsg_config_t *conf,
struct icmsg_data_t *dev_data,
const void *msg, size_t len);
#ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX
/** @brief Hold RX buffer to be used outside of the received callback.
*
* @param[in] conf Structure containing configuration parameters for the icmsg
* instance.
* @param[inout] dev_data Structure containing run-time data used by the icmsg
* instance.
* @param[in] data Pointer to the buffer to be held.
*
* @retval 0 on success.
* @retval -EBUSY when the instance has not finished handshake with the remote
* instance.
* @retval -EINVAL when the @p data argument does not point to a valid RX
* buffer.
* @retval -EALREADY when the buffer is already held.
*/
int icmsg_hold_rx_buffer(const struct icmsg_config_t *conf,
struct icmsg_data_t *dev_data,
const void *data);
/** @brief Release RX buffer for future use.
*
* @param[in] conf Structure containing configuration parameters for the icmsg
* instance.
* @param[inout] dev_data Structure containing run-time data used by the icmsg
* instance.
* @param[in] data Pointer to the buffer to be released.
*
* @retval 0 on success.
* @retval -EBUSY when the instance has not finished handshake with the remote
* instance.
* @retval -EINVAL when the @p data argument does not point to a valid RX
* buffer.
* @retval -EALREADY when the buffer is not held.
*/
int icmsg_release_rx_buffer(const struct icmsg_config_t *conf,
struct icmsg_data_t *dev_data,
const void *data);
#endif
/**
* @}
*/

View file

@ -247,118 +247,6 @@ int icmsg_me_send(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, icmsg_me_ept_id_t id,
const void *msg, size_t len);
/** @brief Get an empty TX buffer to be sent using @ref icmsg_me_send_nocopy
*
* This function is a wrapper around @ref icmsg_get_tx_buffer aligning buffer
* size and pointers to fit header required by the multi-endpoint feature.
* It shares all properites and usage scenarios with @ref icmsg_get_tx_buffer.
*
* @param[in] conf Structure containing configuration parameters for the
& underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[out] buffer Pointer to the empty TX buffer.
* @param[inout] size Pointer to store the requested TX buffer size. If the
* function returns -ENOMEM, this parameter returns the
* maximum allowed size.
* @param[in] wait Timeout value to wait for a free buffer acceptable by
* the function caller. Only K_NO_WAIT is supported by icmsg.
*
* @retval 0 on success.
* @retval -ENOTSUP when requested unsupported @p wait timeout.
* @retval -ENOBUFS when there are no TX buffers available.
* @retval -ENOMEM when the requested size is too big (and the size parameter
* contains the maximum allowed size).
* @retval other errno codes from dependent modules.
*/
int icmsg_me_get_tx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data,
void **buffer, uint32_t *size, k_timeout_t wait);
/** @brief Drop and release a TX buffer
*
* This function is a wrapper around @ref icmsg_drop_tx_buffer aligning buffer
* pointer to fit header required by the multi-endpoint feature. This function
* shares all properties and usage scenarios with @ref icmsg_drop_tx_buffer.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] buffer Pointer to the TX buffer obtained with
* @ref icmsg_me_get_tx_buffer.
*
* @retval 0 on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_drop_tx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data,
const void *buffer);
/** @brief Send a message from a buffer obtained by @ref icmsg_me_get_tx_buffer
* to the remote icmsg_me instance.
*
* This function is a wrapper around @ref icmsg_send_nocopy aligning buffer
* size and pointer to fit header required by the multi-endpoint feature. This
* function shares all properties and usage scenarios with
* @ref icmsg_send_nocopy.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] id Id of the endpoint to use.
* @param[in] msg Pointer to a buffer containing data to send.
* @param[in] len Size of data in the @p msg buffer.
*
*
* @return Size of sent data on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_send_nocopy(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, icmsg_me_ept_id_t id,
const void *msg, size_t len);
#ifdef CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX
/** @brief Hold RX buffer to be used outside of the received callback.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] buffer Pointer to the buffer to be held.
*
* @retval 0 on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_hold_rx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, void *buffer);
/** @brief Release RX buffer for future use.
*
* @param[in] conf Structure containing configuration parameters for the
* underlying icmsg instance.
* @param[inout] data Structure containing run-time data used by the icmsg_me
* instance. The structure is initialized with
* @ref icmsg_me_init and its content must be preserved
* while the icmsg_me instance is active.
* @param[in] buffer Pointer to the buffer to be released.
*
* @retval 0 on success.
* @retval other errno codes from dependent modules.
*/
int icmsg_me_release_rx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, void *buffer);
#endif /* CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX */
/**
* @}
*/

View file

@ -1,7 +1,6 @@
CONFIG_PRINTK=y
CONFIG_IPC_SERVICE=y
CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX=y
CONFIG_MBOX=y
CONFIG_LOG=y

View file

@ -1,7 +1,6 @@
CONFIG_PRINTK=y
CONFIG_IPC_SERVICE=y
CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX=y
CONFIG_MBOX=y
CONFIG_LOG=y

View file

@ -18,7 +18,7 @@ K_THREAD_STACK_DEFINE(ipc1_stack, STACKSIZE);
static volatile uint8_t ipc0A_received_data;
static volatile uint8_t ipc0B_received_data;
static const void *ipc1_received_data;
static volatile uint8_t ipc1_received_data;
static K_SEM_DEFINE(ipc0A_bound_sem, 0, 1);
static K_SEM_DEFINE(ipc0B_bound_sem, 0, 1);
@ -182,11 +182,8 @@ K_THREAD_DEFINE(ipc0B_thread_id, STACKSIZE, ipc0B_entry, NULL, NULL, NULL, PRIOR
/*
* ==> THREAD 1 (IPC instance 1) <==
*
* NOTE: This instance is using the NOCOPY copability of the backend.
*/
static struct ipc_ept ipc1_ept;
static void ipc1_ept_bound(void *priv)
{
k_sem_give(&ipc1_bound_sem);
@ -194,10 +191,9 @@ static void ipc1_ept_bound(void *priv)
static void ipc1_ept_recv(const void *data, size_t len, void *priv)
{
ipc_service_hold_rx_buffer(&ipc1_ept, (void *)data);
ipc1_received_data = data;
ipc1_received_data = *((uint8_t *) data);
k_sem_give(&ipc1_data_sem);
k_sem_give(&ipc0B_data_sem);
}
static struct ipc_ept_cfg ipc1_ept_cfg = {
@ -216,6 +212,7 @@ static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2)
const struct device *ipc1_instance;
unsigned char message = 0;
struct ipc_ept ipc1_ept;
int ret;
printk("IPC-service REMOTE [INST 1] demo started\n");
@ -237,38 +234,16 @@ static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2)
k_sem_take(&ipc1_bound_sem, K_FOREVER);
while (message < 99) {
void *tx_buffer;
uint32_t tx_buffer_size = sizeof(message);
k_sem_take(&ipc1_data_sem, K_FOREVER);
message = *((uint8_t *) ipc1_received_data);
ret = ipc_service_release_rx_buffer(&ipc1_ept, (void *) ipc1_received_data);
if (ret < 0) {
printk("release_rx_buffer() failed with ret %d\n", ret);
break;
}
message = ipc1_received_data;
printk("REMOTE [1]: %d\n", message);
message++;
ret = ipc_service_get_tx_buffer(&ipc1_ept, &tx_buffer, &tx_buffer_size, K_NO_WAIT);
ret = ipc_service_send(&ipc1_ept, &message, sizeof(message));
if (ret < 0) {
printk("get_tx_buffer(%u) failed with ret %d\n", sizeof(message), ret);
break;
}
if (tx_buffer_size != sizeof(message)) {
printk("get_tx_buffer modified buffer size to unexpected value %u\n",
tx_buffer_size);
break;
}
*((uint8_t *) tx_buffer) = message;
ret = ipc_service_send_nocopy(&ipc1_ept, tx_buffer, tx_buffer_size);
if (ret < 0) {
printk("send_message_nocopy(%u) failed with ret %d\n", message, ret);
printk("send_message(%d) failed with ret %d\n", message, ret);
break;
}
}

View file

@ -18,7 +18,7 @@ K_THREAD_STACK_DEFINE(ipc1_stack, STACKSIZE);
static volatile uint8_t ipc0A_received_data;
static volatile uint8_t ipc0B_received_data;
static const void *ipc1_received_data;
static volatile uint8_t ipc1_received_data;
static K_SEM_DEFINE(ipc0A_bound_sem, 0, 1);
static K_SEM_DEFINE(ipc0B_bound_sem, 0, 1);
@ -179,12 +179,8 @@ K_THREAD_DEFINE(ipc0B_thread_id, STACKSIZE, ipc0B_entry, NULL, NULL, NULL, PRIOR
/*
* ==> THREAD 1 (IPC instance 1) <==
*
* NOTE: This instance is using the NOCOPY copability of the backend.
*/
static struct ipc_ept ipc1_ept;
static void ipc1_ept_bound(void *priv)
{
k_sem_give(&ipc1_bound_sem);
@ -192,10 +188,9 @@ static void ipc1_ept_bound(void *priv)
static void ipc1_ept_recv(const void *data, size_t len, void *priv)
{
ipc_service_hold_rx_buffer(&ipc1_ept, (void *)data);
ipc1_received_data = data;
ipc1_received_data = *((uint8_t *) data);
k_sem_give(&ipc1_data_sem);
k_sem_give(&ipc0B_data_sem);
}
static struct ipc_ept_cfg ipc1_ept_cfg = {
@ -214,6 +209,7 @@ static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2)
const struct device *ipc1_instance;
unsigned char message = 0;
struct ipc_ept ipc1_ept;
int ret;
printk("IPC-service HOST [INST 1] demo started\n");
@ -242,36 +238,14 @@ static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2)
k_sleep(K_MSEC(1000));
while (message < 100) {
void *tx_buffer;
uint32_t tx_buffer_size = sizeof(message);
ret = ipc_service_get_tx_buffer(&ipc1_ept, &tx_buffer, &tx_buffer_size, K_NO_WAIT);
ret = ipc_service_send(&ipc1_ept, &message, sizeof(message));
if (ret < 0) {
printk("get_tx_buffer(%u) failed with ret %d\n", sizeof(message), ret);
break;
}
if (tx_buffer_size != sizeof(message)) {
printk("get_tx_buffer modified buffer size to unexpected value %u\n",
tx_buffer_size);
break;
}
*((uint8_t *) tx_buffer) = message;
ret = ipc_service_send_nocopy(&ipc1_ept, tx_buffer, tx_buffer_size);
if (ret < 0) {
printk("send_message_nocopy(%u) failed with ret %d\n", message, ret);
printk("send_message(%d) failed with ret %d\n", message, ret);
break;
}
k_sem_take(&ipc1_data_sem, K_FOREVER);
message = *((uint8_t *) ipc1_received_data);
ret = ipc_service_release_rx_buffer(&ipc1_ept, (void *) ipc1_received_data);
if (ret < 0) {
printk("release_rx_buffer() failed with ret %d\n", ret);
break;
}
message = ipc1_received_data;
printk("HOST [1]: %d\n", message);
message++;

View file

@ -28,14 +28,4 @@ config IPC_SERVICE_BACKEND_ICMSG_ME_EP_NAME_LEN
Maximal length of a string used to discover endpoints between the
initiator and the follower.
config IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX
bool "Nocopy feature for receive path"
select IPC_SERVICE_ICMSG_ME_NOCOPY_RX
help
Enable nocopy feature for receive path of multiendpoint icmsg
ipc_service backend. This features enables functions to hold and
release rx buffer by the ipc_service API user. It also creates
performance and memory overhead so it is recommended to disable
this feature if unused by the API user.
endif # IPC_SERVICE_BACKEND_ICMSG_ME_INITIATOR || IPC_SERVICE_BACKEND_ICMSG_ME_FOLLOWER

View file

@ -260,71 +260,10 @@ static int send(const struct device *instance, void *token,
user_len);
}
static int get_tx_buffer(const struct device *instance, void *token,
void **data, uint32_t *user_len, k_timeout_t wait)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
return icmsg_me_get_tx_buffer(conf, &dev_data->icmsg_me_data, data,
user_len, wait);
}
static int drop_tx_buffer(const struct device *instance, void *token,
const void *data)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
return icmsg_me_drop_tx_buffer(conf, &dev_data->icmsg_me_data, data);
}
static int send_nocopy(const struct device *instance, void *token,
const void *data, size_t len)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
icmsg_me_ept_id_t *id = token;
if (*id == INVALID_EPT_ID) {
return -ENOTCONN;
}
return icmsg_me_send_nocopy(conf, &dev_data->icmsg_me_data, *id,
data, len);
}
#ifdef CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX
int hold_rx_buffer(const struct device *instance, void *token, void *data)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
return icmsg_me_hold_rx_buffer(conf, &dev_data->icmsg_me_data, data);
}
int release_rx_buffer(const struct device *instance, void *token, void *data)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
return icmsg_me_release_rx_buffer(conf, &dev_data->icmsg_me_data, data);
}
#endif /* CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX */
const static struct ipc_service_backend backend_ops = {
.open_instance = open,
.register_endpoint = register_ept,
.send = send,
.get_tx_buffer = get_tx_buffer,
.drop_tx_buffer = drop_tx_buffer,
.send_nocopy = send_nocopy,
#ifdef CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX
.hold_rx_buffer = hold_rx_buffer,
.release_rx_buffer = release_rx_buffer,
#endif
};
static int backend_init(const struct device *instance)

View file

@ -166,67 +166,10 @@ static int send(const struct device *instance, void *token,
return icmsg_me_send(conf, &dev_data->icmsg_me_data, *id, msg, len);
}
static int get_tx_buffer(const struct device *instance, void *token,
void **data, uint32_t *user_len, k_timeout_t wait)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
return icmsg_me_get_tx_buffer(conf, &dev_data->icmsg_me_data, data,
user_len, wait);
}
static int drop_tx_buffer(const struct device *instance, void *token,
const void *data)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
return icmsg_me_drop_tx_buffer(conf, &dev_data->icmsg_me_data, data);
}
static int send_nocopy(const struct device *instance, void *token,
const void *data, size_t len)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
icmsg_me_ept_id_t *id = token;
return icmsg_me_send_nocopy(conf, &dev_data->icmsg_me_data, *id,
data, len);
}
#ifdef CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX
int hold_rx_buffer(const struct device *instance, void *token, void *data)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
return icmsg_me_hold_rx_buffer(conf, &dev_data->icmsg_me_data, data);
}
int release_rx_buffer(const struct device *instance, void *token, void *data)
{
const struct icmsg_config_t *conf = instance->config;
struct backend_data_t *dev_data = instance->data;
return icmsg_me_release_rx_buffer(conf, &dev_data->icmsg_me_data, data);
}
#endif /* CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX */
const static struct ipc_service_backend backend_ops = {
.open_instance = open,
.register_endpoint = register_ept,
.send = send,
.get_tx_buffer = get_tx_buffer,
.drop_tx_buffer = drop_tx_buffer,
.send_nocopy = send_nocopy,
#ifdef CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_NOCOPY_RX
.hold_rx_buffer = hold_rx_buffer,
.release_rx_buffer = release_rx_buffer,
#endif
};
static int backend_init(const struct device *instance)

View file

@ -36,12 +36,3 @@ config IPC_SERVICE_ICMSG_ME
select EVENTS
help
Multi-endpoint functionality for the icmsg library
config IPC_SERVICE_ICMSG_ME_NOCOPY_RX
bool
depends on IPC_SERVICE_ICMSG_ME
select IPC_SERVICE_ICMSG_NOCOPY_RX
help
Enable nocopy feature for receiving path of the multi-endpoint
feature of the icmsg library. This features might be used by backends
based on multi-endpoint icmsg.

View file

@ -1,13 +1,6 @@
# Copyright (c) 2022 Nordic Semiconductor (ASA)
# SPDX-License-Identifier: Apache-2.0
config IPC_SERVICE_ICMSG_NOCOPY_RX
bool
depends on IPC_SERVICE_ICMSG
help
Enable nocopy feature for receiving path of the icmsg library that
might be used by backends based on icmsg.
config IPC_SERVICE_ICMSG_SHMEM_ACCESS_SYNC
bool "Synchronize access to shared memory"
default y

View file

@ -20,11 +20,6 @@ static void *icmsg_buffer_to_user_buffer(const void *icmsg_buffer)
return (void *)(((char *)icmsg_buffer) + HEADER_SIZE);
}
static void *user_buffer_to_icmsg_buffer(const void *user_buffer)
{
return (void *)(((char *)user_buffer) - HEADER_SIZE);
}
static size_t icmsg_buffer_len_to_user_buffer_len(size_t icmsg_buffer_len)
{
return icmsg_buffer_len - HEADER_SIZE;
@ -202,116 +197,3 @@ int icmsg_me_send(const struct icmsg_config_t *conf,
return sent_bytes;
}
static size_t get_buffer_length_to_pass(size_t icmsg_buffer_len)
{
if (icmsg_buffer_len >= HEADER_SIZE) {
return icmsg_buffer_len_to_user_buffer_len(icmsg_buffer_len);
} else {
return 0;
}
}
int icmsg_me_get_tx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data,
void **buffer, uint32_t *user_len, k_timeout_t wait)
{
void *icmsg_buffer;
int r;
size_t icmsg_len;
if (!K_TIMEOUT_EQ(wait, K_NO_WAIT)) {
return -ENOTSUP;
}
if (*user_len) {
icmsg_len = user_buffer_len_to_icmsg_buffer_len(*user_len);
} else {
icmsg_len = 0;
}
r = icmsg_get_tx_buffer(conf, &data->icmsg_data,
&icmsg_buffer, &icmsg_len);
if (r == -ENOMEM) {
*user_len = get_buffer_length_to_pass(icmsg_len);
return -ENOMEM;
}
if (r < 0) {
return r;
}
/* If requested max buffer length (*len == 0) allocated buffer might be
* shorter than HEADER_SIZE. In such circumstances drop the buffer
* and return error.
*/
*user_len = get_buffer_length_to_pass(icmsg_len);
if (!(*user_len)) {
r = icmsg_drop_tx_buffer(conf, &data->icmsg_data, icmsg_buffer);
__ASSERT_NO_MSG(!r);
return -ENOBUFS;
}
*buffer = icmsg_buffer_to_user_buffer(icmsg_buffer);
return 0;
}
int icmsg_me_drop_tx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data,
const void *buffer)
{
const void *buffer_to_drop = user_buffer_to_icmsg_buffer(buffer);
return icmsg_drop_tx_buffer(conf, &data->icmsg_data, buffer_to_drop);
}
int icmsg_me_send_nocopy(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, icmsg_me_ept_id_t id,
const void *msg, size_t len)
{
void *buffer_to_send;
size_t len_to_send;
int r;
int sent_bytes;
buffer_to_send = user_buffer_to_icmsg_buffer(msg);
len_to_send = user_buffer_len_to_icmsg_buffer_len(len);
set_ept_id_in_send_buffer(buffer_to_send, id);
r = icmsg_send_nocopy(conf, &data->icmsg_data,
buffer_to_send, len_to_send);
if (r < 0) {
return r;
}
__ASSERT_NO_MSG(r >= HEADER_SIZE);
if (r < HEADER_SIZE) {
return 0;
}
sent_bytes = icmsg_buffer_len_to_user_buffer_len(r);
return sent_bytes;
}
#ifdef CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX
int icmsg_me_hold_rx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, void *buffer)
{
void *icmsg_buffer = user_buffer_to_icmsg_buffer(buffer);
return icmsg_hold_rx_buffer(conf, &data->icmsg_data, icmsg_buffer);
}
int icmsg_me_release_rx_buffer(const struct icmsg_config_t *conf,
struct icmsg_me_data_t *data, void *buffer)
{
void *icmsg_buffer = user_buffer_to_icmsg_buffer(buffer);
return icmsg_release_rx_buffer(conf, &data->icmsg_data, icmsg_buffer);
}
#endif /* CONFIG_IPC_SERVICE_ICMSG_ME_NOCOPY_RX */