MODULE_LICENSE("GPL");
MODULE_VERSION("1");
+struct virtio_pci_vq_info {
+ /* the actual virtqueue */
+ struct virtqueue *vq;
+
+ /* the number of entries in the queue */
+ int num;
+
+ /* the virtual address of the ring queue */
+ void *queue;
+
+ /* the list node for the virtqueues list */
+ struct list_head node;
+
+ /* MSI-X vector (or none) */
+ unsigned msix_vector;
+};
+
/* Our device structure */
struct virtio_pci_device {
struct virtio_device vdev;
spinlock_t lock;
struct list_head virtqueues;
+ /* array of all queues for house-keeping */
+ struct virtio_pci_vq_info **vqs;
+
/* MSI-X support */
int msix_enabled;
int intx_enabled;
VP_MSIX_VQ_VECTOR = 1,
};
-struct virtio_pci_vq_info {
- /* the actual virtqueue */
- struct virtqueue *vq;
-
- /* the number of entries in the queue */
- int num;
-
- /* the virtual address of the ring queue */
- void *queue;
-
- /* the list node for the virtqueues list */
- struct list_head node;
-
- /* MSI-X vector (or none) */
- unsigned msix_vector;
-};
-
/* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
static const struct pci_device_id virtio_pci_id_table[] = {
{ PCI_DEVICE(0x1af4, PCI_ANY_ID) },
goto out_activate_queue;
}
- vq->priv = info;
info->vq = vq;
if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
INIT_LIST_HEAD(&info->node);
}
+ vp_dev->vqs[index] = info;
return vq;
out_assign:
static void vp_del_vq(struct virtqueue *vq)
{
struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
- struct virtio_pci_vq_info *info = vq->priv;
+ struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
unsigned long flags, size;
spin_lock_irqsave(&vp_dev->lock, flags);
struct virtio_pci_vq_info *info;
list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
- info = vq->priv;
+ info = vp_dev->vqs[vq->index];
if (vp_dev->per_vq_vectors &&
info->msix_vector != VIRTIO_MSI_NO_VECTOR)
free_irq(vp_dev->msix_entries[info->msix_vector].vector,
vp_dev->per_vq_vectors = false;
vp_free_vectors(vdev);
+ kfree(vp_dev->vqs);
}
static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs,
u16 msix_vec;
int i, err, nvectors, allocated_vectors;
+ vp_dev->vqs = kmalloc(nvqs * sizeof *vp_dev->vqs, GFP_KERNEL);
+ if (!vp_dev->vqs)
+ return -ENOMEM;
+
if (!use_msix) {
/* Old style: one normal interrupt for change and all vqs. */
err = vp_request_intx(vdev);
if (err)
- goto error_request;
+ goto error_find;
} else {
if (per_vq_vectors) {
/* Best option: one for change interrupt, one per vq. */
err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors);
if (err)
- goto error_request;
+ goto error_find;
}
vp_dev->per_vq_vectors = per_vq_vectors;
error_find:
vp_del_vqs(vdev);
-
-error_request:
return err;
}
{
struct virtio_device *vdev = vq->vdev;
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
- struct virtio_pci_vq_info *info = vq->priv;
+ struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
struct cpumask *mask;
unsigned int irq;