[PATCH] virtio_pci updates

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch brings the virtio_pci driver up-to-date with what I have locally.
It fixes a bug with destroying a virtqueue, switches to kmalloc so we can
support rings > PAGE_SIZE, and fixes a bug with odd sized configuration
entries.

Signed-off-by: Anthony Liguori <aliguori@xxxxxxxxxx>

diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 85ae096..eb9a8e0 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -1,3 +1,19 @@
+/*
+ * Virtio PCI driver
+ *
+ * This module allows virtio devices to be used over a virtual PCI device.
+ * This can be used with QEMU based VMMs like KVM or Xen.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ *  Anthony Liguori  <aliguori@xxxxxxxxxx>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
 #include <linux/module.h>
 #include <linux/list.h>
 #include <linux/pci.h>
@@ -17,32 +33,32 @@ MODULE_VERSION("1");
 /* Our device structure */
 struct virtio_pci_device
 {
-	/* the virtio device */
 	struct virtio_device vdev;
-	/* the PCI device */
 	struct pci_dev *pci_dev;
+
 	/* the IO mapping for the PCI config space */
 	void *ioaddr;
 
+	/* a list of queues so we can dispatch IRQs */
 	spinlock_t lock;
 	struct list_head virtqueues;
 };
 
 struct virtio_pci_vq_info
 {
+	/* the actual virtqueue */
+	struct virtqueue *vq;
+
 	/* the number of entries in the queue */
 	int num;
-	/* the number of pages the device needs for the ring queue */
-	int n_pages;
+
 	/* the index of the queue */
 	int queue_index;
-	/* the struct page of the ring queue */
-	struct page *pages;
+
 	/* the virtual address of the ring queue */
 	void *queue;
-	/* a pointer to the virtqueue */
-	struct virtqueue *vq;
-	/* the node pointer */
+
+	/* the list node for the virtqueues list */
 	struct list_head node;
 };
 
@@ -127,12 +143,15 @@ static void vp_get(struct virtio_device *vdev, unsigned offset,
 		break;
 	}
 
-	/* for strange accesses of an odd size, we do not perform any
-	 * endianness conversion. */
-	default:
-		ioread8_rep(ioaddr, buf, len);
+	default: {
+		uint8_t *ptr = buf;
+		int i;
+
+		for (i = 0; i < len; i++)
+			ptr[i] = ioread8(ioaddr + i);
 		break;
 	}
+	}
 }
 
 /* the config->set() implementation.  it's symmetric to the config->get()
@@ -169,10 +188,15 @@ static void vp_set(struct virtio_device *vdev, unsigned offset,
 		iowrite32(val, ioaddr + 4);
 		break;
 	}
-	default:
-		iowrite8_rep(ioaddr, buf, len);
+	default: {
+		const uint8_t *ptr = buf;
+		int i;
+
+		for (i = 0; i < len; i++)
+			iowrite8(ptr[i], ioaddr + i);
 		break;
 	}
+	}
 }
 
 /* config->{get,set}_status() implementations */
@@ -237,8 +261,8 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	struct virtio_pci_vq_info *info;
 	struct virtqueue *vq;
-	int err;
 	u16 num;
+	int err;
 
 	/* Select the queue we're interested in */
 	iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
@@ -257,25 +281,14 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
 	info->queue_index = index;
 	info->num = num;
 
-	/* determine the memory needed for the queue and provide the memory
-	 * location to the host */
-	info->n_pages = DIV_ROUND_UP(vring_size(num), PAGE_SIZE);
-	info->pages = alloc_pages(GFP_KERNEL | __GFP_ZERO,
-				  get_order(info->n_pages));
-	if (info->pages == NULL) {
-		err = -ENOMEM;
-		goto out_info;
-	}
-
-	/* FIXME: is this sufficient for info->n_pages > 1? */
-	info->queue = kmap(info->pages);
+	info->queue = kmalloc(vring_size(num), GFP_KERNEL | __GFP_ZERO);
 	if (info->queue == NULL) {
 		err = -ENOMEM;
-		goto out_alloc_pages;
+		goto out_info;
 	}
 
 	/* activate the queue */
-	iowrite32(page_to_pfn(info->pages),
+	iowrite32(virt_to_phys(info->queue) >> PAGE_SHIFT,
 		  vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
 		  
 	/* create the vring */
@@ -297,9 +310,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
 
 out_activate_queue:
 	iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
-	kunmap(info->queue);
-out_alloc_pages:
-	__free_pages(info->pages, get_order(info->n_pages));
+	kfree(info->queue);
 out_info:
 	kfree(info);
 	return ERR_PTR(err);
@@ -319,10 +330,9 @@ static void vp_del_vq(struct virtqueue *vq)
 
 	/* Select and deactivate the queue */
 	iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
-	iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
+	iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
 
-	kunmap(info->queue);
-	__free_pages(info->pages, get_order(info->n_pages));
+	kfree(info->queue);
 	kfree(info);
 }
 
@@ -348,10 +358,13 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
 	if (vp_dev == NULL)
 		return -ENOMEM;
 
-	vp_dev->pci_dev = pci_dev;
+	snprintf(vp_dev->vdev.dev.bus_id, BUS_ID_SIZE, "virtio%d", dev_index);
+	vp_dev->vdev.index = dev_index;
+	dev_index++;
+
 	vp_dev->vdev.dev.parent = &virtio_pci_root;
-	vp_dev->vdev.index = dev_index++;
 	vp_dev->vdev.config = &virtio_pci_config_ops;
+	vp_dev->pci_dev = pci_dev;
 	INIT_LIST_HEAD(&vp_dev->virtqueues);
 	spin_lock_init(&vp_dev->lock);
 
@@ -379,7 +392,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
 
 	/* register a handler for the queue with the PCI device's interrupt */
 	err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED,
-			  pci_name(vp_dev->pci_dev), vp_dev);
+			  vp_dev->vdev.dev.bus_id, vp_dev);
 	if (err)
 		goto out_set_drvdata;
 
diff --git a/include/linux/virtio_pci.h b/include/linux/virtio_pci.h
index b1a1568..4b28409 100644
--- a/include/linux/virtio_pci.h
+++ b/include/linux/virtio_pci.h
@@ -1,3 +1,19 @@
+/*
+ * Virtio PCI driver
+ *
+ * This module allows virtio devices to be used over a virtual PCI device.
+ * This can be used with QEMU based VMMs like KVM or Xen.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ *  Anthony Liguori  <aliguori@xxxxxxxxxx>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
 #ifndef _LINUX_VIRTIO_PCI_H
 #define _LINUX_VIRTIO_PCI_H
 
_______________________________________________
Virtualization mailing list
Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/virtualization

[Index of Archives]     [KVM Development]     [Libvirt Development]     [Libvirt Users]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux