vfio/fsl: Move to the device set infrastructure
[linux-2.6-microblaze.git] / drivers / vfio / fsl-mc / vfio_fsl_mc.c
index 122997c..0ead91b 100644 (file)
 
 static struct fsl_mc_driver vfio_fsl_mc_driver;
 
-static DEFINE_MUTEX(reflck_lock);
-
-static void vfio_fsl_mc_reflck_get(struct vfio_fsl_mc_reflck *reflck)
-{
-       kref_get(&reflck->kref);
-}
-
-static void vfio_fsl_mc_reflck_release(struct kref *kref)
-{
-       struct vfio_fsl_mc_reflck *reflck = container_of(kref,
-                                                     struct vfio_fsl_mc_reflck,
-                                                     kref);
-
-       mutex_destroy(&reflck->lock);
-       kfree(reflck);
-       mutex_unlock(&reflck_lock);
-}
-
-static void vfio_fsl_mc_reflck_put(struct vfio_fsl_mc_reflck *reflck)
-{
-       kref_put_mutex(&reflck->kref, vfio_fsl_mc_reflck_release, &reflck_lock);
-}
-
-static struct vfio_fsl_mc_reflck *vfio_fsl_mc_reflck_alloc(void)
-{
-       struct vfio_fsl_mc_reflck *reflck;
-
-       reflck = kzalloc(sizeof(*reflck), GFP_KERNEL);
-       if (!reflck)
-               return ERR_PTR(-ENOMEM);
-
-       kref_init(&reflck->kref);
-       mutex_init(&reflck->lock);
-
-       return reflck;
-}
-
-static int vfio_fsl_mc_reflck_attach(struct vfio_fsl_mc_device *vdev)
-{
-       int ret = 0;
-
-       mutex_lock(&reflck_lock);
-       if (is_fsl_mc_bus_dprc(vdev->mc_dev)) {
-               vdev->reflck = vfio_fsl_mc_reflck_alloc();
-               ret = PTR_ERR_OR_ZERO(vdev->reflck);
-       } else {
-               struct device *mc_cont_dev = vdev->mc_dev->dev.parent;
-               struct vfio_device *device;
-               struct vfio_fsl_mc_device *cont_vdev;
-
-               device = vfio_device_get_from_dev(mc_cont_dev);
-               if (!device) {
-                       ret = -ENODEV;
-                       goto unlock;
-               }
-
-               cont_vdev =
-                       container_of(device, struct vfio_fsl_mc_device, vdev);
-               if (!cont_vdev || !cont_vdev->reflck) {
-                       vfio_device_put(device);
-                       ret = -ENODEV;
-                       goto unlock;
-               }
-               vfio_fsl_mc_reflck_get(cont_vdev->reflck);
-               vdev->reflck = cont_vdev->reflck;
-               vfio_device_put(device);
-       }
-
-unlock:
-       mutex_unlock(&reflck_lock);
-       return ret;
-}
-
-static int vfio_fsl_mc_regions_init(struct vfio_fsl_mc_device *vdev)
+static int vfio_fsl_mc_open_device(struct vfio_device *core_vdev)
 {
+       struct vfio_fsl_mc_device *vdev =
+               container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
        struct fsl_mc_device *mc_dev = vdev->mc_dev;
        int count = mc_dev->obj_desc.region_count;
        int i;
@@ -136,58 +65,30 @@ static void vfio_fsl_mc_regions_cleanup(struct vfio_fsl_mc_device *vdev)
        kfree(vdev->regions);
 }
 
-static int vfio_fsl_mc_open(struct vfio_device *core_vdev)
-{
-       struct vfio_fsl_mc_device *vdev =
-               container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
-       int ret = 0;
-
-       mutex_lock(&vdev->reflck->lock);
-       if (!vdev->refcnt) {
-               ret = vfio_fsl_mc_regions_init(vdev);
-               if (ret)
-                       goto out;
-       }
-       vdev->refcnt++;
-out:
-       mutex_unlock(&vdev->reflck->lock);
 
-       return ret;
-}
-
-static void vfio_fsl_mc_release(struct vfio_device *core_vdev)
+static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev)
 {
        struct vfio_fsl_mc_device *vdev =
                container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
+       struct fsl_mc_device *mc_dev = vdev->mc_dev;
+       struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev);
+       struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev);
        int ret;
 
-       mutex_lock(&vdev->reflck->lock);
-
-       if (!(--vdev->refcnt)) {
-               struct fsl_mc_device *mc_dev = vdev->mc_dev;
-               struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev);
-               struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev);
-
-               vfio_fsl_mc_regions_cleanup(vdev);
+       vfio_fsl_mc_regions_cleanup(vdev);
 
-               /* reset the device before cleaning up the interrupts */
-               ret = dprc_reset_container(mc_cont->mc_io, 0,
-                     mc_cont->mc_handle,
-                         mc_cont->obj_desc.id,
-                         DPRC_RESET_OPTION_NON_RECURSIVE);
+       /* reset the device before cleaning up the interrupts */
+       ret = dprc_reset_container(mc_cont->mc_io, 0, mc_cont->mc_handle,
+                                  mc_cont->obj_desc.id,
+                                  DPRC_RESET_OPTION_NON_RECURSIVE);
 
-               if (ret) {
-                       dev_warn(&mc_cont->dev, "VFIO_FLS_MC: reset device has failed (%d)\n",
-                                ret);
-                       WARN_ON(1);
-               }
+       if (WARN_ON(ret))
+               dev_warn(&mc_cont->dev,
+                        "VFIO_FLS_MC: reset device has failed (%d)\n", ret);
 
-               vfio_fsl_mc_irqs_cleanup(vdev);
+       vfio_fsl_mc_irqs_cleanup(vdev);
 
-               fsl_mc_cleanup_irq_pool(mc_cont);
-       }
-
-       mutex_unlock(&vdev->reflck->lock);
+       fsl_mc_cleanup_irq_pool(mc_cont);
 }
 
 static long vfio_fsl_mc_ioctl(struct vfio_device *core_vdev,
@@ -504,8 +405,8 @@ static int vfio_fsl_mc_mmap(struct vfio_device *core_vdev,
 
 static const struct vfio_device_ops vfio_fsl_mc_ops = {
        .name           = "vfio-fsl-mc",
-       .open           = vfio_fsl_mc_open,
-       .release        = vfio_fsl_mc_release,
+       .open_device    = vfio_fsl_mc_open_device,
+       .close_device   = vfio_fsl_mc_close_device,
        .ioctl          = vfio_fsl_mc_ioctl,
        .read           = vfio_fsl_mc_read,
        .write          = vfio_fsl_mc_write,
@@ -625,13 +526,16 @@ static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev)
        vdev->mc_dev = mc_dev;
        mutex_init(&vdev->igate);
 
-       ret = vfio_fsl_mc_reflck_attach(vdev);
+       if (is_fsl_mc_bus_dprc(mc_dev))
+               ret = vfio_assign_device_set(&vdev->vdev, &mc_dev->dev);
+       else
+               ret = vfio_assign_device_set(&vdev->vdev, mc_dev->dev.parent);
        if (ret)
                goto out_uninit;
 
        ret = vfio_fsl_mc_init_device(vdev);
        if (ret)
-               goto out_reflck;
+               goto out_uninit;
 
        ret = vfio_register_group_dev(&vdev->vdev);
        if (ret) {
@@ -639,12 +543,6 @@ static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev)
                goto out_device;
        }
 
-       /*
-        * This triggers recursion into vfio_fsl_mc_probe() on another device
-        * and the vfio_fsl_mc_reflck_attach() must succeed, which relies on the
-        * vfio_add_group_dev() above. It has no impact on this vdev, so it is
-        * safe to be after the vfio device is made live.
-        */
        ret = vfio_fsl_mc_scan_container(mc_dev);
        if (ret)
                goto out_group_dev;
@@ -655,8 +553,6 @@ out_group_dev:
        vfio_unregister_group_dev(&vdev->vdev);
 out_device:
        vfio_fsl_uninit_device(vdev);
-out_reflck:
-       vfio_fsl_mc_reflck_put(vdev->reflck);
 out_uninit:
        vfio_uninit_group_dev(&vdev->vdev);
        kfree(vdev);
@@ -675,7 +571,7 @@ static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev)
 
        dprc_remove_devices(mc_dev, NULL, 0);
        vfio_fsl_uninit_device(vdev);
-       vfio_fsl_mc_reflck_put(vdev->reflck);
+
        vfio_uninit_group_dev(&vdev->vdev);
        kfree(vdev);
        vfio_iommu_group_put(mc_dev->dev.iommu_group, dev);