diff options
Diffstat (limited to 'drivers/virtio')
-rw-r--r-- | drivers/virtio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/virtio/virtio_mmio.c | 2 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci_common.c | 201 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci_common.h | 1 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci_modern.c | 8 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 6 |
6 files changed, 110 insertions, 110 deletions
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 77590320d44c..623f72334fa5 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -75,7 +75,7 @@ config VIRTIO_MMIO_CMDLINE_DEVICES Allow virtio-mmio devices instantiation via the kernel command line or module parameters. Be aware that using incorrect parameters (base address in particular) can crash your system - you have been warned. - See Documentation/kernel-parameters.txt for details. + See Documentation/admin-guide/kernel-parameters.rst for details. If unsure, say 'N'. diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 48bfea91dbca..d47a2fcef818 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -489,6 +489,7 @@ static const struct virtio_config_ops virtio_mmio_config_ops = { }; +static void virtio_mmio_release_dev_empty(struct device *_d) {} /* Platform device */ @@ -511,6 +512,7 @@ static int virtio_mmio_probe(struct platform_device *pdev) return -ENOMEM; vm_dev->vdev.dev.parent = &pdev->dev; + vm_dev->vdev.dev.release = virtio_mmio_release_dev_empty; vm_dev->vdev.config = &virtio_mmio_config_ops; vm_dev->pdev = pdev; INIT_LIST_HEAD(&vm_dev->virtqueues); diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index d9a905827967..186cbab327b8 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -37,7 +37,7 @@ void vp_synchronize_vectors(struct virtio_device *vdev) synchronize_irq(vp_dev->pci_dev->irq); for (i = 0; i < vp_dev->msix_vectors; ++i) - synchronize_irq(vp_dev->msix_entries[i].vector); + synchronize_irq(pci_irq_vector(vp_dev->pci_dev, i)); } /* the notify function used when creating a virt queue */ @@ -102,41 +102,6 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) return vp_vring_interrupt(irq, opaque); } -static void vp_free_vectors(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - int i; - - if (vp_dev->intx_enabled) { - free_irq(vp_dev->pci_dev->irq, vp_dev); - vp_dev->intx_enabled = 0; - } - - for (i = 0; i < vp_dev->msix_used_vectors; ++i) - free_irq(vp_dev->msix_entries[i].vector, vp_dev); - - for (i = 0; i < vp_dev->msix_vectors; i++) - if (vp_dev->msix_affinity_masks[i]) - free_cpumask_var(vp_dev->msix_affinity_masks[i]); - - if (vp_dev->msix_enabled) { - /* Disable the vector used for configuration */ - vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR); - - pci_disable_msix(vp_dev->pci_dev); - vp_dev->msix_enabled = 0; - } - - vp_dev->msix_vectors = 0; - vp_dev->msix_used_vectors = 0; - kfree(vp_dev->msix_names); - vp_dev->msix_names = NULL; - kfree(vp_dev->msix_entries); - vp_dev->msix_entries = NULL; - kfree(vp_dev->msix_affinity_masks); - vp_dev->msix_affinity_masks = NULL; -} - static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, bool per_vq_vectors) { @@ -147,10 +112,6 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, vp_dev->msix_vectors = nvectors; - vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries, - GFP_KERNEL); - if (!vp_dev->msix_entries) - goto error; vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names, GFP_KERNEL); if (!vp_dev->msix_names) @@ -165,12 +126,9 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, GFP_KERNEL)) goto error; - for (i = 0; i < nvectors; ++i) - vp_dev->msix_entries[i].entry = i; - - err = pci_enable_msix_exact(vp_dev->pci_dev, - vp_dev->msix_entries, nvectors); - if (err) + err = pci_alloc_irq_vectors(vp_dev->pci_dev, nvectors, nvectors, + PCI_IRQ_MSIX); + if (err < 0) goto error; vp_dev->msix_enabled = 1; @@ -178,7 +136,7 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, v = vp_dev->msix_used_vectors; snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, "%s-config", name); - err = request_irq(vp_dev->msix_entries[v].vector, + err = request_irq(pci_irq_vector(vp_dev->pci_dev, v), vp_config_changed, 0, vp_dev->msix_names[v], vp_dev); if (err) @@ -197,7 +155,7 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, v = vp_dev->msix_used_vectors; snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, "%s-virtqueues", name); - err = request_irq(vp_dev->msix_entries[v].vector, + err = request_irq(pci_irq_vector(vp_dev->pci_dev, v), vp_vring_interrupt, 0, vp_dev->msix_names[v], vp_dev); if (err) @@ -206,19 +164,6 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, } return 0; error: - vp_free_vectors(vdev); - return err; -} - -static int vp_request_intx(struct virtio_device *vdev) -{ - int err; - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, - IRQF_SHARED, dev_name(&vdev->dev), vp_dev); - if (!err) - vp_dev->intx_enabled = 1; return err; } @@ -276,67 +221,88 @@ void vp_del_vqs(struct virtio_device *vdev) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtqueue *vq, *n; - struct virtio_pci_vq_info *info; + int i; list_for_each_entry_safe(vq, n, &vdev->vqs, list) { - 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, - vq); + if (vp_dev->per_vq_vectors) { + int v = vp_dev->vqs[vq->index]->msix_vector; + + if (v != VIRTIO_MSI_NO_VECTOR) + free_irq(pci_irq_vector(vp_dev->pci_dev, v), + vq); + } vp_del_vq(vq); } vp_dev->per_vq_vectors = false; - vp_free_vectors(vdev); + if (vp_dev->intx_enabled) { + free_irq(vp_dev->pci_dev->irq, vp_dev); + vp_dev->intx_enabled = 0; + } + + for (i = 0; i < vp_dev->msix_used_vectors; ++i) + free_irq(pci_irq_vector(vp_dev->pci_dev, i), vp_dev); + + for (i = 0; i < vp_dev->msix_vectors; i++) + if (vp_dev->msix_affinity_masks[i]) + free_cpumask_var(vp_dev->msix_affinity_masks[i]); + + if (vp_dev->msix_enabled) { + /* Disable the vector used for configuration */ + vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR); + + pci_free_irq_vectors(vp_dev->pci_dev); + vp_dev->msix_enabled = 0; + } + + vp_dev->msix_vectors = 0; + vp_dev->msix_used_vectors = 0; + kfree(vp_dev->msix_names); + vp_dev->msix_names = NULL; + kfree(vp_dev->msix_affinity_masks); + vp_dev->msix_affinity_masks = NULL; kfree(vp_dev->vqs); vp_dev->vqs = NULL; } -static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, +static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], const char * const names[], - bool use_msix, bool per_vq_vectors) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); u16 msix_vec; int i, err, nvectors, allocated_vectors; - vp_dev->vqs = kmalloc(nvqs * sizeof *vp_dev->vqs, GFP_KERNEL); + vp_dev->vqs = kcalloc(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_find; + if (per_vq_vectors) { + /* Best option: one for change interrupt, one per vq. */ + nvectors = 1; + for (i = 0; i < nvqs; ++i) + if (callbacks[i]) + ++nvectors; } else { - if (per_vq_vectors) { - /* Best option: one for change interrupt, one per vq. */ - nvectors = 1; - for (i = 0; i < nvqs; ++i) - if (callbacks[i]) - ++nvectors; - } else { - /* Second best: one for change, shared for all vqs. */ - nvectors = 2; - } - - err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); - if (err) - goto error_find; + /* Second best: one for change, shared for all vqs. */ + nvectors = 2; } + err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); + if (err) + goto error_find; + vp_dev->per_vq_vectors = per_vq_vectors; allocated_vectors = vp_dev->msix_used_vectors; for (i = 0; i < nvqs; ++i) { if (!names[i]) { vqs[i] = NULL; continue; - } else if (!callbacks[i] || !vp_dev->msix_enabled) + } + + if (!callbacks[i]) msix_vec = VIRTIO_MSI_NO_VECTOR; else if (vp_dev->per_vq_vectors) msix_vec = allocated_vectors++; @@ -356,14 +322,12 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, sizeof *vp_dev->msix_names, "%s-%s", dev_name(&vp_dev->vdev.dev), names[i]); - err = request_irq(vp_dev->msix_entries[msix_vec].vector, + err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec), vring_interrupt, 0, vp_dev->msix_names[msix_vec], vqs[i]); - if (err) { - vp_del_vq(vqs[i]); + if (err) goto error_find; - } } return 0; @@ -372,6 +336,43 @@ error_find: return err; } +static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs, + struct virtqueue *vqs[], vq_callback_t *callbacks[], + const char * const names[]) +{ + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + int i, err; + + vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); + if (!vp_dev->vqs) + return -ENOMEM; + + err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, + dev_name(&vdev->dev), vp_dev); + if (err) + goto out_del_vqs; + + vp_dev->intx_enabled = 1; + vp_dev->per_vq_vectors = false; + for (i = 0; i < nvqs; ++i) { + if (!names[i]) { + vqs[i] = NULL; + continue; + } + vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], + VIRTIO_MSI_NO_VECTOR); + if (IS_ERR(vqs[i])) { + err = PTR_ERR(vqs[i]); + goto out_del_vqs; + } + } + + return 0; +out_del_vqs: + vp_del_vqs(vdev); + return err; +} + /* the config->find_vqs() implementation */ int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, struct virtqueue *vqs[], @@ -381,17 +382,15 @@ int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, int err; /* Try MSI-X with one vector per queue. */ - err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, true, true); + err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true); if (!err) return 0; /* Fallback: MSI-X with one vector for config, one shared for queues. */ - err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, - true, false); + err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false); if (!err) return 0; /* Finally fall back to regular interrupts. */ - return vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, - false, false); + return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names); } const char *vp_bus_name(struct virtio_device *vdev) @@ -419,7 +418,7 @@ int vp_set_vq_affinity(struct virtqueue *vq, int cpu) if (vp_dev->msix_enabled) { mask = vp_dev->msix_affinity_masks[info->msix_vector]; - irq = vp_dev->msix_entries[info->msix_vector].vector; + irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector); if (cpu == -1) irq_set_affinity_hint(irq, NULL); else { diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index 28263200ed42..b2f666250ae0 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h @@ -85,7 +85,6 @@ struct virtio_pci_device { /* MSI-X support */ int msix_enabled; int intx_enabled; - struct msix_entry *msix_entries; cpumask_var_t *msix_affinity_masks; /* Name strings for interrupts. This size should be enough, * and I'm too lazy to allocate each name separately. */ diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index e76bd91a29da..4bf7ab375894 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -33,12 +33,12 @@ static inline u8 vp_ioread8(u8 __iomem *addr) { return ioread8(addr); } -static inline u16 vp_ioread16 (u16 __iomem *addr) +static inline u16 vp_ioread16 (__le16 __iomem *addr) { return ioread16(addr); } -static inline u32 vp_ioread32(u32 __iomem *addr) +static inline u32 vp_ioread32(__le32 __iomem *addr) { return ioread32(addr); } @@ -48,12 +48,12 @@ static inline void vp_iowrite8(u8 value, u8 __iomem *addr) iowrite8(value, addr); } -static inline void vp_iowrite16(u16 value, u16 __iomem *addr) +static inline void vp_iowrite16(u16 value, __le16 __iomem *addr) { iowrite16(value, addr); } -static inline void vp_iowrite32(u32 value, u32 __iomem *addr) +static inline void vp_iowrite32(u32 value, __le32 __iomem *addr) { iowrite32(value, addr); } diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 489bfc61cf30..409aeaa49246 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -420,7 +420,7 @@ unmap_release: if (i == err_idx) break; vring_unmap_one(vq, &desc[i]); - i = vq->vring.desc[i].next; + i = virtio16_to_cpu(_vq->vdev, vq->vring.desc[i].next); } vq->vq.num_free += total_sg; @@ -601,7 +601,7 @@ EXPORT_SYMBOL_GPL(virtqueue_kick); static void detach_buf(struct vring_virtqueue *vq, unsigned int head) { unsigned int i, j; - u16 nextflag = cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT); + __virtio16 nextflag = cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT); /* Clear data ptr. */ vq->desc_state[head].data = NULL; @@ -649,7 +649,7 @@ static inline bool more_used(const struct vring_virtqueue *vq) * @vq: the struct virtqueue we're talking about. * @len: the length written into the buffer * - * If the driver wrote data into the buffer, @len will be set to the + * If the device wrote data into the buffer, @len will be set to the * amount written. This means you don't need to clear the buffer * beforehand to ensure there's no data leakage in the case of short * writes. |