[SLOF] [PATCH v3 05/22] virtio: introduce helper for initializing virt queue

Nikunj A Dadhania nikunj at linux.vnet.ibm.com
Fri Jan 22 21:54:48 AEDT 2016


The routine takes care to allocate and set the queue address in the
device. Add these calls in virtio-net, virtio-blk and virtio-9p.

With the lack of this routine, devices like virtio-blk and virtio-9p did
not do a device reset in the driver initialization code. This helper
will fix that problem

Change the signature of virtio_set_qaddr, accepting queue address as
unsigned long argument.

Signed-off-by: Nikunj A Dadhania <nikunj at linux.vnet.ibm.com>
---
 board-qemu/slof/pci-device_1af4_1001.fs |  9 -------
 board-qemu/slof/pci-device_1af4_1009.fs |  9 -------
 lib/libvirtio/virtio-9p.c               |  7 ++++++
 lib/libvirtio/virtio-blk.c              |  8 +++++++
 lib/libvirtio/virtio-net.c              | 42 ++++-----------------------------
 lib/libvirtio/virtio-net.h              | 12 ----------
 lib/libvirtio/virtio.c                  | 23 +++++++++++++++++-
 lib/libvirtio/virtio.h                  | 12 +++++++++-
 8 files changed, 53 insertions(+), 69 deletions(-)

diff --git a/board-qemu/slof/pci-device_1af4_1001.fs b/board-qemu/slof/pci-device_1af4_1001.fs
index fb24634..db0bb3f 100644
--- a/board-qemu/slof/pci-device_1af4_1001.fs
+++ b/board-qemu/slof/pci-device_1af4_1001.fs
@@ -22,13 +22,4 @@ pci-io-enable
 
 s" virtio-block.fs" included
 
-\ Allocate memory for virtio queue:
-virtiodev 0 virtio-get-qsize virtio-vring-size
-1000 CLAIM VALUE queue-addr
-
-\ Write queue address into device:
-queue-addr c rshift
-virtiodev vd>base @ 8 +
-rl!-le
-
 pci-device-disable
diff --git a/board-qemu/slof/pci-device_1af4_1009.fs b/board-qemu/slof/pci-device_1af4_1009.fs
index 03964a6..9c8be24 100644
--- a/board-qemu/slof/pci-device_1af4_1009.fs
+++ b/board-qemu/slof/pci-device_1af4_1009.fs
@@ -22,13 +22,4 @@ pci-io-enable
 
 s" virtio-fs.fs" included
 
-\ Allocate memory for virtio queue:
-virtiodev 0 virtio-get-qsize virtio-vring-size
-1000 CLAIM VALUE queue-addr
-
-\ Write queue address into device:
-queue-addr c rshift
-virtiodev vd>base @ 8 +
-rl!-le
-
 pci-device-disable
diff --git a/lib/libvirtio/virtio-9p.c b/lib/libvirtio/virtio-9p.c
index 46bacd6..719ac1a 100644
--- a/lib/libvirtio/virtio-9p.c
+++ b/lib/libvirtio/virtio-9p.c
@@ -19,6 +19,7 @@
 #include "virtio-9p.h"
 #include "p9.h"
 
+static struct vqs vq;
 
 /**
  * Notes for 9P Server config:
@@ -189,6 +190,12 @@ int virtio_9p_init(struct virtio_device *dev, void *tx_buf, void *rx_buf,
 	/* Device specific setup - we do not support special features */
 	virtio_set_guest_features(dev,  0);
 
+	if (virtio_queue_init_vq(dev, &vq, 0)) {
+		virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER
+				  |VIRTIO_STAT_FAILED);
+		return -1;
+	}
+
 	vq_avail = virtio_get_vring_avail(dev, 0);
 	vq_avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
 	vq_avail->idx = 0;
diff --git a/lib/libvirtio/virtio-blk.c b/lib/libvirtio/virtio-blk.c
index 1e01c14..fe50af8 100644
--- a/lib/libvirtio/virtio-blk.c
+++ b/lib/libvirtio/virtio-blk.c
@@ -18,6 +18,8 @@
 
 #define DEFAULT_SECTOR_SIZE 512
 
+static struct vqs vq;
+
 /**
  * Initialize virtio-block device.
  * @param  dev  pointer to virtio device information
@@ -44,6 +46,12 @@ virtioblk_init(struct virtio_device *dev)
 	/* Device specific setup - we support F_BLK_SIZE */
 	virtio_set_guest_features(dev,  VIRTIO_BLK_F_BLK_SIZE);
 
+	if (virtio_queue_init_vq(dev, &vq, 0)) {
+		virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER
+				  |VIRTIO_STAT_FAILED);
+		return 0;
+	}
+
 	vq_avail = virtio_get_vring_avail(dev, 0);
 	vq_avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
 	vq_avail->idx = 0;
diff --git a/lib/libvirtio/virtio-net.c b/lib/libvirtio/virtio-net.c
index d8ce9a3..a32a32e 100644
--- a/lib/libvirtio/virtio-net.c
+++ b/lib/libvirtio/virtio-net.c
@@ -37,18 +37,6 @@
 
 #define sync()  asm volatile (" sync \n" ::: "memory")
 
-/* PCI virtio header offsets */
-#define VIRTIOHDR_DEVICE_FEATURES       0
-#define VIRTIOHDR_GUEST_FEATURES        4
-#define VIRTIOHDR_QUEUE_ADDRESS         8
-#define VIRTIOHDR_QUEUE_SIZE            12
-#define VIRTIOHDR_QUEUE_SELECT          14
-#define VIRTIOHDR_QUEUE_NOTIFY          16
-#define VIRTIOHDR_DEVICE_STATUS         18
-#define VIRTIOHDR_ISR_STATUS            19
-#define VIRTIOHDR_DEVICE_CONFIG         20
-#define VIRTIOHDR_MAC_ADDRESS           20
-
 struct virtio_device virtiodev;
 struct vqs vq[2];     /* Information about virtqueues */
 
@@ -72,8 +60,6 @@ static uint16_t last_rx_idx;	/* Last index in RX "used" ring */
  */
 static int virtionet_init_pci(struct virtio_device *dev)
 {
-	int i;
-
 	dprintf("virtionet: doing virtionet_init_pci!\n");
 
 	if (!dev)
@@ -90,29 +76,11 @@ static int virtionet_init_pci(struct virtio_device *dev)
 	 * second the transmit queue, and the forth is the control queue for
 	 * networking options.
 	 * We are only interested in the receive and transmit queue here. */
-
-	for (i=VQ_RX; i<=VQ_TX; i++) {
-		/* Select ring (0=RX, 1=TX): */
-		vq[i].id = i-VQ_RX;
-		ci_write_16(virtiodev.base+VIRTIOHDR_QUEUE_SELECT,
-			    cpu_to_le16(vq[i].id));
-
-		vq[i].size = le16_to_cpu(ci_read_16(virtiodev.base+VIRTIOHDR_QUEUE_SIZE));
-		vq[i].desc = SLOF_alloc_mem_aligned(virtio_vring_size(vq[i].size), 4096);
-		if (!vq[i].desc) {
-			printf("memory allocation failed!\n");
-			return -1;
-		}
-		memset(vq[i].desc, 0, virtio_vring_size(vq[i].size));
-		ci_write_32(virtiodev.base+VIRTIOHDR_QUEUE_ADDRESS,
-			    cpu_to_le32((long)vq[i].desc / 4096));
-		vq[i].avail = (void*)vq[i].desc
-				    + vq[i].size * sizeof(struct vring_desc);
-		vq[i].used = (void*)VQ_ALIGN((long)vq[i].avail
-				    + vq[i].size * sizeof(struct vring_avail));
-
-		dprintf("%i: vq.id = %llx\nvq.size =%x\n vq.avail =%p\nvq.used=%p\n",
-			i, vq[i].id, vq[i].size, vq[i].avail, vq[i].used);
+	if (virtio_queue_init_vq(dev, &vq[VQ_RX], VQ_RX) ||
+	    virtio_queue_init_vq(dev, &vq[VQ_TX], VQ_TX)) {
+		virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER
+    				  |VIRTIO_STAT_FAILED);
+		return -1;
 	}
 
 	/* Acknowledge device. */
diff --git a/lib/libvirtio/virtio-net.h b/lib/libvirtio/virtio-net.h
index bc7a189..2196f87 100644
--- a/lib/libvirtio/virtio-net.h
+++ b/lib/libvirtio/virtio-net.h
@@ -23,18 +23,6 @@ enum {
 	VQ_TX = 1,	/* Transmit Queue */
 };
 
-struct vqs {
-	uint64_t id;	/* Queue ID */
-	uint32_t size;
-	void *buf_mem;
-	struct vring_desc *desc;
-	struct vring_avail *avail;
-	struct vring_used *used;
-};
-
-/* Device is identified by RX queue ID: */
-#define DEVICE_ID  vq[0].id
-
 extern net_driver_t *virtionet_open(char *mac_addr, int len, struct virtio_device *dev);
 extern void virtionet_close(net_driver_t *driver);
 extern int virtionet_read(char *buf, int len);
diff --git a/lib/libvirtio/virtio.c b/lib/libvirtio/virtio.c
index 8da10c8..063a621 100644
--- a/lib/libvirtio/virtio.c
+++ b/lib/libvirtio/virtio.c
@@ -10,10 +10,15 @@
  *     IBM Corporation - initial implementation
  *****************************************************************************/
 
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
 #include <cpu.h>
 #include <cache.h>
 #include <byteorder.h>
 #include "virtio.h"
+#include "helpers.h"
 
 /* PCI virtio header offsets */
 #define VIRTIOHDR_DEVICE_FEATURES	0
@@ -133,7 +138,7 @@ void virtio_queue_notify(struct virtio_device *dev, int queue)
 /**
  * Set queue address
  */
-void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned int qaddr)
+void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned long qaddr)
 {
 	if (dev->type == VIRTIO_TYPE_PCI) {
 		uint32_t val = qaddr;
@@ -146,6 +151,22 @@ void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned int qaddr)
 	}
 }
 
+int virtio_queue_init_vq(struct virtio_device *dev, struct vqs *vq, unsigned int id)
+{
+	vq->size = virtio_get_qsize(dev, id);
+	vq->desc = SLOF_alloc_mem_aligned(virtio_vring_size(vq->size), 4096);
+	if (!vq->desc) {
+		printf("memory allocation failed!\n");
+		return -1;
+	}
+	memset(vq->desc, 0, virtio_vring_size(vq->size));
+	virtio_set_qaddr(dev, id, (unsigned long)vq->desc);
+	vq->avail = virtio_get_vring_avail(dev, id);
+	vq->used = virtio_get_vring_used(dev, id);
+	vq->id = id;
+	return 0;
+}
+
 /**
  * Set device status bits
  */
diff --git a/lib/libvirtio/virtio.h b/lib/libvirtio/virtio.h
index 9d6d8da..e41f47d 100644
--- a/lib/libvirtio/virtio.h
+++ b/lib/libvirtio/virtio.h
@@ -66,6 +66,15 @@ struct virtio_device {
 	int type;		/* VIRTIO_TYPE_PCI or VIRTIO_TYPE_VIO */
 };
 
+struct vqs {
+	uint64_t id;	/* Queue ID */
+	uint32_t size;
+	void *buf_mem;
+	struct vring_desc *desc;
+	struct vring_avail *avail;
+	struct vring_used *used;
+};
+
 /* Parts of the virtqueue are aligned on a 4096 byte page boundary */
 #define VQ_ALIGN(addr)	(((addr) + 0xfff) & ~0xfff)
 
@@ -74,11 +83,12 @@ extern int virtio_get_qsize(struct virtio_device *dev, int queue);
 extern struct vring_desc *virtio_get_vring_desc(struct virtio_device *dev, int queue);
 extern struct vring_avail *virtio_get_vring_avail(struct virtio_device *dev, int queue);
 extern struct vring_used *virtio_get_vring_used(struct virtio_device *dev, int queue);
+extern int virtio_queue_init_vq(struct virtio_device *dev, struct vqs *vq, unsigned int id);
 
 extern void virtio_reset_device(struct virtio_device *dev);
 extern void virtio_queue_notify(struct virtio_device *dev, int queue);
 extern void virtio_set_status(struct virtio_device *dev, int status);
-extern void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned int qaddr);
+extern void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned long qaddr);
 extern void virtio_set_guest_features(struct virtio_device *dev, int features);
 extern void virtio_get_host_features(struct virtio_device *dev, int *features);
 extern uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size);
-- 
2.5.0



More information about the SLOF mailing list