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:
parent
fbee62d9e3
commit
f93243b68f
12 changed files with 14 additions and 586 deletions
|
|
@ -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
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in a new issue