aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/pci/vfio_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio/pci/vfio_pci.c')
-rw-r--r--drivers/vfio/pci/vfio_pci.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index b0f759476900..c6822149b394 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -305,6 +305,7 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
305{ 305{
306 struct pci_dev *pdev = vdev->pdev; 306 struct pci_dev *pdev = vdev->pdev;
307 struct vfio_pci_dummy_resource *dummy_res, *tmp; 307 struct vfio_pci_dummy_resource *dummy_res, *tmp;
308 struct vfio_pci_ioeventfd *ioeventfd, *ioeventfd_tmp;
308 int i, bar; 309 int i, bar;
309 310
310 /* Stop the device from further DMA */ 311 /* Stop the device from further DMA */
@@ -314,6 +315,15 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
314 VFIO_IRQ_SET_ACTION_TRIGGER, 315 VFIO_IRQ_SET_ACTION_TRIGGER,
315 vdev->irq_type, 0, 0, NULL); 316 vdev->irq_type, 0, 0, NULL);
316 317
318 /* Device closed, don't need mutex here */
319 list_for_each_entry_safe(ioeventfd, ioeventfd_tmp,
320 &vdev->ioeventfds_list, next) {
321 vfio_virqfd_disable(&ioeventfd->virqfd);
322 list_del(&ioeventfd->next);
323 kfree(ioeventfd);
324 }
325 vdev->ioeventfds_nr = 0;
326
317 vdev->virq_disabled = false; 327 vdev->virq_disabled = false;
318 328
319 for (i = 0; i < vdev->num_regions; i++) 329 for (i = 0; i < vdev->num_regions; i++)
@@ -1012,6 +1022,28 @@ hot_reset_release:
1012 1022
1013 kfree(groups); 1023 kfree(groups);
1014 return ret; 1024 return ret;
1025 } else if (cmd == VFIO_DEVICE_IOEVENTFD) {
1026 struct vfio_device_ioeventfd ioeventfd;
1027 int count;
1028
1029 minsz = offsetofend(struct vfio_device_ioeventfd, fd);
1030
1031 if (copy_from_user(&ioeventfd, (void __user *)arg, minsz))
1032 return -EFAULT;
1033
1034 if (ioeventfd.argsz < minsz)
1035 return -EINVAL;
1036
1037 if (ioeventfd.flags & ~VFIO_DEVICE_IOEVENTFD_SIZE_MASK)
1038 return -EINVAL;
1039
1040 count = ioeventfd.flags & VFIO_DEVICE_IOEVENTFD_SIZE_MASK;
1041
1042 if (hweight8(count) != 1 || ioeventfd.fd < -1)
1043 return -EINVAL;
1044
1045 return vfio_pci_ioeventfd(vdev, ioeventfd.offset,
1046 ioeventfd.data, count, ioeventfd.fd);
1015 } 1047 }
1016 1048
1017 return -ENOTTY; 1049 return -ENOTTY;
@@ -1174,6 +1206,8 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1174 vdev->irq_type = VFIO_PCI_NUM_IRQS; 1206 vdev->irq_type = VFIO_PCI_NUM_IRQS;
1175 mutex_init(&vdev->igate); 1207 mutex_init(&vdev->igate);
1176 spin_lock_init(&vdev->irqlock); 1208 spin_lock_init(&vdev->irqlock);
1209 mutex_init(&vdev->ioeventfds_lock);
1210 INIT_LIST_HEAD(&vdev->ioeventfds_list);
1177 1211
1178 ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev); 1212 ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
1179 if (ret) { 1213 if (ret) {
@@ -1215,6 +1249,7 @@ static void vfio_pci_remove(struct pci_dev *pdev)
1215 1249
1216 vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev); 1250 vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
1217 kfree(vdev->region); 1251 kfree(vdev->region);
1252 mutex_destroy(&vdev->ioeventfds_lock);
1218 kfree(vdev); 1253 kfree(vdev);
1219 1254
1220 if (vfio_pci_is_vga(pdev)) { 1255 if (vfio_pci_is_vga(pdev)) {