drm: use anon-inode instead of relying on cdevs
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / gpu / drm / drm_fops.c
index 7f2af9a..88ebc2b 100644 (file)
@@ -79,36 +79,26 @@ static int drm_setup(struct drm_device * dev)
  */
 int drm_open(struct inode *inode, struct file *filp)
 {
-       struct drm_device *dev = NULL;
-       int minor_id = iminor(inode);
+       struct drm_device *dev;
        struct drm_minor *minor;
-       int retcode = 0;
+       int retcode;
        int need_setup = 0;
-       struct address_space *old_mapping;
-       struct address_space *old_imapping;
-
-       minor = idr_find(&drm_minors_idr, minor_id);
-       if (!minor)
-               return -ENODEV;
 
-       if (!(dev = minor->dev))
-               return -ENODEV;
+       minor = drm_minor_acquire(iminor(inode));
+       if (IS_ERR(minor))
+               return PTR_ERR(minor);
 
-       if (drm_device_is_unplugged(dev))
-               return -ENODEV;
+       dev = minor->dev;
+       if (drm_device_is_unplugged(dev)) {
+               retcode = -ENODEV;
+               goto err_release;
+       }
 
        if (!dev->open_count++)
                need_setup = 1;
-       mutex_lock(&dev->struct_mutex);
-       old_imapping = inode->i_mapping;
-       old_mapping = dev->dev_mapping;
-       if (old_mapping == NULL)
-               dev->dev_mapping = &inode->i_data;
-       /* ihold ensures nobody can remove inode with our i_data */
-       ihold(container_of(dev->dev_mapping, struct inode, i_data));
-       inode->i_mapping = dev->dev_mapping;
-       filp->f_mapping = dev->dev_mapping;
-       mutex_unlock(&dev->struct_mutex);
+
+       /* share address_space across all char-devs of a single device */
+       filp->f_mapping = dev->anon_inode->i_mapping;
 
        retcode = drm_open_helper(inode, filp, dev);
        if (retcode)
@@ -121,13 +111,9 @@ int drm_open(struct inode *inode, struct file *filp)
        return 0;
 
 err_undo:
-       mutex_lock(&dev->struct_mutex);
-       filp->f_mapping = old_imapping;
-       inode->i_mapping = old_imapping;
-       iput(container_of(dev->dev_mapping, struct inode, i_data));
-       dev->dev_mapping = old_mapping;
-       mutex_unlock(&dev->struct_mutex);
        dev->open_count--;
+err_release:
+       drm_minor_release(minor);
        return retcode;
 }
 EXPORT_SYMBOL(drm_open);
@@ -143,33 +129,33 @@ EXPORT_SYMBOL(drm_open);
  */
 int drm_stub_open(struct inode *inode, struct file *filp)
 {
-       struct drm_device *dev = NULL;
+       struct drm_device *dev;
        struct drm_minor *minor;
-       int minor_id = iminor(inode);
        int err = -ENODEV;
        const struct file_operations *new_fops;
 
        DRM_DEBUG("\n");
 
        mutex_lock(&drm_global_mutex);
-       minor = idr_find(&drm_minors_idr, minor_id);
-       if (!minor)
-               goto out;
-
-       if (!(dev = minor->dev))
-               goto out;
+       minor = drm_minor_acquire(iminor(inode));
+       if (IS_ERR(minor))
+               goto out_unlock;
 
+       dev = minor->dev;
        if (drm_device_is_unplugged(dev))
-               goto out;
+               goto out_release;
 
        new_fops = fops_get(dev->driver->fops);
        if (!new_fops)
-               goto out;
+               goto out_release;
 
        replace_fops(filp, new_fops);
        if (filp->f_op->open)
                err = filp->f_op->open(inode, filp);
-out:
+
+out_release:
+       drm_minor_release(minor);
+out_unlock:
        mutex_unlock(&drm_global_mutex);
        return err;
 }
@@ -434,7 +420,6 @@ int drm_lastclose(struct drm_device * dev)
 
        drm_legacy_dma_takedown(dev);
 
-       dev->dev_mapping = NULL;
        mutex_unlock(&dev->struct_mutex);
 
        drm_legacy_dev_reinit(dev);
@@ -458,7 +443,8 @@ int drm_lastclose(struct drm_device * dev)
 int drm_release(struct inode *inode, struct file *filp)
 {
        struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
+       struct drm_minor *minor = file_priv->minor;
+       struct drm_device *dev = minor->dev;
        int retcode = 0;
 
        mutex_lock(&drm_global_mutex);
@@ -549,9 +535,6 @@ int drm_release(struct inode *inode, struct file *filp)
                }
        }
 
-       BUG_ON(dev->dev_mapping == NULL);
-       iput(container_of(dev->dev_mapping, struct inode, i_data));
-
        /* drop the reference held my the file priv */
        if (file_priv->master)
                drm_master_put(&file_priv->master);
@@ -580,6 +563,8 @@ int drm_release(struct inode *inode, struct file *filp)
        }
        mutex_unlock(&drm_global_mutex);
 
+       drm_minor_release(minor);
+
        return retcode;
 }
 EXPORT_SYMBOL(drm_release);