@@ -771,6 +771,14 @@ void vfio_device_group_unregister(struct vfio_device *device)
mutex_unlock(&device->group->device_lock);
}
+/* No group lock since df->group and df->group->container cannot change */
+bool vfio_device_group_uses_container(struct vfio_device_file *df)
+{
+ if (WARN_ON(!df->group))
+ return false;
+ return READ_ONCE(df->group->container);
+}
+
int vfio_device_group_use_iommu(struct vfio_device *device)
{
struct vfio_group *group = device->group;
@@ -95,6 +95,7 @@ int vfio_device_set_group(struct vfio_device *device,
void vfio_device_remove_group(struct vfio_device *device);
void vfio_device_group_register(struct vfio_device *device);
void vfio_device_group_unregister(struct vfio_device *device);
+bool vfio_device_group_uses_container(struct vfio_device_file *df);
int vfio_device_group_use_iommu(struct vfio_device *device);
void vfio_device_group_unuse_iommu(struct vfio_device *device);
void vfio_device_group_close(struct vfio_device_file *df);
@@ -423,16 +423,20 @@ static int vfio_device_first_open(struct vfio_device_file *df)
{
struct vfio_device *device = df->device;
struct iommufd_ctx *iommufd = df->iommufd;
- int ret;
+ int ret = 0;
lockdep_assert_held(&device->dev_set->lock);
if (!try_module_get(device->dev->driver->owner))
return -ENODEV;
+ /*
+ * if neither iommufd nor container is used the device is in
+ * noiommu mode then just go ahead to open it.
+ */
if (iommufd)
ret = vfio_iommufd_bind(device, iommufd);
- else
+ else if (vfio_device_group_uses_container(df))
ret = vfio_device_group_use_iommu(device);
if (ret)
goto err_module_put;
@@ -447,7 +451,7 @@ static int vfio_device_first_open(struct vfio_device_file *df)
err_unuse_iommu:
if (iommufd)
vfio_iommufd_unbind(device);
- else
+ else if (vfio_device_group_uses_container(df))
vfio_device_group_unuse_iommu(device);
err_module_put:
module_put(device->dev->driver->owner);
@@ -465,7 +469,7 @@ static void vfio_device_last_close(struct vfio_device_file *df)
device->ops->close_device(device);
if (iommufd)
vfio_iommufd_unbind(device);
- else
+ else if (vfio_device_group_uses_container(df))
vfio_device_group_unuse_iommu(device);
module_put(device->dev->driver->owner);
}