@@ -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);
}
vfio_device_first_open() requires the caller to provide either a valid iommufd (the group path in iommufd compat mode) or a valid container (the group path in legacy container mode). As preparation for noiommu support in device cdev path it's extended to allow both being NULL. The caller is expected to verify noiommu permission before passing NULL to this function. Signed-off-by: Yi Liu <yi.l.liu@intel.com> --- drivers/vfio/group.c | 8 ++++++++ drivers/vfio/vfio.h | 1 + drivers/vfio/vfio_main.c | 12 ++++++++---- 3 files changed, 17 insertions(+), 4 deletions(-)