Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpmsg_virtio: configuration option to set buffer sizes per instance #328

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 60 additions & 4 deletions lib/include/openamp/rpmsg_virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -52,6 +74,7 @@ struct rpmsg_virtio_shm_pool {
*/
struct rpmsg_virtio_device {
struct rpmsg_device rdev;
struct rpmsg_virtio_config config;
edmooring marked this conversation as resolved.
Show resolved Hide resolved
struct virtio_device *vdev;
struct virtqueue *rvq;
struct virtqueue *svq;
Expand Down Expand Up @@ -120,14 +143,14 @@ int rpmsg_virtio_get_buffer_size(struct rpmsg_device *rdev);

/**
* rpmsg_init_vdev - initialize rpmsg virtio device
* Master side:
* 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 RPMsg name service feature, this API will create an
* pools. If the vdev has the RPMsg name service feature, this API will create a
* name service endpoint.
*
* Slave side:
* This API will not return until the driver ready is set by the master side.
* Remote side:
* This API will not return until the driver ready is set by the host side.
*
* @param rvdev - pointer to the rpmsg virtio device
* @param vdev - pointer to the virtio device
Expand All @@ -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
*
Expand Down
43 changes: 36 additions & 7 deletions lib/rpmsg/rpmsg_virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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*/

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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];
Expand All @@ -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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Segmentation fault during my non-reg tests because the rvdev->vdev->role is not yet set.
The block should be move after rdev = &rvdev->rdev;


#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*/

arnopo marked this conversation as resolved.
Show resolved Hide resolved

#ifndef VIRTIO_MASTER_ONLY
if (role == RPMSG_REMOTE) {
/* wait synchro with the master */
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down