From d8ad056b0e4c99fcc05e08db6b82b3733ba81277 Mon Sep 17 00:00:00 2001 From: wangbowen6 <wangbowen6@xiaomi.com> Date: Tue, 9 May 2023 12:53:21 +0800 Subject: [PATCH] virtio: decoupling the transport layer and virtio device layer Add virtio device create/delete virtqueues api to decouple the transport layer and virtio device layer. Signed-off-by: Bowen Wang <wangbowen6@xiaomi.com> --- lib/include/openamp/rpmsg_virtio.h | 4 +- lib/include/openamp/virtio.h | 146 ++++++++++++++++++++++++++++- lib/remoteproc/remoteproc_virtio.c | 42 +++++++++ lib/virtio/virtio.c | 40 -------- 4 files changed, 187 insertions(+), 45 deletions(-) diff --git a/lib/include/openamp/rpmsg_virtio.h b/lib/include/openamp/rpmsg_virtio.h index 3d03e8d5d..7e7ba8fb1 100644 --- a/lib/include/openamp/rpmsg_virtio.h +++ b/lib/include/openamp/rpmsg_virtio.h @@ -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); } /** diff --git a/lib/include/openamp/virtio.h b/lib/include/openamp/virtio.h index 5e227f855..b48c18239 100644 --- a/lib/include/openamp/virtio.h +++ b/lib/include/openamp/virtio.h @@ -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); @@ -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 } diff --git a/lib/remoteproc/remoteproc_virtio.c b/lib/remoteproc/remoteproc_virtio.c index 169e5b5fa..fa469513b 100644 --- a/lib/remoteproc/remoteproc_virtio.c +++ b/lib/remoteproc/remoteproc_virtio.c @@ -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; @@ -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, diff --git a/lib/virtio/virtio.c b/lib/virtio/virtio.c index d25aec334..e67e97d6a 100644 --- a/lib/virtio/virtio.c +++ b/lib/virtio/virtio.c @@ -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; -} -