Message ID | 1351532101-8523-2-git-send-email-ihadzic@research.bell-labs.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Reviewed-by: Thomas Hellstrom <thellstrom@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@research.bell-labs.com> > Reported-by: Thomas Hellstrom <thellstrom@vmware.com> > Cc: stable@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);
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);
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@research.bell-labs.com> Reported-by: Thomas Hellstrom <thellstrom@vmware.com> Cc: stable@vger.kernel.org --- drivers/gpu/drm/drm_fops.c | 47 +++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-)