Reviewed-by: Thomas Hellstrom <thellstrom at vmware.com>

On 10/29/2012 06:35 PM, Ilija Hadzic wrote:
> Some drivers (specifically vmwgfx) look at dev_mapping
> in their open hook, so we have to set dev->dev_mapping
> earlier in the process.
>
> Reference:
> http://lists.freedesktop.org/archives/dri-devel/2012-October/029420.html
>
> Signed-off-by: Ilija Hadzic <ihadzic at research.bell-labs.com>
> Reported-by: Thomas Hellstrom <thellstrom at vmware.com>
> Cc: stable at vger.kernel.org
> ---
>   drivers/gpu/drm/drm_fops.c | 47 
> +++++++++++++++++++++++++++++-----------------
>   1 file changed, 30 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index af68eca..133b413 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,26 +134,37 @@ 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;
> +     /* 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);
> +
>       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)
> -                             dev->open_count--;
> -             }
> -     }
> -     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;
>       }
> +     return 0;
>   
> +err_undo:
> +     mutex_lock(&dev->struct_mutex);
> +     filp->f_mapping = old_mapping;
> +     inode->i_mapping = old_mapping;
> +     iput(container_of(dev->dev_mapping, struct inode, i_data));
> +     dev->dev_mapping = old_mapping;
> +     mutex_unlock(&dev->struct_mutex);
> +     dev->open_count--;
>       return retcode;
>   }
>   EXPORT_SYMBOL(drm_open);

Reply via email to