aboutsummaryrefslogtreecommitdiffstats
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
parentafab4463acc5ae7aa975a0c2400b85ff541c6a5b (diff)
parent0d639883ee26359e1bf38195df1dbca0f879e239 (diff)
Merge branch 'drm-minor' into drm-next
Fix minor conflicts with drm-anon: - allocation/free order - drm_device header cleanups
-rw-r--r--drivers/gpu/drm/drm_drv.c4
-rw-r--r--drivers/gpu/drm/drm_fops.c70
-rw-r--r--drivers/gpu/drm/drm_pci.c2
-rw-r--r--drivers/gpu/drm/drm_platform.c2
-rw-r--r--drivers/gpu/drm/drm_stub.c348
-rw-r--r--drivers/gpu/drm/drm_usb.c2
-rw-r--r--drivers/gpu/drm/tegra/bus.c2
-rw-r--r--include/drm/drmP.h41
8 files changed, 278 insertions, 193 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 345be03c23db..ec651be2f3cb 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -344,7 +344,7 @@ long drm_ioctl(struct file *filp,
344 344
345 DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", 345 DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
346 task_pid_nr(current), 346 task_pid_nr(current),
347 (long)old_encode_dev(file_priv->minor->device), 347 (long)old_encode_dev(file_priv->minor->kdev->devt),
348 file_priv->authenticated, ioctl->name); 348 file_priv->authenticated, ioctl->name);
349 349
350 /* Do not trust userspace, use our own definition */ 350 /* Do not trust userspace, use our own definition */
@@ -402,7 +402,7 @@ long drm_ioctl(struct file *filp,
402 if (!ioctl) 402 if (!ioctl)
403 DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n", 403 DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
404 task_pid_nr(current), 404 task_pid_nr(current),
405 (long)old_encode_dev(file_priv->minor->device), 405 (long)old_encode_dev(file_priv->minor->kdev->devt),
406 file_priv->authenticated, cmd, nr); 406 file_priv->authenticated, cmd, nr);
407 407
408 if (kdata != stack_kdata) 408 if (kdata != stack_kdata)
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);
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index 5736aaa7e86c..9ded847b05b4 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -351,7 +351,7 @@ err_agp:
351 drm_pci_agp_destroy(dev); 351 drm_pci_agp_destroy(dev);
352 pci_disable_device(pdev); 352 pci_disable_device(pdev);
353err_free: 353err_free:
354 drm_dev_free(dev); 354 drm_dev_unref(dev);
355 return ret; 355 return ret;
356} 356}
357EXPORT_SYMBOL(drm_get_pci_dev); 357EXPORT_SYMBOL(drm_get_pci_dev);
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
index 21fc82006b78..319ff5385601 100644
--- a/drivers/gpu/drm/drm_platform.c
+++ b/drivers/gpu/drm/drm_platform.c
@@ -64,7 +64,7 @@ static int drm_get_platform_dev(struct platform_device *platdev,
64 return 0; 64 return 0;
65 65
66err_free: 66err_free:
67 drm_dev_free(dev); 67 drm_dev_unref(dev);
68 return ret; 68 return ret;
69} 69}
70 70
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 04c25cedd4c1..dc2c6095d850 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -72,6 +72,7 @@ module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
72module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); 72module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
73module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); 73module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
74 74
75static DEFINE_SPINLOCK(drm_minor_lock);
75struct idr drm_minors_idr; 76struct idr drm_minors_idr;
76 77
77struct class *drm_class; 78struct class *drm_class;
@@ -119,26 +120,6 @@ void drm_ut_debug_printk(unsigned int request_level,
119} 120}
120EXPORT_SYMBOL(drm_ut_debug_printk); 121EXPORT_SYMBOL(drm_ut_debug_printk);
121 122
122static int drm_minor_get_id(struct drm_device *dev, int type)
123{
124 int ret;
125 int base = 0, limit = 63;
126
127 if (type == DRM_MINOR_CONTROL) {
128 base += 64;
129 limit = base + 63;
130 } else if (type == DRM_MINOR_RENDER) {
131 base += 128;
132 limit = base + 63;
133 }
134
135 mutex_lock(&dev->struct_mutex);
136 ret = idr_alloc(&drm_minors_idr, NULL, base, limit, GFP_KERNEL);
137 mutex_unlock(&dev->struct_mutex);
138
139 return ret == -ENOSPC ? -EINVAL : ret;
140}
141
142struct drm_master *drm_master_create(struct drm_minor *minor) 123struct drm_master *drm_master_create(struct drm_minor *minor)
143{ 124{
144 struct drm_master *master; 125 struct drm_master *master;
@@ -262,119 +243,183 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
262 return 0; 243 return 0;
263} 244}
264 245
265/** 246/*
266 * drm_get_minor - Allocate and register new DRM minor 247 * DRM Minors
267 * @dev: DRM device 248 * A DRM device can provide several char-dev interfaces on the DRM-Major. Each
268 * @minor: Pointer to where new minor is stored 249 * of them is represented by a drm_minor object. Depending on the capabilities
269 * @type: Type of minor 250 * of the device-driver, different interfaces are registered.
270 *
271 * Allocate a new minor of the given type and register it. A pointer to the new
272 * minor is returned in @minor.
273 * Caller must hold the global DRM mutex.
274 * 251 *
275 * RETURNS: 252 * Minors can be accessed via dev->$minor_name. This pointer is either
276 * 0 on success, negative error code on failure. 253 * NULL or a valid drm_minor pointer and stays valid as long as the device is
254 * valid. This means, DRM minors have the same life-time as the underlying
255 * device. However, this doesn't mean that the minor is active. Minors are
256 * registered and unregistered dynamically according to device-state.
277 */ 257 */
278static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, 258
279 int type) 259static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
260 unsigned int type)
261{
262 switch (type) {
263 case DRM_MINOR_LEGACY:
264 return &dev->primary;
265 case DRM_MINOR_RENDER:
266 return &dev->render;
267 case DRM_MINOR_CONTROL:
268 return &dev->control;
269 default:
270 return NULL;
271 }
272}
273
274static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
275{
276 struct drm_minor *minor;
277
278 minor = kzalloc(sizeof(*minor), GFP_KERNEL);
279 if (!minor)
280 return -ENOMEM;
281
282 minor->type = type;
283 minor->dev = dev;
284 INIT_LIST_HEAD(&minor->master_list);
285
286 *drm_minor_get_slot(dev, type) = minor;
287 return 0;
288}
289
290static void drm_minor_free(struct drm_device *dev, unsigned int type)
291{
292 struct drm_minor **slot;
293
294 slot = drm_minor_get_slot(dev, type);
295 if (*slot) {
296 kfree(*slot);
297 *slot = NULL;
298 }
299}
300
301static int drm_minor_register(struct drm_device *dev, unsigned int type)
280{ 302{
281 struct drm_minor *new_minor; 303 struct drm_minor *new_minor;
304 unsigned long flags;
282 int ret; 305 int ret;
283 int minor_id; 306 int minor_id;
284 307
285 DRM_DEBUG("\n"); 308 DRM_DEBUG("\n");
286 309
287 minor_id = drm_minor_get_id(dev, type); 310 new_minor = *drm_minor_get_slot(dev, type);
311 if (!new_minor)
312 return 0;
313
314 idr_preload(GFP_KERNEL);
315 spin_lock_irqsave(&drm_minor_lock, flags);
316 minor_id = idr_alloc(&drm_minors_idr,
317 NULL,
318 64 * type,
319 64 * (type + 1),
320 GFP_NOWAIT);
321 spin_unlock_irqrestore(&drm_minor_lock, flags);
322 idr_preload_end();
323
288 if (minor_id < 0) 324 if (minor_id < 0)
289 return minor_id; 325 return minor_id;
290 326
291 new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
292 if (!new_minor) {
293 ret = -ENOMEM;
294 goto err_idr;
295 }
296
297 new_minor->type = type;
298 new_minor->device = MKDEV(DRM_MAJOR, minor_id);
299 new_minor->dev = dev;
300 new_minor->index = minor_id; 327 new_minor->index = minor_id;
301 INIT_LIST_HEAD(&new_minor->master_list);
302
303 idr_replace(&drm_minors_idr, new_minor, minor_id);
304 328
305#if defined(CONFIG_DEBUG_FS)
306 ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root); 329 ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
307 if (ret) { 330 if (ret) {
308 DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); 331 DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
309 goto err_mem; 332 goto err_id;
310 } 333 }
311#endif
312 334
313 ret = drm_sysfs_device_add(new_minor); 335 ret = drm_sysfs_device_add(new_minor);
314 if (ret) { 336 if (ret) {
315 printk(KERN_ERR 337 DRM_ERROR("DRM: Error sysfs_device_add.\n");
316 "DRM: Error sysfs_device_add.\n");
317 goto err_debugfs; 338 goto err_debugfs;
318 } 339 }
319 *minor = new_minor; 340
341 /* replace NULL with @minor so lookups will succeed from now on */
342 spin_lock_irqsave(&drm_minor_lock, flags);
343 idr_replace(&drm_minors_idr, new_minor, new_minor->index);
344 spin_unlock_irqrestore(&drm_minor_lock, flags);
320 345
321 DRM_DEBUG("new minor assigned %d\n", minor_id); 346 DRM_DEBUG("new minor assigned %d\n", minor_id);
322 return 0; 347 return 0;
323 348
324
325err_debugfs: 349err_debugfs:
326#if defined(CONFIG_DEBUG_FS)
327 drm_debugfs_cleanup(new_minor); 350 drm_debugfs_cleanup(new_minor);
328err_mem: 351err_id:
329#endif 352 spin_lock_irqsave(&drm_minor_lock, flags);
330 kfree(new_minor);
331err_idr:
332 idr_remove(&drm_minors_idr, minor_id); 353 idr_remove(&drm_minors_idr, minor_id);
333 *minor = NULL; 354 spin_unlock_irqrestore(&drm_minor_lock, flags);
355 new_minor->index = 0;
334 return ret; 356 return ret;
335} 357}
336 358
337/** 359static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
338 * drm_unplug_minor - Unplug DRM minor
339 * @minor: Minor to unplug
340 *
341 * Unplugs the given DRM minor but keeps the object. So after this returns,
342 * minor->dev is still valid so existing open-files can still access it to get
343 * device information from their drm_file ojects.
344 * If the minor is already unplugged or if @minor is NULL, nothing is done.
345 * The global DRM mutex must be held by the caller.
346 */
347static void drm_unplug_minor(struct drm_minor *minor)
348{ 360{
361 struct drm_minor *minor;
362 unsigned long flags;
363
364 minor = *drm_minor_get_slot(dev, type);
349 if (!minor || !minor->kdev) 365 if (!minor || !minor->kdev)
350 return; 366 return;
351 367
352#if defined(CONFIG_DEBUG_FS) 368 spin_lock_irqsave(&drm_minor_lock, flags);
353 drm_debugfs_cleanup(minor); 369 idr_remove(&drm_minors_idr, minor->index);
354#endif 370 spin_unlock_irqrestore(&drm_minor_lock, flags);
371 minor->index = 0;
355 372
373 drm_debugfs_cleanup(minor);
356 drm_sysfs_device_remove(minor); 374 drm_sysfs_device_remove(minor);
357 idr_remove(&drm_minors_idr, minor->index);
358} 375}
359 376
360/** 377/**
361 * drm_put_minor - Destroy DRM minor 378 * drm_minor_acquire - Acquire a DRM minor
362 * @minor: Minor to destroy 379 * @minor_id: Minor ID of the DRM-minor
380 *
381 * Looks up the given minor-ID and returns the respective DRM-minor object. The
382 * refence-count of the underlying device is increased so you must release this
383 * object with drm_minor_release().
384 *
385 * As long as you hold this minor, it is guaranteed that the object and the
386 * minor->dev pointer will stay valid! However, the device may get unplugged and
387 * unregistered while you hold the minor.
363 * 388 *
364 * This calls drm_unplug_minor() on the given minor and then frees it. Nothing 389 * Returns:
365 * is done if @minor is NULL. It is fine to call this on already unplugged 390 * Pointer to minor-object with increased device-refcount, or PTR_ERR on
366 * minors. 391 * failure.
367 * The global DRM mutex must be held by the caller.
368 */ 392 */
369static void drm_put_minor(struct drm_minor *minor) 393struct drm_minor *drm_minor_acquire(unsigned int minor_id)
370{ 394{
371 if (!minor) 395 struct drm_minor *minor;
372 return; 396 unsigned long flags;
397
398 spin_lock_irqsave(&drm_minor_lock, flags);
399 minor = idr_find(&drm_minors_idr, minor_id);
400 if (minor)
401 drm_dev_ref(minor->dev);
402 spin_unlock_irqrestore(&drm_minor_lock, flags);
403
404 if (!minor) {
405 return ERR_PTR(-ENODEV);
406 } else if (drm_device_is_unplugged(minor->dev)) {
407 drm_dev_unref(minor->dev);
408 return ERR_PTR(-ENODEV);
409 }
373 410
374 DRM_DEBUG("release secondary minor %d\n", minor->index); 411 return minor;
412}
375 413
376 drm_unplug_minor(minor); 414/**
377 kfree(minor); 415 * drm_minor_release - Release DRM minor
416 * @minor: Pointer to DRM minor object
417 *
418 * Release a minor that was previously acquired via drm_minor_acquire().
419 */
420void drm_minor_release(struct drm_minor *minor)
421{
422 drm_dev_unref(minor->dev);
378} 423}
379 424
380/** 425/**
@@ -394,18 +439,16 @@ void drm_put_dev(struct drm_device *dev)
394 } 439 }
395 440
396 drm_dev_unregister(dev); 441 drm_dev_unregister(dev);
397 drm_dev_free(dev); 442 drm_dev_unref(dev);
398} 443}
399EXPORT_SYMBOL(drm_put_dev); 444EXPORT_SYMBOL(drm_put_dev);
400 445
401void drm_unplug_dev(struct drm_device *dev) 446void drm_unplug_dev(struct drm_device *dev)
402{ 447{
403 /* for a USB device */ 448 /* for a USB device */
404 if (drm_core_check_feature(dev, DRIVER_MODESET)) 449 drm_minor_unregister(dev, DRM_MINOR_LEGACY);
405 drm_unplug_minor(dev->control); 450 drm_minor_unregister(dev, DRM_MINOR_RENDER);
406 if (dev->render) 451 drm_minor_unregister(dev, DRM_MINOR_CONTROL);
407 drm_unplug_minor(dev->render);
408 drm_unplug_minor(dev->primary);
409 452
410 mutex_lock(&drm_global_mutex); 453 mutex_lock(&drm_global_mutex);
411 454
@@ -499,6 +542,9 @@ static void drm_fs_inode_free(struct inode *inode)
499 * Call drm_dev_register() to advertice the device to user space and register it 542 * Call drm_dev_register() to advertice the device to user space and register it
500 * with other core subsystems. 543 * with other core subsystems.
501 * 544 *
545 * The initial ref-count of the object is 1. Use drm_dev_ref() and
546 * drm_dev_unref() to take and drop further ref-counts.
547 *
502 * RETURNS: 548 * RETURNS:
503 * Pointer to new DRM device, or NULL if out of memory. 549 * Pointer to new DRM device, or NULL if out of memory.
504 */ 550 */
@@ -512,6 +558,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
512 if (!dev) 558 if (!dev)
513 return NULL; 559 return NULL;
514 560
561 kref_init(&dev->ref);
515 dev->dev = parent; 562 dev->dev = parent;
516 dev->driver = driver; 563 dev->driver = driver;
517 564
@@ -533,8 +580,24 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
533 goto err_free; 580 goto err_free;
534 } 581 }
535 582
583 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
584 ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
585 if (ret)
586 goto err_minors;
587 }
588
589 if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) {
590 ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
591 if (ret)
592 goto err_minors;
593 }
594
595 ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY);
596 if (ret)
597 goto err_minors;
598
536 if (drm_ht_create(&dev->map_hash, 12)) 599 if (drm_ht_create(&dev->map_hash, 12))
537 goto err_inode; 600 goto err_minors;
538 601
539 ret = drm_ctxbitmap_init(dev); 602 ret = drm_ctxbitmap_init(dev);
540 if (ret) { 603 if (ret) {
@@ -556,7 +619,10 @@ err_ctxbitmap:
556 drm_ctxbitmap_cleanup(dev); 619 drm_ctxbitmap_cleanup(dev);
557err_ht: 620err_ht:
558 drm_ht_remove(&dev->map_hash); 621 drm_ht_remove(&dev->map_hash);
559err_inode: 622err_minors:
623 drm_minor_free(dev, DRM_MINOR_LEGACY);
624 drm_minor_free(dev, DRM_MINOR_RENDER);
625 drm_minor_free(dev, DRM_MINOR_CONTROL);
560 drm_fs_inode_free(dev->anon_inode); 626 drm_fs_inode_free(dev->anon_inode);
561err_free: 627err_free:
562 kfree(dev); 628 kfree(dev);
@@ -564,21 +630,9 @@ err_free:
564} 630}
565EXPORT_SYMBOL(drm_dev_alloc); 631EXPORT_SYMBOL(drm_dev_alloc);
566 632
567/** 633static void drm_dev_release(struct kref *ref)
568 * drm_dev_free - Free DRM device
569 * @dev: DRM device to free
570 *
571 * Free a DRM device that has previously been allocated via drm_dev_alloc().
572 * You must not use kfree() instead or you will leak memory.
573 *
574 * This must not be called once the device got registered. Use drm_put_dev()
575 * instead, which then calls drm_dev_free().
576 */
577void drm_dev_free(struct drm_device *dev)
578{ 634{
579 drm_put_minor(dev->control); 635 struct drm_device *dev = container_of(ref, struct drm_device, ref);
580 drm_put_minor(dev->render);
581 drm_put_minor(dev->primary);
582 636
583 if (dev->driver->driver_features & DRIVER_GEM) 637 if (dev->driver->driver_features & DRIVER_GEM)
584 drm_gem_destroy(dev); 638 drm_gem_destroy(dev);
@@ -587,10 +641,46 @@ void drm_dev_free(struct drm_device *dev)
587 drm_ht_remove(&dev->map_hash); 641 drm_ht_remove(&dev->map_hash);
588 drm_fs_inode_free(dev->anon_inode); 642 drm_fs_inode_free(dev->anon_inode);
589 643
644 drm_minor_free(dev, DRM_MINOR_LEGACY);
645 drm_minor_free(dev, DRM_MINOR_RENDER);
646 drm_minor_free(dev, DRM_MINOR_CONTROL);
647
590 kfree(dev->devname); 648 kfree(dev->devname);
591 kfree(dev); 649 kfree(dev);
592} 650}
593EXPORT_SYMBOL(drm_dev_free); 651
652/**
653 * drm_dev_ref - Take reference of a DRM device
654 * @dev: device to take reference of or NULL
655 *
656 * This increases the ref-count of @dev by one. You *must* already own a
657 * reference when calling this. Use drm_dev_unref() to drop this reference
658 * again.
659 *
660 * This function never fails. However, this function does not provide *any*
661 * guarantee whether the device is alive or running. It only provides a
662 * reference to the object and the memory associated with it.
663 */
664void drm_dev_ref(struct drm_device *dev)
665{
666 if (dev)
667 kref_get(&dev->ref);
668}
669EXPORT_SYMBOL(drm_dev_ref);
670
671/**
672 * drm_dev_unref - Drop reference of a DRM device
673 * @dev: device to drop reference of or NULL
674 *
675 * This decreases the ref-count of @dev by one. The device is destroyed if the
676 * ref-count drops to zero.
677 */
678void drm_dev_unref(struct drm_device *dev)
679{
680 if (dev)
681 kref_put(&dev->ref, drm_dev_release);
682}
683EXPORT_SYMBOL(drm_dev_unref);
594 684
595/** 685/**
596 * drm_dev_register - Register DRM device 686 * drm_dev_register - Register DRM device
@@ -611,26 +701,22 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
611 701
612 mutex_lock(&drm_global_mutex); 702 mutex_lock(&drm_global_mutex);
613 703
614 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 704 ret = drm_minor_register(dev, DRM_MINOR_CONTROL);
615 ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); 705 if (ret)
616 if (ret) 706 goto err_minors;
617 goto out_unlock;
618 }
619 707
620 if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { 708 ret = drm_minor_register(dev, DRM_MINOR_RENDER);
621 ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER); 709 if (ret)
622 if (ret) 710 goto err_minors;
623 goto err_control_node;
624 }
625 711
626 ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY); 712 ret = drm_minor_register(dev, DRM_MINOR_LEGACY);
627 if (ret) 713 if (ret)
628 goto err_render_node; 714 goto err_minors;
629 715
630 if (dev->driver->load) { 716 if (dev->driver->load) {
631 ret = dev->driver->load(dev, flags); 717 ret = dev->driver->load(dev, flags);
632 if (ret) 718 if (ret)
633 goto err_primary_node; 719 goto err_minors;
634 } 720 }
635 721
636 /* setup grouping for legacy outputs */ 722 /* setup grouping for legacy outputs */
@@ -647,12 +733,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
647err_unload: 733err_unload:
648 if (dev->driver->unload) 734 if (dev->driver->unload)
649 dev->driver->unload(dev); 735 dev->driver->unload(dev);
650err_primary_node: 736err_minors:
651 drm_unplug_minor(dev->primary); 737 drm_minor_unregister(dev, DRM_MINOR_LEGACY);
652err_render_node: 738 drm_minor_unregister(dev, DRM_MINOR_RENDER);
653 drm_unplug_minor(dev->render); 739 drm_minor_unregister(dev, DRM_MINOR_CONTROL);
654err_control_node:
655 drm_unplug_minor(dev->control);
656out_unlock: 740out_unlock:
657 mutex_unlock(&drm_global_mutex); 741 mutex_unlock(&drm_global_mutex);
658 return ret; 742 return ret;
@@ -665,7 +749,7 @@ EXPORT_SYMBOL(drm_dev_register);
665 * 749 *
666 * Unregister the DRM device from the system. This does the reverse of 750 * Unregister the DRM device from the system. This does the reverse of
667 * drm_dev_register() but does not deallocate the device. The caller must call 751 * drm_dev_register() but does not deallocate the device. The caller must call
668 * drm_dev_free() to free all resources. 752 * drm_dev_unref() to drop their final reference.
669 */ 753 */
670void drm_dev_unregister(struct drm_device *dev) 754void drm_dev_unregister(struct drm_device *dev)
671{ 755{
@@ -684,8 +768,8 @@ void drm_dev_unregister(struct drm_device *dev)
684 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) 768 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
685 drm_rmmap(dev, r_list->map); 769 drm_rmmap(dev, r_list->map);
686 770
687 drm_unplug_minor(dev->control); 771 drm_minor_unregister(dev, DRM_MINOR_LEGACY);
688 drm_unplug_minor(dev->render); 772 drm_minor_unregister(dev, DRM_MINOR_RENDER);
689 drm_unplug_minor(dev->primary); 773 drm_minor_unregister(dev, DRM_MINOR_CONTROL);
690} 774}
691EXPORT_SYMBOL(drm_dev_unregister); 775EXPORT_SYMBOL(drm_dev_unregister);
diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c
index 0f8cb1ae7607..c3406aad2944 100644
--- a/drivers/gpu/drm/drm_usb.c
+++ b/drivers/gpu/drm/drm_usb.c
@@ -30,7 +30,7 @@ int drm_get_usb_dev(struct usb_interface *interface,
30 return 0; 30 return 0;
31 31
32err_free: 32err_free:
33 drm_dev_free(dev); 33 drm_dev_unref(dev);
34 return ret; 34 return ret;
35 35
36} 36}
diff --git a/drivers/gpu/drm/tegra/bus.c b/drivers/gpu/drm/tegra/bus.c
index e38e5967d77b..71cef5c13dc8 100644
--- a/drivers/gpu/drm/tegra/bus.c
+++ b/drivers/gpu/drm/tegra/bus.c
@@ -63,7 +63,7 @@ int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
63 return 0; 63 return 0;
64 64
65err_free: 65err_free:
66 drm_dev_free(drm); 66 drm_dev_unref(drm);
67 return ret; 67 return ret;
68} 68}
69 69
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3227b716ffdf..99a17c8a1293 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -43,6 +43,7 @@
43#include <asm/current.h> 43#include <asm/current.h>
44#endif /* __alpha__ */ 44#endif /* __alpha__ */
45#include <linux/kernel.h> 45#include <linux/kernel.h>
46#include <linux/kref.h>
46#include <linux/miscdevice.h> 47#include <linux/miscdevice.h>
47#include <linux/fs.h> 48#include <linux/fs.h>
48#include <linux/init.h> 49#include <linux/init.h>
@@ -1008,10 +1009,12 @@ struct drm_driver {
1008 struct list_head legacy_dev_list; 1009 struct list_head legacy_dev_list;
1009}; 1010};
1010 1011
1011#define DRM_MINOR_UNASSIGNED 0 1012enum drm_minor_type {
1012#define DRM_MINOR_LEGACY 1 1013 DRM_MINOR_LEGACY,
1013#define DRM_MINOR_CONTROL 2 1014 DRM_MINOR_CONTROL,
1014#define DRM_MINOR_RENDER 3 1015 DRM_MINOR_RENDER,
1016 DRM_MINOR_CNT,
1017};
1015 1018
1016/** 1019/**
1017 * Info file list entry. This structure represents a debugfs or proc file to 1020 * Info file list entry. This structure represents a debugfs or proc file to
@@ -1040,7 +1043,6 @@ struct drm_info_node {
1040struct drm_minor { 1043struct drm_minor {
1041 int index; /**< Minor device number */ 1044 int index; /**< Minor device number */
1042 int type; /**< Control or render */ 1045 int type; /**< Control or render */
1043 dev_t device; /**< Device number for mknod */
1044 struct device *kdev; /**< Linux device */ 1046 struct device *kdev; /**< Linux device */
1045 struct drm_device *dev; 1047 struct drm_device *dev;
1046 1048
@@ -1098,6 +1100,19 @@ struct drm_device {
1098 char *devname; /**< For /proc/interrupts */ 1100 char *devname; /**< For /proc/interrupts */
1099 int if_version; /**< Highest interface version set */ 1101 int if_version; /**< Highest interface version set */
1100 1102
1103 /** \name Lifetime Management */
1104 /*@{ */
1105 struct kref ref; /**< Object ref-count */
1106 struct device *dev; /**< Device structure of bus-device */
1107 struct drm_driver *driver; /**< DRM driver managing the device */
1108 void *dev_private; /**< DRM driver private data */
1109 struct drm_minor *control; /**< Control node */
1110 struct drm_minor *primary; /**< Primary node */
1111 struct drm_minor *render; /**< Render node */
1112 atomic_t unplugged; /**< Flag whether dev is dead */
1113 struct inode *anon_inode; /**< inode for private address-space */
1114 /*@} */
1115
1101 /** \name Locks */ 1116 /** \name Locks */
1102 /*@{ */ 1117 /*@{ */
1103 spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */ 1118 spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
@@ -1171,7 +1186,6 @@ struct drm_device {
1171 1186
1172 struct drm_agp_head *agp; /**< AGP data */ 1187 struct drm_agp_head *agp; /**< AGP data */
1173 1188
1174 struct device *dev; /**< Device structure */
1175 struct pci_dev *pdev; /**< PCI device structure */ 1189 struct pci_dev *pdev; /**< PCI device structure */
1176#ifdef __alpha__ 1190#ifdef __alpha__
1177 struct pci_controller *hose; 1191 struct pci_controller *hose;
@@ -1182,17 +1196,11 @@ struct drm_device {
1182 1196
1183 struct drm_sg_mem *sg; /**< Scatter gather memory */ 1197 struct drm_sg_mem *sg; /**< Scatter gather memory */
1184 unsigned int num_crtcs; /**< Number of CRTCs on this device */ 1198 unsigned int num_crtcs; /**< Number of CRTCs on this device */
1185 void *dev_private; /**< device private data */
1186 struct inode *anon_inode;
1187 struct drm_sigdata sigdata; /**< For block_all_signals */ 1199 struct drm_sigdata sigdata; /**< For block_all_signals */
1188 sigset_t sigmask; 1200 sigset_t sigmask;
1189 1201
1190 struct drm_driver *driver;
1191 struct drm_local_map *agp_buffer_map; 1202 struct drm_local_map *agp_buffer_map;
1192 unsigned int agp_buffer_token; 1203 unsigned int agp_buffer_token;
1193 struct drm_minor *control; /**< Control node for card */
1194 struct drm_minor *primary; /**< render type primary screen head */
1195 struct drm_minor *render; /**< render node for card */
1196 1204
1197 struct drm_mode_config mode_config; /**< Current mode config */ 1205 struct drm_mode_config mode_config; /**< Current mode config */
1198 1206
@@ -1203,8 +1211,6 @@ struct drm_device {
1203 struct drm_vma_offset_manager *vma_offset_manager; 1211 struct drm_vma_offset_manager *vma_offset_manager;
1204 /*@} */ 1212 /*@} */
1205 int switch_power_state; 1213 int switch_power_state;
1206
1207 atomic_t unplugged; /* device has been unplugged or gone away */
1208}; 1214};
1209 1215
1210#define DRM_SWITCH_POWER_ON 0 1216#define DRM_SWITCH_POWER_ON 0
@@ -1661,9 +1667,14 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map)
1661 1667
1662struct drm_device *drm_dev_alloc(struct drm_driver *driver, 1668struct drm_device *drm_dev_alloc(struct drm_driver *driver,
1663 struct device *parent); 1669 struct device *parent);
1664void drm_dev_free(struct drm_device *dev); 1670void drm_dev_ref(struct drm_device *dev);
1671void drm_dev_unref(struct drm_device *dev);
1665int drm_dev_register(struct drm_device *dev, unsigned long flags); 1672int drm_dev_register(struct drm_device *dev, unsigned long flags);
1666void drm_dev_unregister(struct drm_device *dev); 1673void drm_dev_unregister(struct drm_device *dev);
1674
1675struct drm_minor *drm_minor_acquire(unsigned int minor_id);
1676void drm_minor_release(struct drm_minor *minor);
1677
1667/*@}*/ 1678/*@}*/
1668 1679
1669/* PCI section */ 1680/* PCI section */