diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-03-16 08:13:51 -0400 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-03-16 08:13:51 -0400 |
commit | 07b48c3ac539828d744f0562da1f24e8a234d06e (patch) | |
tree | bb1d32d025f97fc47f44a037951563c72eaf586d /drivers/gpu/drm/drm_fops.c | |
parent | afab4463acc5ae7aa975a0c2400b85ff541c6a5b (diff) | |
parent | 0d639883ee26359e1bf38195df1dbca0f879e239 (diff) |
Merge branch 'drm-minor' into drm-next
Fix minor conflicts with drm-anon:
- allocation/free order
- drm_device header cleanups
Diffstat (limited to 'drivers/gpu/drm/drm_fops.c')
-rw-r--r-- | drivers/gpu/drm/drm_fops.c | 70 |
1 files changed, 30 insertions, 40 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 147a84d9da9b..9b02f126fb0d 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -39,12 +39,12 @@ | |||
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/module.h> | 40 | #include <linux/module.h> |
41 | 41 | ||
42 | /* from BKL pushdown: note that nothing else serializes idr_find() */ | 42 | /* from BKL pushdown */ |
43 | DEFINE_MUTEX(drm_global_mutex); | 43 | DEFINE_MUTEX(drm_global_mutex); |
44 | EXPORT_SYMBOL(drm_global_mutex); | 44 | EXPORT_SYMBOL(drm_global_mutex); |
45 | 45 | ||
46 | static int drm_open_helper(struct inode *inode, struct file *filp, | 46 | static int drm_open_helper(struct inode *inode, struct file *filp, |
47 | struct drm_device * dev); | 47 | struct drm_minor *minor); |
48 | 48 | ||
49 | static int drm_setup(struct drm_device * dev) | 49 | static int drm_setup(struct drm_device * dev) |
50 | { | 50 | { |
@@ -79,29 +79,23 @@ 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 | 86 | ||
88 | minor = idr_find(&drm_minors_idr, minor_id); | 87 | minor = drm_minor_acquire(iminor(inode)); |
89 | if (!minor) | 88 | if (IS_ERR(minor)) |
90 | return -ENODEV; | 89 | return PTR_ERR(minor); |
91 | |||
92 | if (!(dev = minor->dev)) | ||
93 | return -ENODEV; | ||
94 | |||
95 | if (drm_device_is_unplugged(dev)) | ||
96 | return -ENODEV; | ||
97 | 90 | ||
91 | dev = minor->dev; | ||
98 | if (!dev->open_count++) | 92 | if (!dev->open_count++) |
99 | need_setup = 1; | 93 | need_setup = 1; |
100 | 94 | ||
101 | /* share address_space across all char-devs of a single device */ | 95 | /* share address_space across all char-devs of a single device */ |
102 | filp->f_mapping = dev->anon_inode->i_mapping; | 96 | filp->f_mapping = dev->anon_inode->i_mapping; |
103 | 97 | ||
104 | retcode = drm_open_helper(inode, filp, dev); | 98 | retcode = drm_open_helper(inode, filp, minor); |
105 | if (retcode) | 99 | if (retcode) |
106 | goto err_undo; | 100 | goto err_undo; |
107 | if (need_setup) { | 101 | if (need_setup) { |
@@ -113,6 +107,7 @@ int drm_open(struct inode *inode, struct file *filp) | |||
113 | 107 | ||
114 | err_undo: | 108 | err_undo: |
115 | dev->open_count--; | 109 | dev->open_count--; |
110 | drm_minor_release(minor); | ||
116 | return retcode; | 111 | return retcode; |
117 | } | 112 | } |
118 | EXPORT_SYMBOL(drm_open); | 113 | EXPORT_SYMBOL(drm_open); |
@@ -128,33 +123,30 @@ EXPORT_SYMBOL(drm_open); | |||
128 | */ | 123 | */ |
129 | int drm_stub_open(struct inode *inode, struct file *filp) | 124 | int drm_stub_open(struct inode *inode, struct file *filp) |
130 | { | 125 | { |
131 | struct drm_device *dev = NULL; | 126 | struct drm_device *dev; |
132 | struct drm_minor *minor; | 127 | struct drm_minor *minor; |
133 | int minor_id = iminor(inode); | ||
134 | int err = -ENODEV; | 128 | int err = -ENODEV; |
135 | const struct file_operations *new_fops; | 129 | const struct file_operations *new_fops; |
136 | 130 | ||
137 | DRM_DEBUG("\n"); | 131 | DRM_DEBUG("\n"); |
138 | 132 | ||
139 | mutex_lock(&drm_global_mutex); | 133 | mutex_lock(&drm_global_mutex); |
140 | minor = idr_find(&drm_minors_idr, minor_id); | 134 | minor = drm_minor_acquire(iminor(inode)); |
141 | if (!minor) | 135 | if (IS_ERR(minor)) |
142 | goto out; | 136 | goto out_unlock; |
143 | |||
144 | if (!(dev = minor->dev)) | ||
145 | goto out; | ||
146 | |||
147 | if (drm_device_is_unplugged(dev)) | ||
148 | goto out; | ||
149 | 137 | ||
138 | dev = minor->dev; | ||
150 | new_fops = fops_get(dev->driver->fops); | 139 | new_fops = fops_get(dev->driver->fops); |
151 | if (!new_fops) | 140 | if (!new_fops) |
152 | goto out; | 141 | goto out_release; |
153 | 142 | ||
154 | replace_fops(filp, new_fops); | 143 | replace_fops(filp, new_fops); |
155 | if (filp->f_op->open) | 144 | if (filp->f_op->open) |
156 | err = filp->f_op->open(inode, filp); | 145 | err = filp->f_op->open(inode, filp); |
157 | out: | 146 | |
147 | out_release: | ||
148 | drm_minor_release(minor); | ||
149 | out_unlock: | ||
158 | mutex_unlock(&drm_global_mutex); | 150 | mutex_unlock(&drm_global_mutex); |
159 | return err; | 151 | return err; |
160 | } | 152 | } |
@@ -181,16 +173,16 @@ static int drm_cpu_valid(void) | |||
181 | * | 173 | * |
182 | * \param inode device inode. | 174 | * \param inode device inode. |
183 | * \param filp file pointer. | 175 | * \param filp file pointer. |
184 | * \param dev device. | 176 | * \param minor acquired minor-object. |
185 | * \return zero on success or a negative number on failure. | 177 | * \return zero on success or a negative number on failure. |
186 | * | 178 | * |
187 | * Creates and initializes a drm_file structure for the file private data in \p | 179 | * Creates and initializes a drm_file structure for the file private data in \p |
188 | * filp and add it into the double linked list in \p dev. | 180 | * filp and add it into the double linked list in \p dev. |
189 | */ | 181 | */ |
190 | static int drm_open_helper(struct inode *inode, struct file *filp, | 182 | static int drm_open_helper(struct inode *inode, struct file *filp, |
191 | struct drm_device * dev) | 183 | struct drm_minor *minor) |
192 | { | 184 | { |
193 | int minor_id = iminor(inode); | 185 | struct drm_device *dev = minor->dev; |
194 | struct drm_file *priv; | 186 | struct drm_file *priv; |
195 | int ret; | 187 | int ret; |
196 | 188 | ||
@@ -201,7 +193,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, | |||
201 | if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF) | 193 | if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF) |
202 | return -EINVAL; | 194 | return -EINVAL; |
203 | 195 | ||
204 | DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id); | 196 | DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index); |
205 | 197 | ||
206 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 198 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
207 | if (!priv) | 199 | if (!priv) |
@@ -211,11 +203,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, | |||
211 | priv->filp = filp; | 203 | priv->filp = filp; |
212 | priv->uid = current_euid(); | 204 | priv->uid = current_euid(); |
213 | priv->pid = get_pid(task_pid(current)); | 205 | priv->pid = get_pid(task_pid(current)); |
214 | priv->minor = idr_find(&drm_minors_idr, minor_id); | 206 | priv->minor = minor; |
215 | if (!priv->minor) { | ||
216 | ret = -ENODEV; | ||
217 | goto out_put_pid; | ||
218 | } | ||
219 | 207 | ||
220 | /* for compatibility root is always authenticated */ | 208 | /* for compatibility root is always authenticated */ |
221 | priv->always_authenticated = capable(CAP_SYS_ADMIN); | 209 | priv->always_authenticated = capable(CAP_SYS_ADMIN); |
@@ -321,7 +309,6 @@ out_prime_destroy: | |||
321 | drm_prime_destroy_file_private(&priv->prime); | 309 | drm_prime_destroy_file_private(&priv->prime); |
322 | if (dev->driver->driver_features & DRIVER_GEM) | 310 | if (dev->driver->driver_features & DRIVER_GEM) |
323 | drm_gem_release(dev, priv); | 311 | drm_gem_release(dev, priv); |
324 | out_put_pid: | ||
325 | put_pid(priv->pid); | 312 | put_pid(priv->pid); |
326 | kfree(priv); | 313 | kfree(priv); |
327 | filp->private_data = NULL; | 314 | filp->private_data = NULL; |
@@ -442,7 +429,8 @@ int drm_lastclose(struct drm_device * dev) | |||
442 | int drm_release(struct inode *inode, struct file *filp) | 429 | int drm_release(struct inode *inode, struct file *filp) |
443 | { | 430 | { |
444 | struct drm_file *file_priv = filp->private_data; | 431 | struct drm_file *file_priv = filp->private_data; |
445 | struct drm_device *dev = file_priv->minor->dev; | 432 | struct drm_minor *minor = file_priv->minor; |
433 | struct drm_device *dev = minor->dev; | ||
446 | int retcode = 0; | 434 | int retcode = 0; |
447 | 435 | ||
448 | mutex_lock(&drm_global_mutex); | 436 | mutex_lock(&drm_global_mutex); |
@@ -458,7 +446,7 @@ int drm_release(struct inode *inode, struct file *filp) | |||
458 | 446 | ||
459 | DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", | 447 | DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", |
460 | task_pid_nr(current), | 448 | task_pid_nr(current), |
461 | (long)old_encode_dev(file_priv->minor->device), | 449 | (long)old_encode_dev(file_priv->minor->kdev->devt), |
462 | dev->open_count); | 450 | dev->open_count); |
463 | 451 | ||
464 | /* Release any auth tokens that might point to this file_priv, | 452 | /* Release any auth tokens that might point to this file_priv, |
@@ -561,6 +549,8 @@ int drm_release(struct inode *inode, struct file *filp) | |||
561 | } | 549 | } |
562 | mutex_unlock(&drm_global_mutex); | 550 | mutex_unlock(&drm_global_mutex); |
563 | 551 | ||
552 | drm_minor_release(minor); | ||
553 | |||
564 | return retcode; | 554 | return retcode; |
565 | } | 555 | } |
566 | EXPORT_SYMBOL(drm_release); | 556 | EXPORT_SYMBOL(drm_release); |