diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2015-02-06 17:05:06 -0500 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2015-02-06 17:05:06 -0500 |
commit | 4a68810dbbb4664fe4a9ac1be4d1c0e34a9b58f5 (patch) | |
tree | 991c071b48d4e049f6cf800a5fea12a6dfe989e2 /drivers/vfio | |
parent | 60720a0fc6469e8f924f85510c2a24ecc7bdaf9c (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.c | 19 |
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 | ||
292 | static void vfio_group_put(struct vfio_group *group) | 294 | static 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 | } |
744 | EXPORT_SYMBOL_GPL(vfio_del_group_dev); | 747 | EXPORT_SYMBOL_GPL(vfio_del_group_dev); |