diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-01-29 04:49:19 -0500 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-03-16 07:25:17 -0400 |
commit | 1616c525b98deb34b8f4b02eccf0ae3a1310fa27 (patch) | |
tree | d28625fe2ae686919c757df8ec6b8940e0d46d22 /drivers/gpu/drm/drm_fops.c | |
parent | 099d1c290e2ebc3b798961a6c177c3aef5f0b789 (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.c | 50 |
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 | */ |
80 | int drm_open(struct inode *inode, struct file *filp) | 80 | int 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--; |
130 | err_release: | ||
131 | drm_minor_release(minor); | ||
131 | return retcode; | 132 | return retcode; |
132 | } | 133 | } |
133 | EXPORT_SYMBOL(drm_open); | 134 | EXPORT_SYMBOL(drm_open); |
@@ -143,33 +144,33 @@ EXPORT_SYMBOL(drm_open); | |||
143 | */ | 144 | */ |
144 | int drm_stub_open(struct inode *inode, struct file *filp) | 145 | int 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); |
172 | out: | 170 | |
171 | out_release: | ||
172 | drm_minor_release(minor); | ||
173 | out_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) | |||
453 | int drm_release(struct inode *inode, struct file *filp) | 454 | int 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 | } |
580 | EXPORT_SYMBOL(drm_release); | 584 | EXPORT_SYMBOL(drm_release); |