Some drivers (specifically vmwgfx) look at dev_mapping
in their open hook, so we have to set dev->dev_mapping
earlier in the process.

Signed-off-by: Ilija Hadzic <ihadzic at research.bell-labs.com>
---
 drivers/gpu/drm/drm_fops.c |   43 +++++++++++++++++++++++++++++--------------
 1 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 7ef1b67..50b7b47 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)
        int minor_id = iminor(inode);
        struct drm_minor *minor;
        int retcode = 0;
+       int need_setup = 0;
+       struct address_space *old_mapping;

        minor = idr_find(&drm_minors_idr, minor_id);
        if (!minor)
@@ -132,23 +134,36 @@ int drm_open(struct inode *inode, struct file *filp)
        if (drm_device_is_unplugged(dev))
                return -ENODEV;

+       if (!dev->open_count++)
+               need_setup = 1;
+       mutex_lock(&dev->struct_mutex);
+       old_mapping = dev->dev_mapping;
+       if (old_mapping == NULL)
+               dev->dev_mapping = &inode->i_data;
+       mutex_unlock(&dev->struct_mutex);
+
        retcode = drm_open_helper(inode, filp, dev);
-       if (!retcode) {
-               atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
-               if (!dev->open_count++)
-                       retcode = drm_setup(dev);
-       }
-       if (!retcode) {
-               mutex_lock(&dev->struct_mutex);
-               if (dev->dev_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);
+       if (retcode)
+               goto err_undo;
+       atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+       if (need_setup) {
+               retcode = drm_setup(dev);
+               if (retcode)
+                       goto err_undo;
        }
+       /* ihold ensures nobody can remove inode with our i_data */
+       mutex_lock(&dev->struct_mutex);
+       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);
+       return 0;

+err_undo:
+       dev->open_count--;
+       mutex_lock(&dev->struct_mutex);
+       dev->dev_mapping = old_mapping;
+       mutex_unlock(&dev->struct_mutex);
        return retcode;
 }
 EXPORT_SYMBOL(drm_open);
-- 
1.7.4.1

Reply via email to