From 6cb75b8e58f1f5bf9c793da3057f1c228fef0d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Mi=C5=9B?= Date: Mon, 13 Dec 2021 11:49:18 +0100 Subject: [PATCH] rpmsg_virtio: configuration option to set buffer sizes per instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable user of rpmsg_virtio to set sizes of TX and RX buffers per created rpmsg_virtio instance. Each instance can use other buffer sizes. Signed-off-by: Hubert Miś --- lib/include/openamp/rpmsg_virtio.h | 56 ++++++++++++++++++++++++++++++ lib/rpmsg/rpmsg_virtio.c | 43 +++++++++++++++++++---- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/lib/include/openamp/rpmsg_virtio.h b/lib/include/openamp/rpmsg_virtio.h index 12cb47fc8..7d5e729c1 100644 --- a/lib/include/openamp/rpmsg_virtio.h +++ b/lib/include/openamp/rpmsg_virtio.h @@ -41,9 +41,31 @@ struct rpmsg_virtio_shm_pool { size_t size; }; +/** + * struct rpmsg_virtio_config - configuration of rpmsg device based on virtio + * + * This structure is used by the rpmsg virtio host to configure the virtiio + * layer. + * + * @h2r_buf_size: the size of the buffer used to send data from host to remote + * @r2h_buf_size: the size of the buffer used to send data from remote to host + */ +struct rpmsg_virtio_config { + uint32_t h2r_buf_size; + uint32_t r2h_buf_size; +}; + +/* Default configuration */ +#define RPMSG_VIRTIO_DEFAULT_CONFIG \ + ((const struct rpmsg_virtio_config) { \ + .h2r_buf_size = RPMSG_BUFFER_SIZE, \ + .r2h_buf_size = RPMSG_BUFFER_SIZE, \ + }) + /** * struct rpmsg_virtio_device - representation of a rpmsg device based on virtio * @rdev: rpmsg device, first property in the struct + * @config: structure containing virtio configuration * @vdev: pointer to the virtio device * @rvq: pointer to receive virtqueue * @svq: pointer to send virtqueue @@ -52,6 +74,7 @@ struct rpmsg_virtio_shm_pool { */ struct rpmsg_virtio_device { struct rpmsg_device rdev; + struct rpmsg_virtio_config config; struct virtio_device *vdev; struct virtqueue *rvq; struct virtqueue *svq; @@ -145,6 +168,39 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, struct metal_io_region *shm_io, struct rpmsg_virtio_shm_pool *shpool); +/** + * rpmsg_init_vdev_with_config - initialize rpmsg virtio device with config + * Host side: + * Initialize RPMsg virtio queues and shared buffers, the address of shm can be + * ANY. In this case, function will get shared memory from system shared memory + * pools. If the vdev has the RPMsg name service feature, this API will create a + * name service endpoint. + * Sizes of virtio data buffers used by the initialized RPMsg instance are set + * to values read from the passed configuration structure. + * + * Remote side: + * This API will not return until the driver ready is set by the host side. + * Sizes of virtio data buffers are set by the host side. Values passed in the + * configuration structure have no effect. + * + * @param rvdev - pointer to the rpmsg virtio device + * @param vdev - pointer to the virtio device + * @param ns_bind_cb - callback handler for name service announcement without + * local endpoints waiting to bind. + * @param shm_io - pointer to the share memory I/O region. + * @param shpool - pointer to shared memory pool. rpmsg_virtio_init_shm_pool has + * to be called first to fill this structure. + * @param config - pointer to configuration structure + * + * @return - status of function execution + */ +int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, + struct virtio_device *vdev, + rpmsg_ns_bind_cb ns_bind_cb, + struct metal_io_region *shm_io, + struct rpmsg_virtio_shm_pool *shpool, + const struct rpmsg_virtio_config *config); + /** * rpmsg_deinit_vdev - deinitialize rpmsg virtio device * diff --git a/lib/rpmsg/rpmsg_virtio.c b/lib/rpmsg/rpmsg_virtio.c index c7c578d62..0db626e87 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ b/lib/rpmsg/rpmsg_virtio.c @@ -3,6 +3,7 @@ * All rights reserved. * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. * Copyright (c) 2018 Linaro, Inc. All rights reserved. + * Copyright (c) 2021 Nordic Semiconductor ASA * * SPDX-License-Identifier: BSD-3-Clause */ @@ -151,8 +152,8 @@ static void *rpmsg_virtio_get_tx_buffer(struct rpmsg_virtio_device *rvdev, data = virtqueue_get_buffer(rvdev->svq, len, idx); if (!data && rvdev->svq->vq_free_cnt) { data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool, - RPMSG_BUFFER_SIZE); - *len = RPMSG_BUFFER_SIZE; + rvdev->config.h2r_buf_size); + *len = rvdev->config.h2r_buf_size; *idx = 0; } } @@ -250,7 +251,7 @@ static int _rpmsg_virtio_get_buffer_size(struct rpmsg_virtio_device *rvdev) * If device role is Master then buffers are provided by us, * so just provide the macro. */ - length = RPMSG_BUFFER_SIZE - sizeof(struct rpmsg_hdr); + length = rvdev->config.h2r_buf_size - sizeof(struct rpmsg_hdr); } #endif /*!VIRTIO_SLAVE_ONLY*/ @@ -384,7 +385,7 @@ static int rpmsg_virtio_send_offchannel_nocopy(struct rpmsg_device *rdev, #ifndef VIRTIO_SLAVE_ONLY if (rpmsg_virtio_get_role(rvdev) == RPMSG_MASTER) - buff_len = RPMSG_BUFFER_SIZE; + buff_len = rvdev->config.h2r_buf_size; else #endif /*!VIRTIO_SLAVE_ONLY*/ buff_len = virtqueue_get_buffer_length(rvdev->svq, idx); @@ -610,6 +611,17 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, rpmsg_ns_bind_cb ns_bind_cb, struct metal_io_region *shm_io, struct rpmsg_virtio_shm_pool *shpool) +{ + return rpmsg_init_vdev_with_config(rvdev, vdev, ns_bind_cb, shm_io, + shpool, &RPMSG_VIRTIO_DEFAULT_CONFIG); +} + +int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, + struct virtio_device *vdev, + rpmsg_ns_bind_cb ns_bind_cb, + struct metal_io_region *shm_io, + struct rpmsg_virtio_shm_pool *shpool, + const struct rpmsg_virtio_config *config) { struct rpmsg_device *rdev; const char *vq_names[RPMSG_NUM_VRINGS]; @@ -630,6 +642,23 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, rdev->ops.send_offchannel_nocopy = rpmsg_virtio_send_offchannel_nocopy; role = rpmsg_virtio_get_role(rvdev); +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + /* + * The virtio configuration contains only options applicable to + * a virtio driver, implying rpmsg host role. + */ + if (config == NULL) { + return RPMSG_ERR_PARAM; + } + rvdev->config = *config; + } +#else /*!VIRTIO_SLAVE_ONLY*/ + /* Ignore passed config in the virtio-device-only configuration. */ + (void)config; +#endif /*!VIRTIO_SLAVE_ONLY*/ + + #ifndef VIRTIO_MASTER_ONLY if (role == RPMSG_REMOTE) { /* wait synchro with the master */ @@ -699,11 +728,11 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, unsigned int idx; void *buffer; - vqbuf.len = RPMSG_BUFFER_SIZE; + vqbuf.len = rvdev->config.r2h_buf_size; for (idx = 0; idx < rvdev->rvq->vq_nentries; idx++) { /* Initialize TX virtqueue buffers for remote device */ buffer = rpmsg_virtio_shm_pool_get_buffer(shpool, - RPMSG_BUFFER_SIZE); + rvdev->config.r2h_buf_size); if (!buffer) { return RPMSG_ERR_NO_BUFF; @@ -714,7 +743,7 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, metal_io_block_set(shm_io, metal_io_virt_to_offset(shm_io, buffer), - 0x00, RPMSG_BUFFER_SIZE); + 0x00, rvdev->config.r2h_buf_size); status = virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1, buffer);