aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_fops.c50
-rw-r--r--drivers/gpu/drm/drm_stub.c39
2 files changed, 66 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);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index f2f0249304b7..269048215e82 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -356,6 +356,45 @@ static void drm_unplug_minor(struct drm_minor *minor)
356} 356}
357 357
358/** 358/**
359 * drm_minor_acquire - Acquire a DRM minor
360 * @minor_id: Minor ID of the DRM-minor
361 *
362 * Looks up the given minor-ID and returns the respective DRM-minor object. The
363 * refence-count of the underlying device is increased so you must release this
364 * object with drm_minor_release().
365 *
366 * As long as you hold this minor, it is guaranteed that the object and the
367 * minor->dev pointer will stay valid! However, the device may get unplugged and
368 * unregistered while you hold the minor.
369 *
370 * Returns:
371 * Pointer to minor-object with increased device-refcount, or PTR_ERR on
372 * failure.
373 */
374struct drm_minor *drm_minor_acquire(unsigned int minor_id)
375{
376 struct drm_minor *minor;
377
378 minor = idr_find(&drm_minors_idr, minor_id);
379 if (!minor)
380 return ERR_PTR(-ENODEV);
381
382 drm_dev_ref(minor->dev);
383 return minor;
384}
385
386/**
387 * drm_minor_release - Release DRM minor
388 * @minor: Pointer to DRM minor object
389 *
390 * Release a minor that was previously acquired via drm_minor_acquire().
391 */
392void drm_minor_release(struct drm_minor *minor)
393{
394 drm_dev_unref(minor->dev);
395}
396
397/**
359 * drm_put_minor - Destroy DRM minor 398 * drm_put_minor - Destroy DRM minor
360 * @minor: Minor to destroy 399 * @minor: Minor to destroy
361 * 400 *