Merge tag 'nfsd-5.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
[linux-2.6-microblaze.git] / drivers / vfio / vfio.c
index 32660e8..5e631c3 100644 (file)
@@ -89,16 +89,6 @@ struct vfio_group {
        struct blocking_notifier_head   notifier;
 };
 
-struct vfio_device {
-       refcount_t                      refcount;
-       struct completion               comp;
-       struct device                   *dev;
-       const struct vfio_device_ops    *ops;
-       struct vfio_group               *group;
-       struct list_head                group_next;
-       void                            *device_data;
-};
-
 #ifdef CONFIG_VFIO_NOIOMMU
 static bool noiommu __read_mostly;
 module_param_named(enable_unsafe_noiommu_mode,
@@ -109,8 +99,8 @@ MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode.  Thi
 /*
  * vfio_iommu_group_{get,put} are only intended for VFIO bus driver probe
  * and remove functions, any use cases other than acquiring the first
- * reference for the purpose of calling vfio_add_group_dev() or removing
- * that symmetric reference after vfio_del_group_dev() should use the raw
+ * reference for the purpose of calling vfio_register_group_dev() or removing
+ * that symmetric reference after vfio_unregister_group_dev() should use the raw
  * iommu_group_{get,put} functions.  In particular, vfio_iommu_group_put()
  * removes the device from the dummy group and cannot be nested.
  */
@@ -532,35 +522,6 @@ static struct vfio_group *vfio_group_get_from_dev(struct device *dev)
 /**
  * Device objects - create, release, get, put, search
  */
-static
-struct vfio_device *vfio_group_create_device(struct vfio_group *group,
-                                            struct device *dev,
-                                            const struct vfio_device_ops *ops,
-                                            void *device_data)
-{
-       struct vfio_device *device;
-
-       device = kzalloc(sizeof(*device), GFP_KERNEL);
-       if (!device)
-               return ERR_PTR(-ENOMEM);
-
-       refcount_set(&device->refcount, 1);
-       init_completion(&device->comp);
-       device->dev = dev;
-       /* Our reference on group is moved to the device */
-       device->group = group;
-       device->ops = ops;
-       device->device_data = device_data;
-       dev_set_drvdata(dev, device);
-
-       mutex_lock(&group->device_lock);
-       list_add(&device->group_next, &group->device_list);
-       group->dev_counter++;
-       mutex_unlock(&group->device_lock);
-
-       return device;
-}
-
 /* Device reference always implies a group reference */
 void vfio_device_put(struct vfio_device *device)
 {
@@ -779,14 +740,22 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb,
 /**
  * VFIO driver API
  */
-int vfio_add_group_dev(struct device *dev,
-                      const struct vfio_device_ops *ops, void *device_data)
+void vfio_init_group_dev(struct vfio_device *device, struct device *dev,
+                        const struct vfio_device_ops *ops)
+{
+       init_completion(&device->comp);
+       device->dev = dev;
+       device->ops = ops;
+}
+EXPORT_SYMBOL_GPL(vfio_init_group_dev);
+
+int vfio_register_group_dev(struct vfio_device *device)
 {
+       struct vfio_device *existing_device;
        struct iommu_group *iommu_group;
        struct vfio_group *group;
-       struct vfio_device *device;
 
-       iommu_group = iommu_group_get(dev);
+       iommu_group = iommu_group_get(device->dev);
        if (!iommu_group)
                return -EINVAL;
 
@@ -805,23 +774,29 @@ int vfio_add_group_dev(struct device *dev,
                iommu_group_put(iommu_group);
        }
 
-       device = vfio_group_get_device(group, dev);
-       if (device) {
-               dev_WARN(dev, "Device already exists on group %d\n",
+       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));
-               vfio_device_put(device);
+               vfio_device_put(existing_device);
                vfio_group_put(group);
                return -EBUSY;
        }
 
-       device = vfio_group_create_device(group, dev, ops, device_data);
-       if (IS_ERR(device)) {
-               vfio_group_put(group);
-               return PTR_ERR(device);
-       }
+       /* Our reference on group is moved to the device */
+       device->group = group;
+
+       /* Refcounting can't start until the driver calls register */
+       refcount_set(&device->refcount, 1);
+
+       mutex_lock(&group->device_lock);
+       list_add(&device->group_next, &group->device_list);
+       group->dev_counter++;
+       mutex_unlock(&group->device_lock);
+
        return 0;
 }
-EXPORT_SYMBOL_GPL(vfio_add_group_dev);
+EXPORT_SYMBOL_GPL(vfio_register_group_dev);
 
 /**
  * Get a reference to the vfio_device for a device.  Even if the
@@ -856,7 +831,7 @@ static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group,
                int ret;
 
                if (it->ops->match) {
-                       ret = it->ops->match(it->device_data, buf);
+                       ret = it->ops->match(it, buf);
                        if (ret < 0) {
                                device = ERR_PTR(ret);
                                break;
@@ -875,23 +850,12 @@ static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group,
        return device;
 }
 
-/*
- * Caller must hold a reference to the vfio_device
- */
-void *vfio_device_data(struct vfio_device *device)
-{
-       return device->device_data;
-}
-EXPORT_SYMBOL_GPL(vfio_device_data);
-
 /*
  * Decrement the device reference count and wait for the device to be
  * removed.  Open file descriptors for the device... */
-void *vfio_del_group_dev(struct device *dev)
+void vfio_unregister_group_dev(struct vfio_device *device)
 {
-       struct vfio_device *device = dev_get_drvdata(dev);
        struct vfio_group *group = device->group;
-       void *device_data = device->device_data;
        struct vfio_unbound_dev *unbound;
        unsigned int i = 0;
        bool interrupted = false;
@@ -908,7 +872,7 @@ void *vfio_del_group_dev(struct device *dev)
         */
        unbound = kzalloc(sizeof(*unbound), GFP_KERNEL);
        if (unbound) {
-               unbound->dev = dev;
+               unbound->dev = device->dev;
                mutex_lock(&group->unbound_lock);
                list_add(&unbound->unbound_next, &group->unbound_list);
                mutex_unlock(&group->unbound_lock);
@@ -919,7 +883,7 @@ void *vfio_del_group_dev(struct device *dev)
        rc = try_wait_for_completion(&device->comp);
        while (rc <= 0) {
                if (device->ops->request)
-                       device->ops->request(device_data, i++);
+                       device->ops->request(device, i++);
 
                if (interrupted) {
                        rc = wait_for_completion_timeout(&device->comp,
@@ -929,7 +893,7 @@ void *vfio_del_group_dev(struct device *dev)
                                &device->comp, HZ * 10);
                        if (rc < 0) {
                                interrupted = true;
-                               dev_warn(dev,
+                               dev_warn(device->dev,
                                         "Device is currently in use, task"
                                         " \"%s\" (%d) "
                                         "blocked until device is released",
@@ -960,14 +924,10 @@ void *vfio_del_group_dev(struct device *dev)
        if (list_empty(&group->device_list))
                wait_event(group->container_q, !group->container);
 
-       /* Matches the get in vfio_group_create_device() */
+       /* Matches the get in vfio_register_group_dev() */
        vfio_group_put(group);
-       dev_set_drvdata(dev, NULL);
-       kfree(device);
-
-       return device_data;
 }
-EXPORT_SYMBOL_GPL(vfio_del_group_dev);
+EXPORT_SYMBOL_GPL(vfio_unregister_group_dev);
 
 /**
  * VFIO base fd, /dev/vfio/vfio
@@ -1409,7 +1369,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
        if (IS_ERR(device))
                return PTR_ERR(device);
 
-       ret = device->ops->open(device->device_data);
+       ret = device->ops->open(device);
        if (ret) {
                vfio_device_put(device);
                return ret;
@@ -1421,7 +1381,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
         */
        ret = get_unused_fd_flags(O_CLOEXEC);
        if (ret < 0) {
-               device->ops->release(device->device_data);
+               device->ops->release(device);
                vfio_device_put(device);
                return ret;
        }
@@ -1431,7 +1391,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
        if (IS_ERR(filep)) {
                put_unused_fd(ret);
                ret = PTR_ERR(filep);
-               device->ops->release(device->device_data);
+               device->ops->release(device);
                vfio_device_put(device);
                return ret;
        }
@@ -1588,7 +1548,7 @@ static int vfio_device_fops_release(struct inode *inode, struct file *filep)
 {
        struct vfio_device *device = filep->private_data;
 
-       device->ops->release(device->device_data);
+       device->ops->release(device);
 
        vfio_group_try_dissolve_container(device->group);
 
@@ -1605,7 +1565,7 @@ static long vfio_device_fops_unl_ioctl(struct file *filep,
        if (unlikely(!device->ops->ioctl))
                return -EINVAL;
 
-       return device->ops->ioctl(device->device_data, cmd, arg);
+       return device->ops->ioctl(device, cmd, arg);
 }
 
 static ssize_t vfio_device_fops_read(struct file *filep, char __user *buf,
@@ -1616,7 +1576,7 @@ static ssize_t vfio_device_fops_read(struct file *filep, char __user *buf,
        if (unlikely(!device->ops->read))
                return -EINVAL;
 
-       return device->ops->read(device->device_data, buf, count, ppos);
+       return device->ops->read(device, buf, count, ppos);
 }
 
 static ssize_t vfio_device_fops_write(struct file *filep,
@@ -1628,7 +1588,7 @@ static ssize_t vfio_device_fops_write(struct file *filep,
        if (unlikely(!device->ops->write))
                return -EINVAL;
 
-       return device->ops->write(device->device_data, buf, count, ppos);
+       return device->ops->write(device, buf, count, ppos);
 }
 
 static int vfio_device_fops_mmap(struct file *filep, struct vm_area_struct *vma)
@@ -1638,7 +1598,7 @@ static int vfio_device_fops_mmap(struct file *filep, struct vm_area_struct *vma)
        if (unlikely(!device->ops->mmap))
                return -EINVAL;
 
-       return device->ops->mmap(device->device_data, vma);
+       return device->ops->mmap(device, vma);
 }
 
 static const struct file_operations vfio_device_fops = {