aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fops.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-01-29 04:49:19 -0500
committerDavid Herrmann <dh.herrmann@gmail.com>2014-03-16 07:25:17 -0400
commit1616c525b98deb34b8f4b02eccf0ae3a1310fa27 (patch)
treed28625fe2ae686919c757df8ec6b8940e0d46d22 /drivers/gpu/drm/drm_fops.c
parent099d1c290e2ebc3b798961a6c177c3aef5f0b789 (diff)
drm: add minor-lookup/release helpers
Instead of accessing drm_minors_idr directly, this adds a small helper to hide the internals. This will help us later to remove the drm_global_mutex requirement for minor-lookup. Furthermore, this also makes sure that minor->dev is always valid and takes a reference-count to the device as long as the minor is used in an open-file. This way, "struct file*"->private_data->dev is guaranteed to be valid (which it has to, as we cannot reset it). Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/drm_fops.c')
-rw-r--r--drivers/gpu/drm/drm_fops.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 6466cb5d8b1f..79478191404a 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -79,23 +79,22 @@ static int drm_setup(struct drm_device * dev)
79 */ 79 */
80int drm_open(struct inode *inode, struct file *filp) 80int drm_open(struct inode *inode, struct file *filp)
81{ 81{
82 struct drm_device *dev = NULL; 82 struct drm_device *dev;
83 int minor_id = iminor(inode);
84 struct drm_minor *minor; 83 struct drm_minor *minor;
85 int retcode = 0; 84 int retcode;
86 int need_setup = 0; 85 int need_setup = 0;
87 struct address_space *old_mapping; 86 struct address_space *old_mapping;
88 struct address_space *old_imapping; 87 struct address_space *old_imapping;
89 88
90 minor = idr_find(&drm_minors_idr, minor_id); 89 minor = drm_minor_acquire(iminor(inode));
91 if (!minor) 90 if (IS_ERR(minor))
92 return -ENODEV; 91 return PTR_ERR(minor);
93
94 if (!(dev = minor->dev))
95 return -ENODEV;
96 92
97 if (drm_device_is_unplugged(dev)) 93 dev = minor->dev;
98 return -ENODEV; 94 if (drm_device_is_unplugged(dev)) {
95 retcode = -ENODEV;
96 goto err_release;
97 }
99 98
100 if (!dev->open_count++) 99 if (!dev->open_count++)
101 need_setup = 1; 100 need_setup = 1;
@@ -128,6 +127,8 @@ err_undo:
128 dev->dev_mapping = old_mapping; 127 dev->dev_mapping = old_mapping;
129 mutex_unlock(&dev->struct_mutex); 128 mutex_unlock(&dev->struct_mutex);
130 dev->open_count--; 129 dev->open_count--;
130err_release:
131 drm_minor_release(minor);
131 return retcode; 132 return retcode;
132} 133}
133EXPORT_SYMBOL(drm_open); 134EXPORT_SYMBOL(drm_open);
@@ -143,33 +144,33 @@ EXPORT_SYMBOL(drm_open);
143 */ 144 */
144int drm_stub_open(struct inode *inode, struct file *filp) 145int drm_stub_open(struct inode *inode, struct file *filp)
145{ 146{
146 struct drm_device *dev = NULL; 147 struct drm_device *dev;
147 struct drm_minor *minor; 148 struct drm_minor *minor;
148 int minor_id = iminor(inode);
149 int err = -ENODEV; 149 int err = -ENODEV;
150 const struct file_operations *new_fops; 150 const struct file_operations *new_fops;
151 151
152 DRM_DEBUG("\n"); 152 DRM_DEBUG("\n");
153 153
154 mutex_lock(&drm_global_mutex); 154 mutex_lock(&drm_global_mutex);
155 minor = idr_find(&drm_minors_idr, minor_id); 155 minor = drm_minor_acquire(iminor(inode));
156 if (!minor) 156 if (IS_ERR(minor))
157 goto out; 157 goto out_unlock;
158
159 if (!(dev = minor->dev))
160 goto out;
161 158
159 dev = minor->dev;
162 if (drm_device_is_unplugged(dev)) 160 if (drm_device_is_unplugged(dev))
163 goto out; 161 goto out_release;
164 162
165 new_fops = fops_get(dev->driver->fops); 163 new_fops = fops_get(dev->driver->fops);
166 if (!new_fops) 164 if (!new_fops)
167 goto out; 165 goto out_release;
168 166
169 replace_fops(filp, new_fops); 167 replace_fops(filp, new_fops);
170 if (filp->f_op->open) 168 if (filp->f_op->open)
171 err = filp->f_op->open(inode, filp); 169 err = filp->f_op->open(inode, filp);
172out: 170
171out_release:
172 drm_minor_release(minor);
173out_unlock:
173 mutex_unlock(&drm_global_mutex); 174 mutex_unlock(&drm_global_mutex);
174 return err; 175 return err;
175} 176}
@@ -453,7 +454,8 @@ int drm_lastclose(struct drm_device * dev)
453int drm_release(struct inode *inode, struct file *filp) 454int drm_release(struct inode *inode, struct file *filp)
454{ 455{
455 struct drm_file *file_priv = filp->private_data; 456 struct drm_file *file_priv = filp->private_data;
456 struct drm_device *dev = file_priv->minor->dev; 457 struct drm_minor *minor = file_priv->minor;
458 struct drm_device *dev = minor->dev;
457 int retcode = 0; 459 int retcode = 0;
458 460
459 mutex_lock(&drm_global_mutex); 461 mutex_lock(&drm_global_mutex);
@@ -575,6 +577,8 @@ int drm_release(struct inode *inode, struct file *filp)
575 } 577 }
576 mutex_unlock(&drm_global_mutex); 578 mutex_unlock(&drm_global_mutex);
577 579
580 drm_minor_release(minor);
581
578 return retcode; 582 return retcode;
579} 583}
580EXPORT_SYMBOL(drm_release); 584EXPORT_SYMBOL(drm_release);