aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIlija Hadzic <ilijahadzic@gmail.com>2012-10-29 13:35:01 -0400
committerDave Airlie <airlied@redhat.com>2012-11-06 19:51:15 -0500
commitfdb40a08ef7bc970899c3a1f471165f9c22763a1 (patch)
tree70426eb405d29964713c9954cb116027152f8a8a /drivers
parent0f1cb1bd94a9c967cd4ad3de51cfdabe61eb5dcc (diff)
drm: set dev_mapping before calling drm_open_helper
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 Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_fops.c47
1 files changed, 30 insertions, 17 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index af68eca44abe..133b4132983e 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)
121 int minor_id = iminor(inode); 121 int minor_id = iminor(inode);
122 struct drm_minor *minor; 122 struct drm_minor *minor;
123 int retcode = 0; 123 int retcode = 0;
124 int need_setup = 0;
125 struct address_space *old_mapping;
124 126
125 minor = idr_find(&drm_minors_idr, minor_id); 127 minor = idr_find(&drm_minors_idr, minor_id);
126 if (!minor) 128 if (!minor)
@@ -132,26 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)
132 if (drm_device_is_unplugged(dev)) 134 if (drm_device_is_unplugged(dev))
133 return -ENODEV; 135 return -ENODEV;
134 136
137 if (!dev->open_count++)
138 need_setup = 1;
139 mutex_lock(&dev->struct_mutex);
140 old_mapping = dev->dev_mapping;
141 if (old_mapping == NULL)
142 dev->dev_mapping = &inode->i_data;
143 /* ihold ensures nobody can remove inode with our i_data */
144 ihold(container_of(dev->dev_mapping, struct inode, i_data));
145 inode->i_mapping = dev->dev_mapping;
146 filp->f_mapping = dev->dev_mapping;
147 mutex_unlock(&dev->struct_mutex);
148
135 retcode = drm_open_helper(inode, filp, dev); 149 retcode = drm_open_helper(inode, filp, dev);
136 if (!retcode) { 150 if (retcode)
137 atomic_inc(&dev->counts[_DRM_STAT_OPENS]); 151 goto err_undo;
138 if (!dev->open_count++) { 152 atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
139 retcode = drm_setup(dev); 153 if (need_setup) {
140 if (retcode) 154 retcode = drm_setup(dev);
141 dev->open_count--; 155 if (retcode)
142 } 156 goto err_undo;
143 }
144 if (!retcode) {
145 mutex_lock(&dev->struct_mutex);
146 if (dev->dev_mapping == NULL)
147 dev->dev_mapping = &inode->i_data;
148 /* ihold ensures nobody can remove inode with our i_data */
149 ihold(container_of(dev->dev_mapping, struct inode, i_data));
150 inode->i_mapping = dev->dev_mapping;
151 filp->f_mapping = dev->dev_mapping;
152 mutex_unlock(&dev->struct_mutex);
153 } 157 }
158 return 0;
154 159
160err_undo:
161 mutex_lock(&dev->struct_mutex);
162 filp->f_mapping = old_mapping;
163 inode->i_mapping = old_mapping;
164 iput(container_of(dev->dev_mapping, struct inode, i_data));
165 dev->dev_mapping = old_mapping;
166 mutex_unlock(&dev->struct_mutex);
167 dev->open_count--;
155 return retcode; 168 return retcode;
156} 169}
157EXPORT_SYMBOL(drm_open); 170EXPORT_SYMBOL(drm_open);