aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fops.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-03-16 08:13:51 -0400
committerDavid Herrmann <dh.herrmann@gmail.com>2014-03-16 08:13:51 -0400
commit07b48c3ac539828d744f0562da1f24e8a234d06e (patch)
treebb1d32d025f97fc47f44a037951563c72eaf586d /drivers/gpu/drm/drm_fops.c
parentafab4463acc5ae7aa975a0c2400b85ff541c6a5b (diff)
parent0d639883ee26359e1bf38195df1dbca0f879e239 (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.c70
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 */
43DEFINE_MUTEX(drm_global_mutex); 43DEFINE_MUTEX(drm_global_mutex);
44EXPORT_SYMBOL(drm_global_mutex); 44EXPORT_SYMBOL(drm_global_mutex);
45 45
46static int drm_open_helper(struct inode *inode, struct file *filp, 46static int drm_open_helper(struct inode *inode, struct file *filp,
47 struct drm_device * dev); 47 struct drm_minor *minor);
48 48
49static int drm_setup(struct drm_device * dev) 49static int drm_setup(struct drm_device * dev)
50{ 50{
@@ -79,29 +79,23 @@ 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 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
114err_undo: 108err_undo:
115 dev->open_count--; 109 dev->open_count--;
110 drm_minor_release(minor);
116 return retcode; 111 return retcode;
117} 112}
118EXPORT_SYMBOL(drm_open); 113EXPORT_SYMBOL(drm_open);
@@ -128,33 +123,30 @@ EXPORT_SYMBOL(drm_open);
128 */ 123 */
129int drm_stub_open(struct inode *inode, struct file *filp) 124int 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);
157out: 146
147out_release:
148 drm_minor_release(minor);
149out_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 */
190static int drm_open_helper(struct inode *inode, struct file *filp, 182static 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);
324out_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)
442int drm_release(struct inode *inode, struct file *filp) 429int 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}
566EXPORT_SYMBOL(drm_release); 556EXPORT_SYMBOL(drm_release);