From 8c60cb68fd76fa6d6083f0a27899efbacffaff53 Mon Sep 17 00:00:00 2001
From: Bowen Wang <wangbowen@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 apis 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 7503b2ab9..0194f2752 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;
-}
-