Commit ff52c3fc authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Rusty Russell

virtio: fix memory leak on device removal

Make vp_free_vectors do the reverse of vq_request_vectors.
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 8ef562d1
...@@ -258,7 +258,6 @@ static void vp_free_vectors(struct virtio_device *vdev) ...@@ -258,7 +258,6 @@ static void vp_free_vectors(struct virtio_device *vdev)
for (i = 0; i < vp_dev->msix_used_vectors; ++i) for (i = 0; i < vp_dev->msix_used_vectors; ++i)
free_irq(vp_dev->msix_entries[i].vector, vp_dev); free_irq(vp_dev->msix_entries[i].vector, vp_dev);
vp_dev->msix_used_vectors = 0;
if (vp_dev->msix_enabled) { if (vp_dev->msix_enabled) {
/* Disable the vector used for configuration */ /* Disable the vector used for configuration */
...@@ -267,9 +266,16 @@ static void vp_free_vectors(struct virtio_device *vdev) ...@@ -267,9 +266,16 @@ static void vp_free_vectors(struct virtio_device *vdev)
/* Flush the write out to device */ /* Flush the write out to device */
ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
vp_dev->msix_enabled = 0;
pci_disable_msix(vp_dev->pci_dev); 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;
} }
static int vp_enable_msix(struct pci_dev *dev, struct msix_entry *entries, static int vp_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
...@@ -297,11 +303,11 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs) ...@@ -297,11 +303,11 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries, vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries,
GFP_KERNEL); GFP_KERNEL);
if (!vp_dev->msix_entries) if (!vp_dev->msix_entries)
goto error_entries; goto error;
vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names, vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names,
GFP_KERNEL); GFP_KERNEL);
if (!vp_dev->msix_names) if (!vp_dev->msix_names)
goto error_names; goto error;
for (i = 0; i < nvectors; ++i) for (i = 0; i < nvectors; ++i)
vp_dev->msix_entries[i].entry = i; vp_dev->msix_entries[i].entry = i;
...@@ -314,7 +320,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs) ...@@ -314,7 +320,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, err = request_irq(vp_dev->pci_dev->irq, vp_interrupt,
IRQF_SHARED, name, vp_dev); IRQF_SHARED, name, vp_dev);
if (err) if (err)
goto error_irq; goto error;
vp_dev->intx_enabled = 1; vp_dev->intx_enabled = 1;
} else { } else {
vp_dev->msix_vectors = err; vp_dev->msix_vectors = err;
...@@ -328,7 +334,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs) ...@@ -328,7 +334,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
vp_config_changed, 0, vp_dev->msix_names[v], vp_config_changed, 0, vp_dev->msix_names[v],
vp_dev); vp_dev);
if (err) if (err)
goto error_irq; goto error;
++vp_dev->msix_used_vectors; ++vp_dev->msix_used_vectors;
iowrite16(v, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); iowrite16(v, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
...@@ -336,7 +342,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs) ...@@ -336,7 +342,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
v = ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); v = ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
if (v == VIRTIO_MSI_NO_VECTOR) { if (v == VIRTIO_MSI_NO_VECTOR) {
err = -EBUSY; err = -EBUSY;
goto error_irq; goto error;
} }
} }
...@@ -349,16 +355,12 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs) ...@@ -349,16 +355,12 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
vp_vring_interrupt, 0, vp_dev->msix_names[v], vp_vring_interrupt, 0, vp_dev->msix_names[v],
vp_dev); vp_dev);
if (err) if (err)
goto error_irq; goto error;
++vp_dev->msix_used_vectors; ++vp_dev->msix_used_vectors;
} }
return 0; return 0;
error_irq: error:
vp_free_vectors(vdev); vp_free_vectors(vdev);
kfree(vp_dev->msix_names);
error_names:
kfree(vp_dev->msix_entries);
error_entries:
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment