diff options
-rw-r--r-- | drivers/virtio/virtio_pci.c | 56 |
1 files changed, 31 insertions, 25 deletions
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 6f3db1f89654..6a7b8bff51e5 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
@@ -31,6 +31,23 @@ MODULE_DESCRIPTION("virtio-pci"); | |||
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | MODULE_VERSION("1"); | 32 | MODULE_VERSION("1"); |
33 | 33 | ||
34 | struct virtio_pci_vq_info { | ||
35 | /* the actual virtqueue */ | ||
36 | struct virtqueue *vq; | ||
37 | |||
38 | /* the number of entries in the queue */ | ||
39 | int num; | ||
40 | |||
41 | /* the virtual address of the ring queue */ | ||
42 | void *queue; | ||
43 | |||
44 | /* the list node for the virtqueues list */ | ||
45 | struct list_head node; | ||
46 | |||
47 | /* MSI-X vector (or none) */ | ||
48 | unsigned msix_vector; | ||
49 | }; | ||
50 | |||
34 | /* Our device structure */ | 51 | /* Our device structure */ |
35 | struct virtio_pci_device { | 52 | struct virtio_pci_device { |
36 | struct virtio_device vdev; | 53 | struct virtio_device vdev; |
@@ -46,6 +63,9 @@ struct virtio_pci_device { | |||
46 | spinlock_t lock; | 63 | spinlock_t lock; |
47 | struct list_head virtqueues; | 64 | struct list_head virtqueues; |
48 | 65 | ||
66 | /* array of all queues for house-keeping */ | ||
67 | struct virtio_pci_vq_info **vqs; | ||
68 | |||
49 | /* MSI-X support */ | 69 | /* MSI-X support */ |
50 | int msix_enabled; | 70 | int msix_enabled; |
51 | int intx_enabled; | 71 | int intx_enabled; |
@@ -71,23 +91,6 @@ enum { | |||
71 | VP_MSIX_VQ_VECTOR = 1, | 91 | VP_MSIX_VQ_VECTOR = 1, |
72 | }; | 92 | }; |
73 | 93 | ||
74 | struct virtio_pci_vq_info { | ||
75 | /* the actual virtqueue */ | ||
76 | struct virtqueue *vq; | ||
77 | |||
78 | /* the number of entries in the queue */ | ||
79 | int num; | ||
80 | |||
81 | /* the virtual address of the ring queue */ | ||
82 | void *queue; | ||
83 | |||
84 | /* the list node for the virtqueues list */ | ||
85 | struct list_head node; | ||
86 | |||
87 | /* MSI-X vector (or none) */ | ||
88 | unsigned msix_vector; | ||
89 | }; | ||
90 | |||
91 | /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ | 94 | /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ |
92 | static const struct pci_device_id virtio_pci_id_table[] = { | 95 | static const struct pci_device_id virtio_pci_id_table[] = { |
93 | { PCI_DEVICE(0x1af4, PCI_ANY_ID) }, | 96 | { PCI_DEVICE(0x1af4, PCI_ANY_ID) }, |
@@ -434,7 +437,6 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, | |||
434 | goto out_activate_queue; | 437 | goto out_activate_queue; |
435 | } | 438 | } |
436 | 439 | ||
437 | vq->priv = info; | ||
438 | info->vq = vq; | 440 | info->vq = vq; |
439 | 441 | ||
440 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { | 442 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { |
@@ -454,6 +456,7 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, | |||
454 | INIT_LIST_HEAD(&info->node); | 456 | INIT_LIST_HEAD(&info->node); |
455 | } | 457 | } |
456 | 458 | ||
459 | vp_dev->vqs[index] = info; | ||
457 | return vq; | 460 | return vq; |
458 | 461 | ||
459 | out_assign: | 462 | out_assign: |
@@ -469,7 +472,7 @@ out_info: | |||
469 | static void vp_del_vq(struct virtqueue *vq) | 472 | static void vp_del_vq(struct virtqueue *vq) |
470 | { | 473 | { |
471 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | 474 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); |
472 | struct virtio_pci_vq_info *info = vq->priv; | 475 | struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index]; |
473 | unsigned long flags, size; | 476 | unsigned long flags, size; |
474 | 477 | ||
475 | spin_lock_irqsave(&vp_dev->lock, flags); | 478 | spin_lock_irqsave(&vp_dev->lock, flags); |
@@ -503,7 +506,7 @@ static void vp_del_vqs(struct virtio_device *vdev) | |||
503 | struct virtio_pci_vq_info *info; | 506 | struct virtio_pci_vq_info *info; |
504 | 507 | ||
505 | list_for_each_entry_safe(vq, n, &vdev->vqs, list) { | 508 | list_for_each_entry_safe(vq, n, &vdev->vqs, list) { |
506 | info = vq->priv; | 509 | info = vp_dev->vqs[vq->index]; |
507 | if (vp_dev->per_vq_vectors && | 510 | if (vp_dev->per_vq_vectors && |
508 | info->msix_vector != VIRTIO_MSI_NO_VECTOR) | 511 | info->msix_vector != VIRTIO_MSI_NO_VECTOR) |
509 | free_irq(vp_dev->msix_entries[info->msix_vector].vector, | 512 | free_irq(vp_dev->msix_entries[info->msix_vector].vector, |
@@ -513,6 +516,7 @@ static void vp_del_vqs(struct virtio_device *vdev) | |||
513 | vp_dev->per_vq_vectors = false; | 516 | vp_dev->per_vq_vectors = false; |
514 | 517 | ||
515 | vp_free_vectors(vdev); | 518 | vp_free_vectors(vdev); |
519 | kfree(vp_dev->vqs); | ||
516 | } | 520 | } |
517 | 521 | ||
518 | static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, | 522 | static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, |
@@ -526,11 +530,15 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
526 | u16 msix_vec; | 530 | u16 msix_vec; |
527 | int i, err, nvectors, allocated_vectors; | 531 | int i, err, nvectors, allocated_vectors; |
528 | 532 | ||
533 | vp_dev->vqs = kmalloc(nvqs * sizeof *vp_dev->vqs, GFP_KERNEL); | ||
534 | if (!vp_dev->vqs) | ||
535 | return -ENOMEM; | ||
536 | |||
529 | if (!use_msix) { | 537 | if (!use_msix) { |
530 | /* Old style: one normal interrupt for change and all vqs. */ | 538 | /* Old style: one normal interrupt for change and all vqs. */ |
531 | err = vp_request_intx(vdev); | 539 | err = vp_request_intx(vdev); |
532 | if (err) | 540 | if (err) |
533 | goto error_request; | 541 | goto error_find; |
534 | } else { | 542 | } else { |
535 | if (per_vq_vectors) { | 543 | if (per_vq_vectors) { |
536 | /* Best option: one for change interrupt, one per vq. */ | 544 | /* Best option: one for change interrupt, one per vq. */ |
@@ -545,7 +553,7 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
545 | 553 | ||
546 | err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); | 554 | err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); |
547 | if (err) | 555 | if (err) |
548 | goto error_request; | 556 | goto error_find; |
549 | } | 557 | } |
550 | 558 | ||
551 | vp_dev->per_vq_vectors = per_vq_vectors; | 559 | vp_dev->per_vq_vectors = per_vq_vectors; |
@@ -587,8 +595,6 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
587 | 595 | ||
588 | error_find: | 596 | error_find: |
589 | vp_del_vqs(vdev); | 597 | vp_del_vqs(vdev); |
590 | |||
591 | error_request: | ||
592 | return err; | 598 | return err; |
593 | } | 599 | } |
594 | 600 | ||
@@ -630,7 +636,7 @@ static int vp_set_vq_affinity(struct virtqueue *vq, int cpu) | |||
630 | { | 636 | { |
631 | struct virtio_device *vdev = vq->vdev; | 637 | struct virtio_device *vdev = vq->vdev; |
632 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 638 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
633 | struct virtio_pci_vq_info *info = vq->priv; | 639 | struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index]; |
634 | struct cpumask *mask; | 640 | struct cpumask *mask; |
635 | unsigned int irq; | 641 | unsigned int irq; |
636 | 642 | ||