Commit 1362591f authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Alex Williamson
Browse files

vfio: factor out a vfio_group_find_or_alloc helper



Factor out a helper to find or allocate the vfio_group to reduce the
spagetthi code in vfio_register_group_dev a little.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Link: https://lore.kernel.org/r/20210924155705.4258-5-hch@lst.de


Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent c5b4ba97
Loading
Loading
Loading
Loading
+35 −25
Original line number Diff line number Diff line
@@ -823,49 +823,59 @@ void vfio_uninit_group_dev(struct vfio_device *device)
}
EXPORT_SYMBOL_GPL(vfio_uninit_group_dev);

int vfio_register_group_dev(struct vfio_device *device)
struct vfio_group *vfio_group_find_or_alloc(struct device *dev)
{
	struct vfio_device *existing_device;
	struct iommu_group *iommu_group;
	struct vfio_group *group;

	/*
	 * If the driver doesn't specify a set then the device is added to a
	 * singleton set just for itself.
	 */
	if (!device->dev_set)
		vfio_assign_device_set(device, device);

	iommu_group = vfio_iommu_group_get(device->dev);
	iommu_group = vfio_iommu_group_get(dev);
	if (!iommu_group)
		return -EINVAL;
		return ERR_PTR(-EINVAL);

	/* a found vfio_group already holds a reference to the iommu_group */
	group = vfio_group_get_from_iommu(iommu_group);
	if (!group) {
	if (group)
		goto out_put;

	/* a newly created vfio_group keeps the reference. */
	group = vfio_create_group(iommu_group);
		if (IS_ERR(group)) {
	if (IS_ERR(group))
		goto out_remove;
	return group;

out_remove:
#ifdef CONFIG_VFIO_NOIOMMU
	if (iommu_group_get_iommudata(iommu_group) == &noiommu)
				iommu_group_remove_device(device->dev);
		iommu_group_remove_device(dev);
#endif
out_put:
	iommu_group_put(iommu_group);
			return PTR_ERR(group);
	return group;
}
	} else {

int vfio_register_group_dev(struct vfio_device *device)
{
	struct vfio_device *existing_device;
	struct vfio_group *group;

	/*
		 * A found vfio_group already holds a reference to the
		 * iommu_group.  A created vfio_group keeps the reference.
	 * If the driver doesn't specify a set then the device is added to a
	 * singleton set just for itself.
	 */
		iommu_group_put(iommu_group);
	}
	if (!device->dev_set)
		vfio_assign_device_set(device, device);

	group = vfio_group_find_or_alloc(device->dev);
	if (IS_ERR(group))
		return PTR_ERR(group);

	existing_device = vfio_group_get_device(group, device->dev);
	if (existing_device) {
		dev_WARN(device->dev, "Device already exists on group %d\n",
			 iommu_group_id(iommu_group));
			 iommu_group_id(group->iommu_group));
		vfio_device_put(existing_device);
#ifdef CONFIG_VFIO_NOIOMMU
		if (iommu_group_get_iommudata(iommu_group) == &noiommu)
		if (iommu_group_get_iommudata(group->iommu_group) == &noiommu)
			iommu_group_remove_device(device->dev);
#endif
		vfio_group_put(group);