drm_drv.c 22.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6
/*
 * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
 *
 * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
 * All Rights Reserved.
 *
7 8
 * Author Rickard E. (Rik) Faith <faith@valinux.com>
 *
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

29
#include <linux/debugfs.h>
30
#include <linux/fs.h>
L
Linus Torvalds 已提交
31 32
#include <linux/module.h>
#include <linux/moduleparam.h>
33
#include <linux/mount.h>
34
#include <linux/slab.h>
35 36
#include <drm/drmP.h>
#include <drm/drm_core.h>
37
#include "drm_legacy.h"
L
Linus Torvalds 已提交
38

D
Dave Airlie 已提交
39
unsigned int drm_debug = 0;	/* 1 to enable debug output */
L
Linus Torvalds 已提交
40 41
EXPORT_SYMBOL(drm_debug);

42 43 44 45
unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */

unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */

46 47 48 49 50 51
/*
 * Default to use monotonic timestamps for wait-for-vblank and page-flip
 * complete events.
 */
unsigned int drm_timestamp_monotonic = 1;

D
Dave Airlie 已提交
52 53
MODULE_AUTHOR(CORE_AUTHOR);
MODULE_DESCRIPTION(CORE_DESC);
L
Linus Torvalds 已提交
54 55
MODULE_LICENSE("GPL and additional rights");
MODULE_PARM_DESC(debug, "Enable debug output");
56 57
MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
58
MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
L
Linus Torvalds 已提交
59

60
module_param_named(debug, drm_debug, int, 0600);
61 62
module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
63
module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
L
Linus Torvalds 已提交
64

65
static DEFINE_SPINLOCK(drm_minor_lock);
66
static struct idr drm_minors_idr;
67

68
struct class *drm_class;
69
static struct dentry *drm_debugfs_root;
J
Joe Perches 已提交
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

int drm_err(const char *func, const char *format, ...)
{
	struct va_format vaf;
	va_list args;
	int r;

	va_start(args, format);

	vaf.fmt = format;
	vaf.va = &args;

	r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);

	va_end(args);

	return r;
}
EXPORT_SYMBOL(drm_err);

90
void drm_ut_debug_printk(const char *function_name, const char *format, ...)
91
{
D
Daniel Vetter 已提交
92
	struct va_format vaf;
93
	va_list args;
L
Linus Torvalds 已提交
94

95 96 97 98
	va_start(args, format);
	vaf.fmt = format;
	vaf.va = &args;

99
	printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf);
100 101

	va_end(args);
102 103
}
EXPORT_SYMBOL(drm_ut_debug_printk);
J
Joe Perches 已提交
104

105 106 107 108
struct drm_master *drm_master_create(struct drm_minor *minor)
{
	struct drm_master *master;

109
	master = kzalloc(sizeof(*master), GFP_KERNEL);
110 111 112 113 114 115
	if (!master)
		return NULL;

	kref_init(&master->refcount);
	spin_lock_init(&master->lock.spinlock);
	init_waitqueue_head(&master->lock.lock_queue);
116 117 118 119
	if (drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER)) {
		kfree(master);
		return NULL;
	}
120 121 122 123 124 125 126 127 128 129 130
	INIT_LIST_HEAD(&master->magicfree);
	master->minor = minor;

	return master;
}

struct drm_master *drm_master_get(struct drm_master *master)
{
	kref_get(&master->refcount);
	return master;
}
131
EXPORT_SYMBOL(drm_master_get);
132 133 134 135 136 137

static void drm_master_destroy(struct kref *kref)
{
	struct drm_master *master = container_of(kref, struct drm_master, refcount);
	struct drm_magic_entry *pt, *next;
	struct drm_device *dev = master->minor->dev;
138
	struct drm_map_list *r_list, *list_temp;
139

140
	mutex_lock(&dev->struct_mutex);
141 142 143
	if (dev->driver->master_destroy)
		dev->driver->master_destroy(dev, master);

144 145 146 147 148 149 150
	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
		if (r_list->master == master) {
			drm_rmmap_locked(dev, r_list->map);
			r_list = NULL;
		}
	}

151
	if (master->unique) {
152
		kfree(master->unique);
153 154 155 156 157 158 159
		master->unique = NULL;
		master->unique_len = 0;
	}

	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
		list_del(&pt->head);
		drm_ht_remove_item(&master->magiclist, &pt->hash_item);
160
		kfree(pt);
161 162 163 164
	}

	drm_ht_remove(&master->magiclist);

165
	mutex_unlock(&dev->struct_mutex);
166
	kfree(master);
167 168 169 170 171 172 173
}

void drm_master_put(struct drm_master **master)
{
	kref_put(&(*master)->refcount, drm_master_destroy);
	*master = NULL;
}
174
EXPORT_SYMBOL(drm_master_put);
175 176 177 178

int drm_setmaster_ioctl(struct drm_device *dev, void *data,
			struct drm_file *file_priv)
{
179
	int ret = 0;
180

181
	mutex_lock(&dev->master_mutex);
182
	if (drm_is_master(file_priv))
183
		goto out_unlock;
184

185 186 187 188
	if (file_priv->minor->master) {
		ret = -EINVAL;
		goto out_unlock;
	}
189

190 191 192 193
	if (!file_priv->master) {
		ret = -EINVAL;
		goto out_unlock;
	}
194 195 196 197

	file_priv->minor->master = drm_master_get(file_priv->master);
	if (dev->driver->master_set) {
		ret = dev->driver->master_set(dev, file_priv, false);
198
		if (unlikely(ret != 0))
199
			drm_master_put(&file_priv->minor->master);
200 201
	}

202 203
out_unlock:
	mutex_unlock(&dev->master_mutex);
204
	return ret;
205 206 207 208 209
}

int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
{
210 211 212
	int ret = -EINVAL;

	mutex_lock(&dev->master_mutex);
213
	if (!drm_is_master(file_priv))
214
		goto out_unlock;
215

216
	if (!file_priv->minor->master)
217
		goto out_unlock;
218

219
	ret = 0;
220 221
	if (dev->driver->master_drop)
		dev->driver->master_drop(dev, file_priv, false);
222
	drm_master_put(&file_priv->minor->master);
223 224 225 226

out_unlock:
	mutex_unlock(&dev->master_mutex);
	return ret;
227 228
}

229 230 231 232 233
/*
 * DRM Minors
 * A DRM device can provide several char-dev interfaces on the DRM-Major. Each
 * of them is represented by a drm_minor object. Depending on the capabilities
 * of the device-driver, different interfaces are registered.
L
Linus Torvalds 已提交
234
 *
235 236 237 238 239
 * Minors can be accessed via dev->$minor_name. This pointer is either
 * NULL or a valid drm_minor pointer and stays valid as long as the device is
 * valid. This means, DRM minors have the same life-time as the underlying
 * device. However, this doesn't mean that the minor is active. Minors are
 * registered and unregistered dynamically according to device-state.
L
Linus Torvalds 已提交
240
 */
241

D
David Herrmann 已提交
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
					     unsigned int type)
{
	switch (type) {
	case DRM_MINOR_LEGACY:
		return &dev->primary;
	case DRM_MINOR_RENDER:
		return &dev->render;
	case DRM_MINOR_CONTROL:
		return &dev->control;
	default:
		return NULL;
	}
}

static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
{
	struct drm_minor *minor;
260 261
	unsigned long flags;
	int r;
D
David Herrmann 已提交
262 263 264 265 266 267 268 269

	minor = kzalloc(sizeof(*minor), GFP_KERNEL);
	if (!minor)
		return -ENOMEM;

	minor->type = type;
	minor->dev = dev;

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
	idr_preload(GFP_KERNEL);
	spin_lock_irqsave(&drm_minor_lock, flags);
	r = idr_alloc(&drm_minors_idr,
		      NULL,
		      64 * type,
		      64 * (type + 1),
		      GFP_NOWAIT);
	spin_unlock_irqrestore(&drm_minor_lock, flags);
	idr_preload_end();

	if (r < 0)
		goto err_free;

	minor->index = r;

285 286 287 288 289 290
	minor->kdev = drm_sysfs_minor_alloc(minor);
	if (IS_ERR(minor->kdev)) {
		r = PTR_ERR(minor->kdev);
		goto err_index;
	}

D
David Herrmann 已提交
291 292
	*drm_minor_get_slot(dev, type) = minor;
	return 0;
293

294 295 296 297
err_index:
	spin_lock_irqsave(&drm_minor_lock, flags);
	idr_remove(&drm_minors_idr, minor->index);
	spin_unlock_irqrestore(&drm_minor_lock, flags);
298 299 300
err_free:
	kfree(minor);
	return r;
D
David Herrmann 已提交
301 302
}

303 304
static void drm_minor_free(struct drm_device *dev, unsigned int type)
{
305 306
	struct drm_minor **slot, *minor;
	unsigned long flags;
307 308

	slot = drm_minor_get_slot(dev, type);
309 310 311 312 313
	minor = *slot;
	if (!minor)
		return;

	drm_mode_group_destroy(&minor->mode_group);
314
	put_device(minor->kdev);
315 316 317 318 319 320 321

	spin_lock_irqsave(&drm_minor_lock, flags);
	idr_remove(&drm_minors_idr, minor->index);
	spin_unlock_irqrestore(&drm_minor_lock, flags);

	kfree(minor);
	*slot = NULL;
322 323
}

324
static int drm_minor_register(struct drm_device *dev, unsigned int type)
L
Linus Torvalds 已提交
325
{
326
	struct drm_minor *minor;
327
	unsigned long flags;
L
Linus Torvalds 已提交
328 329 330 331
	int ret;

	DRM_DEBUG("\n");

332 333
	minor = *drm_minor_get_slot(dev, type);
	if (!minor)
D
David Herrmann 已提交
334 335
		return 0;

336
	ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
337
	if (ret) {
338
		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
339
		return ret;
340
	}
341

342 343
	ret = device_add(minor->kdev);
	if (ret)
D
Daniel Vetter 已提交
344
		goto err_debugfs;
345

346 347
	/* replace NULL with @minor so lookups will succeed from now on */
	spin_lock_irqsave(&drm_minor_lock, flags);
348
	idr_replace(&drm_minors_idr, minor, minor->index);
349
	spin_unlock_irqrestore(&drm_minor_lock, flags);
350

351
	DRM_DEBUG("new minor registered %d\n", minor->index);
352 353
	return 0;

D
Daniel Vetter 已提交
354
err_debugfs:
355
	drm_debugfs_cleanup(minor);
L
Linus Torvalds 已提交
356 357
	return ret;
}
D
Dave Airlie 已提交
358

359
static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
360
{
361
	struct drm_minor *minor;
362
	unsigned long flags;
363 364

	minor = *drm_minor_get_slot(dev, type);
365
	if (!minor || !device_is_registered(minor->kdev))
366 367
		return;

368
	/* replace @minor with NULL so lookups will fail from now on */
369
	spin_lock_irqsave(&drm_minor_lock, flags);
370
	idr_replace(&drm_minors_idr, NULL, minor->index);
371
	spin_unlock_irqrestore(&drm_minor_lock, flags);
372

373 374
	device_del(minor->kdev);
	dev_set_drvdata(minor->kdev, NULL); /* safety belt */
375
	drm_debugfs_cleanup(minor);
376 377 378
}

/**
379 380 381 382 383 384 385 386 387 388
 * drm_minor_acquire - Acquire a DRM minor
 * @minor_id: Minor ID of the DRM-minor
 *
 * Looks up the given minor-ID and returns the respective DRM-minor object. The
 * refence-count of the underlying device is increased so you must release this
 * object with drm_minor_release().
 *
 * As long as you hold this minor, it is guaranteed that the object and the
 * minor->dev pointer will stay valid! However, the device may get unplugged and
 * unregistered while you hold the minor.
389
 *
390 391 392
 * Returns:
 * Pointer to minor-object with increased device-refcount, or PTR_ERR on
 * failure.
L
Linus Torvalds 已提交
393
 */
394
struct drm_minor *drm_minor_acquire(unsigned int minor_id)
L
Linus Torvalds 已提交
395
{
396
	struct drm_minor *minor;
397
	unsigned long flags;
398

399
	spin_lock_irqsave(&drm_minor_lock, flags);
400
	minor = idr_find(&drm_minors_idr, minor_id);
401 402 403 404 405 406 407 408
	if (minor)
		drm_dev_ref(minor->dev);
	spin_unlock_irqrestore(&drm_minor_lock, flags);

	if (!minor) {
		return ERR_PTR(-ENODEV);
	} else if (drm_device_is_unplugged(minor->dev)) {
		drm_dev_unref(minor->dev);
409
		return ERR_PTR(-ENODEV);
410
	}
411

412 413
	return minor;
}
D
Dave Airlie 已提交
414

415 416 417 418 419 420 421 422 423
/**
 * drm_minor_release - Release DRM minor
 * @minor: Pointer to DRM minor object
 *
 * Release a minor that was previously acquired via drm_minor_acquire().
 */
void drm_minor_release(struct drm_minor *minor)
{
	drm_dev_unref(minor->dev);
L
Linus Torvalds 已提交
424
}
425 426

/**
427 428
 * drm_put_dev - Unregister and release a DRM device
 * @dev: DRM device
429
 *
430
 * Called at module unload time or when a PCI device is unplugged.
431
 *
432 433 434 435
 * Use of this function is discouraged. It will eventually go away completely.
 * Please use drm_dev_unregister() and drm_dev_unref() explicitly instead.
 *
 * Cleans up all DRM device, calling drm_lastclose().
436 437 438 439 440 441 442 443 444 445
 */
void drm_put_dev(struct drm_device *dev)
{
	DRM_DEBUG("\n");

	if (!dev) {
		DRM_ERROR("cleanup called no dev\n");
		return;
	}

446
	drm_dev_unregister(dev);
D
David Herrmann 已提交
447
	drm_dev_unref(dev);
448 449
}
EXPORT_SYMBOL(drm_put_dev);
450 451 452 453

void drm_unplug_dev(struct drm_device *dev)
{
	/* for a USB device */
454 455 456
	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
	drm_minor_unregister(dev, DRM_MINOR_RENDER);
	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
457 458 459 460 461 462 463 464 465 466 467

	mutex_lock(&drm_global_mutex);

	drm_device_set_unplugged(dev);

	if (dev->open_count == 0) {
		drm_put_dev(dev);
	}
	mutex_unlock(&drm_global_mutex);
}
EXPORT_SYMBOL(drm_unplug_dev);
D
David Herrmann 已提交
468

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
/*
 * DRM internal mount
 * We want to be able to allocate our own "struct address_space" to control
 * memory-mappings in VRAM (or stolen RAM, ...). However, core MM does not allow
 * stand-alone address_space objects, so we need an underlying inode. As there
 * is no way to allocate an independent inode easily, we need a fake internal
 * VFS mount-point.
 *
 * The drm_fs_inode_new() function allocates a new inode, drm_fs_inode_free()
 * frees it again. You are allowed to use iget() and iput() to get references to
 * the inode. But each drm_fs_inode_new() call must be paired with exactly one
 * drm_fs_inode_free() call (which does not have to be the last iput()).
 * We use drm_fs_inode_*() to manage our internal VFS mount-point and share it
 * between multiple inode-users. You could, technically, call
 * iget() + drm_fs_inode_free() directly after alloc and sometime later do an
 * iput(), but this way you'd end up with a new vfsmount for each inode.
 */

static int drm_fs_cnt;
static struct vfsmount *drm_fs_mnt;

static const struct dentry_operations drm_fs_dops = {
	.d_dname	= simple_dname,
};

static const struct super_operations drm_fs_sops = {
	.statfs		= simple_statfs,
};

static struct dentry *drm_fs_mount(struct file_system_type *fs_type, int flags,
				   const char *dev_name, void *data)
{
	return mount_pseudo(fs_type,
			    "drm:",
			    &drm_fs_sops,
			    &drm_fs_dops,
			    0x010203ff);
}

static struct file_system_type drm_fs_type = {
	.name		= "drm",
	.owner		= THIS_MODULE,
	.mount		= drm_fs_mount,
	.kill_sb	= kill_anon_super,
};

static struct inode *drm_fs_inode_new(void)
{
	struct inode *inode;
	int r;

	r = simple_pin_fs(&drm_fs_type, &drm_fs_mnt, &drm_fs_cnt);
	if (r < 0) {
		DRM_ERROR("Cannot mount pseudo fs: %d\n", r);
		return ERR_PTR(r);
	}

	inode = alloc_anon_inode(drm_fs_mnt->mnt_sb);
	if (IS_ERR(inode))
		simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);

	return inode;
}

static void drm_fs_inode_free(struct inode *inode)
{
	if (inode) {
		iput(inode);
		simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
	}
}

D
David Herrmann 已提交
541
/**
542
 * drm_dev_alloc - Allocate new DRM device
D
David Herrmann 已提交
543 544 545 546
 * @driver: DRM driver to allocate device for
 * @parent: Parent device object
 *
 * Allocate and initialize a new DRM device. No device registration is done.
547 548
 * Call drm_dev_register() to advertice the device to user space and register it
 * with other core subsystems.
D
David Herrmann 已提交
549
 *
D
David Herrmann 已提交
550 551 552
 * The initial ref-count of the object is 1. Use drm_dev_ref() and
 * drm_dev_unref() to take and drop further ref-counts.
 *
D
David Herrmann 已提交
553 554 555 556 557 558 559 560 561 562 563 564 565
 * RETURNS:
 * Pointer to new DRM device, or NULL if out of memory.
 */
struct drm_device *drm_dev_alloc(struct drm_driver *driver,
				 struct device *parent)
{
	struct drm_device *dev;
	int ret;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return NULL;

D
David Herrmann 已提交
566
	kref_init(&dev->ref);
D
David Herrmann 已提交
567 568 569 570 571 572 573 574 575
	dev->dev = parent;
	dev->driver = driver;

	INIT_LIST_HEAD(&dev->filelist);
	INIT_LIST_HEAD(&dev->ctxlist);
	INIT_LIST_HEAD(&dev->vmalist);
	INIT_LIST_HEAD(&dev->maplist);
	INIT_LIST_HEAD(&dev->vblank_event_list);

576
	spin_lock_init(&dev->buf_lock);
D
David Herrmann 已提交
577 578 579
	spin_lock_init(&dev->event_lock);
	mutex_init(&dev->struct_mutex);
	mutex_init(&dev->ctxlist_mutex);
580
	mutex_init(&dev->master_mutex);
D
David Herrmann 已提交
581

582 583 584 585
	dev->anon_inode = drm_fs_inode_new();
	if (IS_ERR(dev->anon_inode)) {
		ret = PTR_ERR(dev->anon_inode);
		DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
D
David Herrmann 已提交
586
		goto err_free;
587 588
	}

D
David Herrmann 已提交
589 590 591 592 593 594
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
		if (ret)
			goto err_minors;
	}

595
	if (drm_core_check_feature(dev, DRIVER_RENDER)) {
D
David Herrmann 已提交
596 597 598 599 600 601 602 603 604
		ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
		if (ret)
			goto err_minors;
	}

	ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY);
	if (ret)
		goto err_minors;

605
	if (drm_ht_create(&dev->map_hash, 12))
D
David Herrmann 已提交
606
		goto err_minors;
D
David Herrmann 已提交
607

608
	ret = drm_legacy_ctxbitmap_init(dev);
D
David Herrmann 已提交
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
	if (ret) {
		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
		goto err_ht;
	}

	if (driver->driver_features & DRIVER_GEM) {
		ret = drm_gem_init(dev);
		if (ret) {
			DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
			goto err_ctxbitmap;
		}
	}

	return dev;

err_ctxbitmap:
625
	drm_legacy_ctxbitmap_cleanup(dev);
D
David Herrmann 已提交
626 627
err_ht:
	drm_ht_remove(&dev->map_hash);
D
David Herrmann 已提交
628
err_minors:
629 630 631
	drm_minor_free(dev, DRM_MINOR_LEGACY);
	drm_minor_free(dev, DRM_MINOR_RENDER);
	drm_minor_free(dev, DRM_MINOR_CONTROL);
632
	drm_fs_inode_free(dev->anon_inode);
D
David Herrmann 已提交
633
err_free:
634
	mutex_destroy(&dev->master_mutex);
D
David Herrmann 已提交
635 636 637 638
	kfree(dev);
	return NULL;
}
EXPORT_SYMBOL(drm_dev_alloc);
639

D
David Herrmann 已提交
640
static void drm_dev_release(struct kref *ref)
641
{
D
David Herrmann 已提交
642
	struct drm_device *dev = container_of(ref, struct drm_device, ref);
643

644 645 646
	if (dev->driver->driver_features & DRIVER_GEM)
		drm_gem_destroy(dev);

647
	drm_legacy_ctxbitmap_cleanup(dev);
648
	drm_ht_remove(&dev->map_hash);
649
	drm_fs_inode_free(dev->anon_inode);
650

651 652 653 654
	drm_minor_free(dev, DRM_MINOR_LEGACY);
	drm_minor_free(dev, DRM_MINOR_RENDER);
	drm_minor_free(dev, DRM_MINOR_CONTROL);

655
	mutex_destroy(&dev->master_mutex);
656
	kfree(dev->unique);
657 658
	kfree(dev);
}
D
David Herrmann 已提交
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691

/**
 * drm_dev_ref - Take reference of a DRM device
 * @dev: device to take reference of or NULL
 *
 * This increases the ref-count of @dev by one. You *must* already own a
 * reference when calling this. Use drm_dev_unref() to drop this reference
 * again.
 *
 * This function never fails. However, this function does not provide *any*
 * guarantee whether the device is alive or running. It only provides a
 * reference to the object and the memory associated with it.
 */
void drm_dev_ref(struct drm_device *dev)
{
	if (dev)
		kref_get(&dev->ref);
}
EXPORT_SYMBOL(drm_dev_ref);

/**
 * drm_dev_unref - Drop reference of a DRM device
 * @dev: device to drop reference of or NULL
 *
 * This decreases the ref-count of @dev by one. The device is destroyed if the
 * ref-count drops to zero.
 */
void drm_dev_unref(struct drm_device *dev)
{
	if (dev)
		kref_put(&dev->ref, drm_dev_release);
}
EXPORT_SYMBOL(drm_dev_unref);
692

693 694 695
/**
 * drm_dev_register - Register DRM device
 * @dev: Device to register
696
 * @flags: Flags passed to the driver's .load() function
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
 *
 * Register the DRM device @dev with the system, advertise device to user-space
 * and start normal device operation. @dev must be allocated via drm_dev_alloc()
 * previously.
 *
 * Never call this twice on any device!
 *
 * RETURNS:
 * 0 on success, negative error code on failure.
 */
int drm_dev_register(struct drm_device *dev, unsigned long flags)
{
	int ret;

	mutex_lock(&drm_global_mutex);

713
	ret = drm_minor_register(dev, DRM_MINOR_CONTROL);
D
David Herrmann 已提交
714 715
	if (ret)
		goto err_minors;
716

717
	ret = drm_minor_register(dev, DRM_MINOR_RENDER);
D
David Herrmann 已提交
718 719
	if (ret)
		goto err_minors;
720

721
	ret = drm_minor_register(dev, DRM_MINOR_LEGACY);
722
	if (ret)
D
David Herrmann 已提交
723
		goto err_minors;
724 725 726 727

	if (dev->driver->load) {
		ret = dev->driver->load(dev, flags);
		if (ret)
D
David Herrmann 已提交
728
			goto err_minors;
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
	}

	/* setup grouping for legacy outputs */
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		ret = drm_mode_group_init_legacy_group(dev,
				&dev->primary->mode_group);
		if (ret)
			goto err_unload;
	}

	ret = 0;
	goto out_unlock;

err_unload:
	if (dev->driver->unload)
		dev->driver->unload(dev);
D
David Herrmann 已提交
745
err_minors:
746 747 748
	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
	drm_minor_unregister(dev, DRM_MINOR_RENDER);
	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
749 750 751 752 753
out_unlock:
	mutex_unlock(&drm_global_mutex);
	return ret;
}
EXPORT_SYMBOL(drm_dev_register);
754 755 756 757 758 759 760

/**
 * drm_dev_unregister - Unregister DRM device
 * @dev: Device to unregister
 *
 * Unregister the DRM device from the system. This does the reverse of
 * drm_dev_register() but does not deallocate the device. The caller must call
D
David Herrmann 已提交
761
 * drm_dev_unref() to drop their final reference.
762 763 764 765 766 767 768 769 770 771
 */
void drm_dev_unregister(struct drm_device *dev)
{
	struct drm_map_list *r_list, *list_temp;

	drm_lastclose(dev);

	if (dev->driver->unload)
		dev->driver->unload(dev);

772 773
	if (dev->agp)
		drm_pci_agp_destroy(dev);
774 775 776 777 778 779

	drm_vblank_cleanup(dev);

	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
		drm_rmmap(dev, r_list->map);

780 781 782
	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
	drm_minor_unregister(dev, DRM_MINOR_RENDER);
	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
783 784
}
EXPORT_SYMBOL(drm_dev_unregister);
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809

/**
 * drm_dev_set_unique - Set the unique name of a DRM device
 * @dev: device of which to set the unique name
 * @fmt: format string for unique name
 *
 * Sets the unique name of a DRM device using the specified format string and
 * a variable list of arguments. Drivers can use this at driver probe time if
 * the unique name of the devices they drive is static.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...)
{
	va_list ap;

	kfree(dev->unique);

	va_start(ap, fmt);
	dev->unique = kvasprintf(GFP_KERNEL, fmt, ap);
	va_end(ap);

	return dev->unique ? 0 : -ENOMEM;
}
EXPORT_SYMBOL(drm_dev_set_unique);
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921

/*
 * DRM Core
 * The DRM core module initializes all global DRM objects and makes them
 * available to drivers. Once setup, drivers can probe their respective
 * devices.
 * Currently, core management includes:
 *  - The "DRM-Global" key/value database
 *  - Global ID management for connectors
 *  - DRM major number allocation
 *  - DRM minor management
 *  - DRM sysfs class
 *  - DRM debugfs root
 *
 * Furthermore, the DRM core provides dynamic char-dev lookups. For each
 * interface registered on a DRM device, you can request minor numbers from DRM
 * core. DRM core takes care of major-number management and char-dev
 * registration. A stub ->open() callback forwards any open() requests to the
 * registered minor.
 */

static int drm_stub_open(struct inode *inode, struct file *filp)
{
	const struct file_operations *new_fops;
	struct drm_minor *minor;
	int err;

	DRM_DEBUG("\n");

	mutex_lock(&drm_global_mutex);
	minor = drm_minor_acquire(iminor(inode));
	if (IS_ERR(minor)) {
		err = PTR_ERR(minor);
		goto out_unlock;
	}

	new_fops = fops_get(minor->dev->driver->fops);
	if (!new_fops) {
		err = -ENODEV;
		goto out_release;
	}

	replace_fops(filp, new_fops);
	if (filp->f_op->open)
		err = filp->f_op->open(inode, filp);
	else
		err = 0;

out_release:
	drm_minor_release(minor);
out_unlock:
	mutex_unlock(&drm_global_mutex);
	return err;
}

static const struct file_operations drm_stub_fops = {
	.owner = THIS_MODULE,
	.open = drm_stub_open,
	.llseek = noop_llseek,
};

static int __init drm_core_init(void)
{
	int ret = -ENOMEM;

	drm_global_init();
	drm_connector_ida_init();
	idr_init(&drm_minors_idr);

	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
		goto err_p1;

	drm_class = drm_sysfs_create(THIS_MODULE, "drm");
	if (IS_ERR(drm_class)) {
		printk(KERN_ERR "DRM: Error creating drm class.\n");
		ret = PTR_ERR(drm_class);
		goto err_p2;
	}

	drm_debugfs_root = debugfs_create_dir("dri", NULL);
	if (!drm_debugfs_root) {
		DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
		ret = -1;
		goto err_p3;
	}

	DRM_INFO("Initialized %s %d.%d.%d %s\n",
		 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
	return 0;
err_p3:
	drm_sysfs_destroy();
err_p2:
	unregister_chrdev(DRM_MAJOR, "drm");

	idr_destroy(&drm_minors_idr);
err_p1:
	return ret;
}

static void __exit drm_core_exit(void)
{
	debugfs_remove(drm_debugfs_root);
	drm_sysfs_destroy();

	unregister_chrdev(DRM_MAJOR, "drm");

	drm_connector_ida_destroy();
	idr_destroy(&drm_minors_idr);
}

module_init(drm_core_init);
module_exit(drm_core_exit);