aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2015-02-06 17:05:06 -0500
committerAlex Williamson <alex.williamson@redhat.com>2015-02-06 17:05:06 -0500
commit4a68810dbbb4664fe4a9ac1be4d1c0e34a9b58f5 (patch)
tree991c071b48d4e049f6cf800a5fea12a6dfe989e2 /drivers/vfio
parent60720a0fc6469e8f924f85510c2a24ecc7bdaf9c (diff)
vfio: Tie IOMMU group reference to vfio group
Move the iommu_group reference from the device to the vfio_group. This ensures that the iommu_group persists as long as the vfio_group remains. This can be important if all of the device from an iommu_group are removed, but we still have an outstanding vfio_group reference; we can still walk the empty list of devices. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/vfio.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 43d5622b19b7..13e0f39d91e0 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -274,6 +274,7 @@ static void vfio_group_release(struct kref *kref)
274{ 274{
275 struct vfio_group *group = container_of(kref, struct vfio_group, kref); 275 struct vfio_group *group = container_of(kref, struct vfio_group, kref);
276 struct vfio_unbound_dev *unbound, *tmp; 276 struct vfio_unbound_dev *unbound, *tmp;
277 struct iommu_group *iommu_group = group->iommu_group;
277 278
278 WARN_ON(!list_empty(&group->device_list)); 279 WARN_ON(!list_empty(&group->device_list));
279 280
@@ -287,6 +288,7 @@ static void vfio_group_release(struct kref *kref)
287 list_del(&group->vfio_next); 288 list_del(&group->vfio_next);
288 vfio_free_group_minor(group->minor); 289 vfio_free_group_minor(group->minor);
289 vfio_group_unlock_and_free(group); 290 vfio_group_unlock_and_free(group);
291 iommu_group_put(iommu_group);
290} 292}
291 293
292static void vfio_group_put(struct vfio_group *group) 294static void vfio_group_put(struct vfio_group *group)
@@ -625,6 +627,12 @@ int vfio_add_group_dev(struct device *dev,
625 iommu_group_put(iommu_group); 627 iommu_group_put(iommu_group);
626 return PTR_ERR(group); 628 return PTR_ERR(group);
627 } 629 }
630 } else {
631 /*
632 * A found vfio_group already holds a reference to the
633 * iommu_group. A created vfio_group keeps the reference.
634 */
635 iommu_group_put(iommu_group);
628 } 636 }
629 637
630 device = vfio_group_get_device(group, dev); 638 device = vfio_group_get_device(group, dev);
@@ -633,21 +641,19 @@ int vfio_add_group_dev(struct device *dev,
633 dev_name(dev), iommu_group_id(iommu_group)); 641 dev_name(dev), iommu_group_id(iommu_group));
634 vfio_device_put(device); 642 vfio_device_put(device);
635 vfio_group_put(group); 643 vfio_group_put(group);
636 iommu_group_put(iommu_group);
637 return -EBUSY; 644 return -EBUSY;
638 } 645 }
639 646
640 device = vfio_group_create_device(group, dev, ops, device_data); 647 device = vfio_group_create_device(group, dev, ops, device_data);
641 if (IS_ERR(device)) { 648 if (IS_ERR(device)) {
642 vfio_group_put(group); 649 vfio_group_put(group);
643 iommu_group_put(iommu_group);
644 return PTR_ERR(device); 650 return PTR_ERR(device);
645 } 651 }
646 652
647 /* 653 /*
648 * Added device holds reference to iommu_group and vfio_device 654 * Drop all but the vfio_device reference. The vfio_device holds
649 * (which in turn holds reference to vfio_group). Drop extra 655 * a reference to the vfio_group, which holds a reference to the
650 * group reference used while acquiring device. 656 * iommu_group.
651 */ 657 */
652 vfio_group_put(group); 658 vfio_group_put(group);
653 659
@@ -702,7 +708,6 @@ void *vfio_del_group_dev(struct device *dev)
702{ 708{
703 struct vfio_device *device = dev_get_drvdata(dev); 709 struct vfio_device *device = dev_get_drvdata(dev);
704 struct vfio_group *group = device->group; 710 struct vfio_group *group = device->group;
705 struct iommu_group *iommu_group = group->iommu_group;
706 void *device_data = device->device_data; 711 void *device_data = device->device_data;
707 struct vfio_unbound_dev *unbound; 712 struct vfio_unbound_dev *unbound;
708 713
@@ -737,8 +742,6 @@ void *vfio_del_group_dev(struct device *dev)
737 742
738 vfio_group_put(group); 743 vfio_group_put(group);
739 744
740 iommu_group_put(iommu_group);
741
742 return device_data; 745 return device_data;
743} 746}
744EXPORT_SYMBOL_GPL(vfio_del_group_dev); 747EXPORT_SYMBOL_GPL(vfio_del_group_dev);