summaryrefslogtreecommitdiff
path: root/drivers/vfio
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@nvidia.com>2022-11-29 16:31:46 -0400
committerJason Gunthorpe <jgg@nvidia.com>2022-12-02 11:52:03 -0400
commit294aaccb50130f596943be892c5d3a3568b76c57 (patch)
tree4c088ece14eebed89cc345300ef6d4687a9c5801 /drivers/vfio
parent2a54e347d990574ceb047b71ea0b03979232b85e (diff)
vfio: Move vfio_device driver open/close code to a function
This error unwind is getting complicated. Move all the code into two pair'd function. The functions should be called when the open_count == 1 after incrementing/before decrementing. Link: https://lore.kernel.org/r/1-v4-42cd2eb0e3eb+335a-vfio_iommufd_jgg@nvidia.com Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Yi Liu <yi.l.liu@intel.com> Reviewed-by: Alex Williamson <alex.williamson@redhat.com> Tested-by: Alex Williamson <alex.williamson@redhat.com> Tested-by: Yi Liu <yi.l.liu@intel.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Tested-by: Lixiao Yang <lixiao.yang@intel.com> Tested-by: Matthew Rosato <mjrosato@linux.ibm.com> Tested-by: Yu He <yu.he@intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/vfio_main.c95
1 files changed, 53 insertions, 42 deletions
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 2d168793d4e1..2e8346d13c16 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -734,6 +734,51 @@ bool vfio_assert_device_open(struct vfio_device *device)
return !WARN_ON_ONCE(!READ_ONCE(device->open_count));
}
+static int vfio_device_first_open(struct vfio_device *device)
+{
+ int ret;
+
+ lockdep_assert_held(&device->dev_set->lock);
+
+ if (!try_module_get(device->dev->driver->owner))
+ return -ENODEV;
+
+ /*
+ * Here we pass the KVM pointer with the group under the lock. If the
+ * device driver will use it, it must obtain a reference and release it
+ * during close_device.
+ */
+ mutex_lock(&device->group->group_lock);
+ device->kvm = device->group->kvm;
+ if (device->ops->open_device) {
+ ret = device->ops->open_device(device);
+ if (ret)
+ goto err_module_put;
+ }
+ vfio_device_container_register(device);
+ mutex_unlock(&device->group->group_lock);
+ return 0;
+
+err_module_put:
+ device->kvm = NULL;
+ mutex_unlock(&device->group->group_lock);
+ module_put(device->dev->driver->owner);
+ return ret;
+}
+
+static void vfio_device_last_close(struct vfio_device *device)
+{
+ lockdep_assert_held(&device->dev_set->lock);
+
+ mutex_lock(&device->group->group_lock);
+ vfio_device_container_unregister(device);
+ if (device->ops->close_device)
+ device->ops->close_device(device);
+ device->kvm = NULL;
+ mutex_unlock(&device->group->group_lock);
+ module_put(device->dev->driver->owner);
+}
+
static struct file *vfio_device_open(struct vfio_device *device)
{
struct file *filep;
@@ -745,29 +790,12 @@ static struct file *vfio_device_open(struct vfio_device *device)
if (ret)
return ERR_PTR(ret);
- if (!try_module_get(device->dev->driver->owner)) {
- ret = -ENODEV;
- goto err_unassign_container;
- }
-
mutex_lock(&device->dev_set->lock);
device->open_count++;
if (device->open_count == 1) {
- /*
- * Here we pass the KVM pointer with the group under the read
- * lock. If the device driver will use it, it must obtain a
- * reference and release it during close_device.
- */
- mutex_lock(&device->group->group_lock);
- device->kvm = device->group->kvm;
-
- if (device->ops->open_device) {
- ret = device->ops->open_device(device);
- if (ret)
- goto err_undo_count;
- }
- vfio_device_container_register(device);
- mutex_unlock(&device->group->group_lock);
+ ret = vfio_device_first_open(device);
+ if (ret)
+ goto err_unassign_container;
}
mutex_unlock(&device->dev_set->lock);
@@ -800,20 +828,11 @@ static struct file *vfio_device_open(struct vfio_device *device)
err_close_device:
mutex_lock(&device->dev_set->lock);
- mutex_lock(&device->group->group_lock);
- if (device->open_count == 1 && device->ops->close_device) {
- device->ops->close_device(device);
-
- vfio_device_container_unregister(device);
- }
-err_undo_count:
- mutex_unlock(&device->group->group_lock);
+ if (device->open_count == 1)
+ vfio_device_last_close(device);
+err_unassign_container:
device->open_count--;
- if (device->open_count == 0 && device->kvm)
- device->kvm = NULL;
mutex_unlock(&device->dev_set->lock);
- module_put(device->dev->driver->owner);
-err_unassign_container:
vfio_device_unassign_container(device);
return ERR_PTR(ret);
}
@@ -1016,19 +1035,11 @@ static int vfio_device_fops_release(struct inode *inode, struct file *filep)
mutex_lock(&device->dev_set->lock);
vfio_assert_device_open(device);
- mutex_lock(&device->group->group_lock);
- if (device->open_count == 1 && device->ops->close_device)
- device->ops->close_device(device);
-
- vfio_device_container_unregister(device);
- mutex_unlock(&device->group->group_lock);
+ if (device->open_count == 1)
+ vfio_device_last_close(device);
device->open_count--;
- if (device->open_count == 0)
- device->kvm = NULL;
mutex_unlock(&device->dev_set->lock);
- module_put(device->dev->driver->owner);
-
vfio_device_unassign_container(device);
vfio_device_put_registration(device);