Skip to content

Commit

Permalink
virtio: decoupling the transport layer and virtio device layer
Browse files Browse the repository at this point in the history
Add virtio device create/delete virtqueues api to decouple the
transport layer and virtio device layer.

Signed-off-by: Bowen Wang <[email protected]>
  • Loading branch information
CV-Bowen committed May 12, 2023
1 parent a94e0c6 commit d8ad056
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 45 deletions.
4 changes: 2 additions & 2 deletions lib/include/openamp/rpmsg_virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev,
const char *names[],
vq_callback *callbacks)
{
return virtio_create_virtqueues(rvdev->vdev, flags, nvqs, names,
callbacks);
return rvdev->vdev->func->create_virtqueues(rvdev->vdev, flags, nvqs,
names, callbacks);
}

/**
Expand Down
146 changes: 143 additions & 3 deletions lib/include/openamp/virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ void virtio_describe(struct virtio_device *dev, const char *msg,
*/

struct virtio_dispatch {
int (*create_virtqueues)(struct virtio_device *vdev,
unsigned int flags,
unsigned int nvqs, const char *names[],
vq_callback callbacks[]);
void (*delete_virtqueues)(struct virtio_device *vdev);
uint8_t (*get_status)(struct virtio_device *dev);
void (*set_status)(struct virtio_device *dev, uint8_t status);
uint32_t (*get_features)(struct virtio_device *dev);
Expand All @@ -181,9 +186,144 @@ struct virtio_dispatch {
void (*notify)(struct virtqueue *vq);
};

int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags,
unsigned int nvqs, const char *names[],
vq_callback callbacks[]);
/**
* @brief Create the virtio device virtqueue.
*
* @param[in] vdev Pointer to virtio device structure.
* @param[in] flags Create flag.
* @param[in] nvqs The virtqueue number.
* @param[in] names Virtqueue names.
* @param[in] callbacks Virtqueue callback functions.
*
* @return pointer to virtio device structure.
*/

static inline int
virtio_device_create_virtqueues(struct virtio_device *vdev, unsigned int flags,
unsigned int nvqs, const char *names[],
vq_callback callbacks[])
{
return vdev->func->create_virtqueues(vdev, flags, nvqs, names,
callbacks);
}

/**
* @brief Delete the virtio device virtqueue.
*
* @param[in] vdev Pointer to virtio device structure.
*
* @return pointer to virtio device structure.
*/

static inline void
virtio_device_delete_virtqueues(struct virtio_device *vdev)
{
return vdev->func->delete_virtqueues ?
vdev->func->delete_virtqueues(vdev) : -ENXIO;
}

/**
* @brief Retrieve device status.
*
* @param[in] dev Pointer to device structure.
*
* @return status of the device.
*/

static inline uint8_t virtio_device_get_status(struct virtio_device *vdev)
{
return vdev->func->get_status(vdev);
}

/**
* @brief Set device status.
*
* @param[in] dev Pointer to device structure.
* @param[in] status Value to be set as device status.
*
* @return N/A.
*/

static inline void virtio_device_set_status(struct virtio_device *vdev,
uint8_t status)
{
vdev->func->set_status(vdev, status);
}

/**
* @brief Retrieve configuration data from the device.
*
* @param[in] dev Pointer to device structure.
* @param[in] offset Offset of the data within the configuration area.
* @param[in] dst Address of the buffer that will hold the data.
* @param[in] len Length of the data to be retrieved.
*
* @return N/A.
*/

static inline void virtio_device_read_config(struct virtio_device *vdev,
uint32_t offset, void *dst,
int length)
{
vdev->func->read_config(vdev, offset, dst, length);
}

/**
* @brief Write configuration data to the device.
*
* @param[in] dev Pointer to device structure.
* @param[in] offset Offset of the data within the configuration area.
* @param[in] src Address of the buffer that holds the data to write.
* @param[in] len Length of the data to be written.
*
* @return N/A.
*/

static inline void virtio_device_write_config(struct virtio_device *vdev,
uint32_t offset, void *src,
int length)
{
vdev->func->write_config(vdev, offset, src, length);
}

/**
* @brief Retrieve features supported by both the VIRTIO driver and the VIRTIO device.
*
* @param[in] dev Pointer to device structure.
*
* @return Features supported by both the driver and the device as a bitfield.
*/

static inline uint32_t virtio_device_get_features(struct virtio_device *vdev)
{
return vdev->func->get_features(vdev);
}

/**
* @brief Set features supported by the VIRTIO driver.
*
* @param[in] dev Pointer to device structure.
* @param[in] features Features supported by the driver as a bitfield.
*
* @return N/A.
*/

static inline void virtio_device_set_features(struct virtio_device *vdev,
uint32_t features)
{
return vdev->func->set_features(vdev, features);
}

/**
* @brief Reset virtio device.
* @param[in] vdev Pointer to virtio_device structure.
* @return N/A.
*/

static inline void virtio_device_reset(struct virtio_device *vdev)
{
vdev->func->reset_device(vdev);
}

#if defined __cplusplus
}
Expand Down
42 changes: 42 additions & 0 deletions lib/remoteproc/remoteproc_virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,47 @@
#include <metal/utilities.h>
#include <metal/alloc.h>

static int rproc_virtio_create_virtqueues(struct virtio_device *vdev,
unsigned int flags,
unsigned int nvqs,
const char *names[],
vq_callback callbacks[])
{
struct virtio_vring_info *vring_info;
struct vring_alloc_info *vring_alloc;
unsigned int num_vrings, i;
int ret;
(void)flags;

num_vrings = vdev->vrings_num;
if (nvqs > num_vrings)
return ERROR_VQUEUE_INVLD_PARAM;
/* Initialize virtqueue for each vring */
for (i = 0; i < nvqs; i++) {
vring_info = &vdev->vrings_info[i];

vring_alloc = &vring_info->info;
#ifndef VIRTIO_DEVICE_ONLY
if (vdev->role == VIRTIO_DEV_DRIVER) {
size_t offset;
struct metal_io_region *io = vring_info->io;

offset = metal_io_virt_to_offset(io,
vring_alloc->vaddr);
metal_io_block_set(io, offset, 0,
vring_size(vring_alloc->num_descs,
vring_alloc->align));
}
#endif
ret = virtqueue_create(vdev, i, names[i], vring_alloc,
callbacks[i], vdev->func->notify,
vring_info->vq);
if (ret)
return ret;
}
return 0;
}

static void rproc_virtio_virtqueue_notify(struct virtqueue *vq)
{
struct remoteproc_virtio *rpvdev;
Expand Down Expand Up @@ -175,6 +216,7 @@ static void rproc_virtio_reset_device(struct virtio_device *vdev)
#endif

static const struct virtio_dispatch remoteproc_virtio_dispatch_funcs = {
.create_virtqueues = rproc_virtio_create_virtqueues,
.get_status = rproc_virtio_get_status,
.get_features = rproc_virtio_get_features,
.read_config = rproc_virtio_read_config,
Expand Down
40 changes: 0 additions & 40 deletions lib/virtio/virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,43 +96,3 @@ void virtio_describe(struct virtio_device *dev, const char *msg,
/* TODO: Not used currently - keeping it for future use*/
virtio_feature_name(0, desc);
}

int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags,
unsigned int nvqs, const char *names[],
vq_callback callbacks[])
{
struct virtio_vring_info *vring_info;
struct vring_alloc_info *vring_alloc;
unsigned int num_vrings, i;
int ret;
(void)flags;

num_vrings = vdev->vrings_num;
if (nvqs > num_vrings)
return ERROR_VQUEUE_INVLD_PARAM;
/* Initialize virtqueue for each vring */
for (i = 0; i < nvqs; i++) {
vring_info = &vdev->vrings_info[i];

vring_alloc = &vring_info->info;
#ifndef VIRTIO_DEVICE_ONLY
if (vdev->role == VIRTIO_DEV_DRIVER) {
size_t offset;
struct metal_io_region *io = vring_info->io;

offset = metal_io_virt_to_offset(io,
vring_alloc->vaddr);
metal_io_block_set(io, offset, 0,
vring_size(vring_alloc->num_descs,
vring_alloc->align));
}
#endif
ret = virtqueue_create(vdev, i, names[i], vring_alloc,
callbacks[i], vdev->func->notify,
vring_info->vq);
if (ret)
return ret;
}
return 0;
}

0 comments on commit d8ad056

Please sign in to comment.