Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.15-rc3 780 lines 20 kB view raw
1/** 2 * \file drm_stub.h 3 * Stub support 4 * 5 * \author Rickard E. (Rik) Faith <faith@valinux.com> 6 */ 7 8/* 9 * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org 10 * 11 * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California. 12 * All Rights Reserved. 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a 15 * copy of this software and associated documentation files (the "Software"), 16 * to deal in the Software without restriction, including without limitation 17 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 * and/or sell copies of the Software, and to permit persons to whom the 19 * Software is furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice (including the next 22 * paragraph) shall be included in all copies or substantial portions of the 23 * Software. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31 * DEALINGS IN THE SOFTWARE. 32 */ 33 34#include <linux/fs.h> 35#include <linux/module.h> 36#include <linux/moduleparam.h> 37#include <linux/mount.h> 38#include <linux/slab.h> 39#include <drm/drmP.h> 40#include <drm/drm_core.h> 41 42unsigned int drm_debug = 0; /* 1 to enable debug output */ 43EXPORT_SYMBOL(drm_debug); 44 45unsigned int drm_rnodes = 0; /* 1 to enable experimental render nodes API */ 46EXPORT_SYMBOL(drm_rnodes); 47 48/* 1 to allow user space to request universal planes (experimental) */ 49unsigned int drm_universal_planes = 0; 50EXPORT_SYMBOL(drm_universal_planes); 51 52unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ 53EXPORT_SYMBOL(drm_vblank_offdelay); 54 55unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ 56EXPORT_SYMBOL(drm_timestamp_precision); 57 58/* 59 * Default to use monotonic timestamps for wait-for-vblank and page-flip 60 * complete events. 61 */ 62unsigned int drm_timestamp_monotonic = 1; 63 64MODULE_AUTHOR(CORE_AUTHOR); 65MODULE_DESCRIPTION(CORE_DESC); 66MODULE_LICENSE("GPL and additional rights"); 67MODULE_PARM_DESC(debug, "Enable debug output"); 68MODULE_PARM_DESC(rnodes, "Enable experimental render nodes API"); 69MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); 70MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); 71MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); 72 73module_param_named(debug, drm_debug, int, 0600); 74module_param_named(rnodes, drm_rnodes, int, 0600); 75module_param_named(universal_planes, drm_universal_planes, int, 0600); 76module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); 77module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); 78module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); 79 80static DEFINE_SPINLOCK(drm_minor_lock); 81struct idr drm_minors_idr; 82 83struct class *drm_class; 84struct dentry *drm_debugfs_root; 85 86int drm_err(const char *func, const char *format, ...) 87{ 88 struct va_format vaf; 89 va_list args; 90 int r; 91 92 va_start(args, format); 93 94 vaf.fmt = format; 95 vaf.va = &args; 96 97 r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf); 98 99 va_end(args); 100 101 return r; 102} 103EXPORT_SYMBOL(drm_err); 104 105void drm_ut_debug_printk(const char *function_name, const char *format, ...) 106{ 107 struct va_format vaf; 108 va_list args; 109 110 va_start(args, format); 111 vaf.fmt = format; 112 vaf.va = &args; 113 114 printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf); 115 116 va_end(args); 117} 118EXPORT_SYMBOL(drm_ut_debug_printk); 119 120struct drm_master *drm_master_create(struct drm_minor *minor) 121{ 122 struct drm_master *master; 123 124 master = kzalloc(sizeof(*master), GFP_KERNEL); 125 if (!master) 126 return NULL; 127 128 kref_init(&master->refcount); 129 spin_lock_init(&master->lock.spinlock); 130 init_waitqueue_head(&master->lock.lock_queue); 131 drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER); 132 INIT_LIST_HEAD(&master->magicfree); 133 master->minor = minor; 134 135 return master; 136} 137 138struct drm_master *drm_master_get(struct drm_master *master) 139{ 140 kref_get(&master->refcount); 141 return master; 142} 143EXPORT_SYMBOL(drm_master_get); 144 145static void drm_master_destroy(struct kref *kref) 146{ 147 struct drm_master *master = container_of(kref, struct drm_master, refcount); 148 struct drm_magic_entry *pt, *next; 149 struct drm_device *dev = master->minor->dev; 150 struct drm_map_list *r_list, *list_temp; 151 152 mutex_lock(&dev->struct_mutex); 153 if (dev->driver->master_destroy) 154 dev->driver->master_destroy(dev, master); 155 156 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) { 157 if (r_list->master == master) { 158 drm_rmmap_locked(dev, r_list->map); 159 r_list = NULL; 160 } 161 } 162 163 if (master->unique) { 164 kfree(master->unique); 165 master->unique = NULL; 166 master->unique_len = 0; 167 } 168 169 kfree(dev->devname); 170 dev->devname = NULL; 171 172 list_for_each_entry_safe(pt, next, &master->magicfree, head) { 173 list_del(&pt->head); 174 drm_ht_remove_item(&master->magiclist, &pt->hash_item); 175 kfree(pt); 176 } 177 178 drm_ht_remove(&master->magiclist); 179 180 mutex_unlock(&dev->struct_mutex); 181 kfree(master); 182} 183 184void drm_master_put(struct drm_master **master) 185{ 186 kref_put(&(*master)->refcount, drm_master_destroy); 187 *master = NULL; 188} 189EXPORT_SYMBOL(drm_master_put); 190 191int drm_setmaster_ioctl(struct drm_device *dev, void *data, 192 struct drm_file *file_priv) 193{ 194 int ret = 0; 195 196 mutex_lock(&dev->master_mutex); 197 if (file_priv->is_master) 198 goto out_unlock; 199 200 if (file_priv->minor->master) { 201 ret = -EINVAL; 202 goto out_unlock; 203 } 204 205 if (!file_priv->master) { 206 ret = -EINVAL; 207 goto out_unlock; 208 } 209 210 file_priv->minor->master = drm_master_get(file_priv->master); 211 file_priv->is_master = 1; 212 if (dev->driver->master_set) { 213 ret = dev->driver->master_set(dev, file_priv, false); 214 if (unlikely(ret != 0)) { 215 file_priv->is_master = 0; 216 drm_master_put(&file_priv->minor->master); 217 } 218 } 219 220out_unlock: 221 mutex_unlock(&dev->master_mutex); 222 return ret; 223} 224 225int drm_dropmaster_ioctl(struct drm_device *dev, void *data, 226 struct drm_file *file_priv) 227{ 228 int ret = -EINVAL; 229 230 mutex_lock(&dev->master_mutex); 231 if (!file_priv->is_master) 232 goto out_unlock; 233 234 if (!file_priv->minor->master) 235 goto out_unlock; 236 237 ret = 0; 238 if (dev->driver->master_drop) 239 dev->driver->master_drop(dev, file_priv, false); 240 drm_master_put(&file_priv->minor->master); 241 file_priv->is_master = 0; 242 243out_unlock: 244 mutex_unlock(&dev->master_mutex); 245 return ret; 246} 247 248/* 249 * DRM Minors 250 * A DRM device can provide several char-dev interfaces on the DRM-Major. Each 251 * of them is represented by a drm_minor object. Depending on the capabilities 252 * of the device-driver, different interfaces are registered. 253 * 254 * Minors can be accessed via dev->$minor_name. This pointer is either 255 * NULL or a valid drm_minor pointer and stays valid as long as the device is 256 * valid. This means, DRM minors have the same life-time as the underlying 257 * device. However, this doesn't mean that the minor is active. Minors are 258 * registered and unregistered dynamically according to device-state. 259 */ 260 261static struct drm_minor **drm_minor_get_slot(struct drm_device *dev, 262 unsigned int type) 263{ 264 switch (type) { 265 case DRM_MINOR_LEGACY: 266 return &dev->primary; 267 case DRM_MINOR_RENDER: 268 return &dev->render; 269 case DRM_MINOR_CONTROL: 270 return &dev->control; 271 default: 272 return NULL; 273 } 274} 275 276static int drm_minor_alloc(struct drm_device *dev, unsigned int type) 277{ 278 struct drm_minor *minor; 279 280 minor = kzalloc(sizeof(*minor), GFP_KERNEL); 281 if (!minor) 282 return -ENOMEM; 283 284 minor->type = type; 285 minor->dev = dev; 286 287 *drm_minor_get_slot(dev, type) = minor; 288 return 0; 289} 290 291static void drm_minor_free(struct drm_device *dev, unsigned int type) 292{ 293 struct drm_minor **slot; 294 295 slot = drm_minor_get_slot(dev, type); 296 if (*slot) { 297 kfree(*slot); 298 *slot = NULL; 299 } 300} 301 302static int drm_minor_register(struct drm_device *dev, unsigned int type) 303{ 304 struct drm_minor *new_minor; 305 unsigned long flags; 306 int ret; 307 int minor_id; 308 309 DRM_DEBUG("\n"); 310 311 new_minor = *drm_minor_get_slot(dev, type); 312 if (!new_minor) 313 return 0; 314 315 idr_preload(GFP_KERNEL); 316 spin_lock_irqsave(&drm_minor_lock, flags); 317 minor_id = idr_alloc(&drm_minors_idr, 318 NULL, 319 64 * type, 320 64 * (type + 1), 321 GFP_NOWAIT); 322 spin_unlock_irqrestore(&drm_minor_lock, flags); 323 idr_preload_end(); 324 325 if (minor_id < 0) 326 return minor_id; 327 328 new_minor->index = minor_id; 329 330 ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root); 331 if (ret) { 332 DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); 333 goto err_id; 334 } 335 336 ret = drm_sysfs_device_add(new_minor); 337 if (ret) { 338 DRM_ERROR("DRM: Error sysfs_device_add.\n"); 339 goto err_debugfs; 340 } 341 342 /* replace NULL with @minor so lookups will succeed from now on */ 343 spin_lock_irqsave(&drm_minor_lock, flags); 344 idr_replace(&drm_minors_idr, new_minor, new_minor->index); 345 spin_unlock_irqrestore(&drm_minor_lock, flags); 346 347 DRM_DEBUG("new minor assigned %d\n", minor_id); 348 return 0; 349 350err_debugfs: 351 drm_debugfs_cleanup(new_minor); 352err_id: 353 spin_lock_irqsave(&drm_minor_lock, flags); 354 idr_remove(&drm_minors_idr, minor_id); 355 spin_unlock_irqrestore(&drm_minor_lock, flags); 356 new_minor->index = 0; 357 return ret; 358} 359 360static void drm_minor_unregister(struct drm_device *dev, unsigned int type) 361{ 362 struct drm_minor *minor; 363 unsigned long flags; 364 365 minor = *drm_minor_get_slot(dev, type); 366 if (!minor || !minor->kdev) 367 return; 368 369 spin_lock_irqsave(&drm_minor_lock, flags); 370 idr_remove(&drm_minors_idr, minor->index); 371 spin_unlock_irqrestore(&drm_minor_lock, flags); 372 minor->index = 0; 373 374 drm_debugfs_cleanup(minor); 375 drm_sysfs_device_remove(minor); 376} 377 378/** 379 * drm_minor_acquire - Acquire a DRM minor 380 * @minor_id: Minor ID of the DRM-minor 381 * 382 * Looks up the given minor-ID and returns the respective DRM-minor object. The 383 * refence-count of the underlying device is increased so you must release this 384 * object with drm_minor_release(). 385 * 386 * As long as you hold this minor, it is guaranteed that the object and the 387 * minor->dev pointer will stay valid! However, the device may get unplugged and 388 * unregistered while you hold the minor. 389 * 390 * Returns: 391 * Pointer to minor-object with increased device-refcount, or PTR_ERR on 392 * failure. 393 */ 394struct drm_minor *drm_minor_acquire(unsigned int minor_id) 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 if (minor) 402 drm_dev_ref(minor->dev); 403 spin_unlock_irqrestore(&drm_minor_lock, flags); 404 405 if (!minor) { 406 return ERR_PTR(-ENODEV); 407 } else if (drm_device_is_unplugged(minor->dev)) { 408 drm_dev_unref(minor->dev); 409 return ERR_PTR(-ENODEV); 410 } 411 412 return minor; 413} 414 415/** 416 * drm_minor_release - Release DRM minor 417 * @minor: Pointer to DRM minor object 418 * 419 * Release a minor that was previously acquired via drm_minor_acquire(). 420 */ 421void drm_minor_release(struct drm_minor *minor) 422{ 423 drm_dev_unref(minor->dev); 424} 425 426/** 427 * Called via drm_exit() at module unload time or when pci device is 428 * unplugged. 429 * 430 * Cleans up all DRM device, calling drm_lastclose(). 431 * 432 */ 433void drm_put_dev(struct drm_device *dev) 434{ 435 DRM_DEBUG("\n"); 436 437 if (!dev) { 438 DRM_ERROR("cleanup called no dev\n"); 439 return; 440 } 441 442 drm_dev_unregister(dev); 443 drm_dev_unref(dev); 444} 445EXPORT_SYMBOL(drm_put_dev); 446 447void drm_unplug_dev(struct drm_device *dev) 448{ 449 /* for a USB device */ 450 drm_minor_unregister(dev, DRM_MINOR_LEGACY); 451 drm_minor_unregister(dev, DRM_MINOR_RENDER); 452 drm_minor_unregister(dev, DRM_MINOR_CONTROL); 453 454 mutex_lock(&drm_global_mutex); 455 456 drm_device_set_unplugged(dev); 457 458 if (dev->open_count == 0) { 459 drm_put_dev(dev); 460 } 461 mutex_unlock(&drm_global_mutex); 462} 463EXPORT_SYMBOL(drm_unplug_dev); 464 465/* 466 * DRM internal mount 467 * We want to be able to allocate our own "struct address_space" to control 468 * memory-mappings in VRAM (or stolen RAM, ...). However, core MM does not allow 469 * stand-alone address_space objects, so we need an underlying inode. As there 470 * is no way to allocate an independent inode easily, we need a fake internal 471 * VFS mount-point. 472 * 473 * The drm_fs_inode_new() function allocates a new inode, drm_fs_inode_free() 474 * frees it again. You are allowed to use iget() and iput() to get references to 475 * the inode. But each drm_fs_inode_new() call must be paired with exactly one 476 * drm_fs_inode_free() call (which does not have to be the last iput()). 477 * We use drm_fs_inode_*() to manage our internal VFS mount-point and share it 478 * between multiple inode-users. You could, technically, call 479 * iget() + drm_fs_inode_free() directly after alloc and sometime later do an 480 * iput(), but this way you'd end up with a new vfsmount for each inode. 481 */ 482 483static int drm_fs_cnt; 484static struct vfsmount *drm_fs_mnt; 485 486static const struct dentry_operations drm_fs_dops = { 487 .d_dname = simple_dname, 488}; 489 490static const struct super_operations drm_fs_sops = { 491 .statfs = simple_statfs, 492}; 493 494static struct dentry *drm_fs_mount(struct file_system_type *fs_type, int flags, 495 const char *dev_name, void *data) 496{ 497 return mount_pseudo(fs_type, 498 "drm:", 499 &drm_fs_sops, 500 &drm_fs_dops, 501 0x010203ff); 502} 503 504static struct file_system_type drm_fs_type = { 505 .name = "drm", 506 .owner = THIS_MODULE, 507 .mount = drm_fs_mount, 508 .kill_sb = kill_anon_super, 509}; 510 511static struct inode *drm_fs_inode_new(void) 512{ 513 struct inode *inode; 514 int r; 515 516 r = simple_pin_fs(&drm_fs_type, &drm_fs_mnt, &drm_fs_cnt); 517 if (r < 0) { 518 DRM_ERROR("Cannot mount pseudo fs: %d\n", r); 519 return ERR_PTR(r); 520 } 521 522 inode = alloc_anon_inode(drm_fs_mnt->mnt_sb); 523 if (IS_ERR(inode)) 524 simple_release_fs(&drm_fs_mnt, &drm_fs_cnt); 525 526 return inode; 527} 528 529static void drm_fs_inode_free(struct inode *inode) 530{ 531 if (inode) { 532 iput(inode); 533 simple_release_fs(&drm_fs_mnt, &drm_fs_cnt); 534 } 535} 536 537/** 538 * drm_dev_alloc - Allocate new drm device 539 * @driver: DRM driver to allocate device for 540 * @parent: Parent device object 541 * 542 * Allocate and initialize a new DRM device. No device registration is done. 543 * Call drm_dev_register() to advertice the device to user space and register it 544 * with other core subsystems. 545 * 546 * The initial ref-count of the object is 1. Use drm_dev_ref() and 547 * drm_dev_unref() to take and drop further ref-counts. 548 * 549 * RETURNS: 550 * Pointer to new DRM device, or NULL if out of memory. 551 */ 552struct drm_device *drm_dev_alloc(struct drm_driver *driver, 553 struct device *parent) 554{ 555 struct drm_device *dev; 556 int ret; 557 558 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 559 if (!dev) 560 return NULL; 561 562 kref_init(&dev->ref); 563 dev->dev = parent; 564 dev->driver = driver; 565 566 INIT_LIST_HEAD(&dev->filelist); 567 INIT_LIST_HEAD(&dev->ctxlist); 568 INIT_LIST_HEAD(&dev->vmalist); 569 INIT_LIST_HEAD(&dev->maplist); 570 INIT_LIST_HEAD(&dev->vblank_event_list); 571 572 spin_lock_init(&dev->count_lock); 573 spin_lock_init(&dev->event_lock); 574 mutex_init(&dev->struct_mutex); 575 mutex_init(&dev->ctxlist_mutex); 576 mutex_init(&dev->master_mutex); 577 578 dev->anon_inode = drm_fs_inode_new(); 579 if (IS_ERR(dev->anon_inode)) { 580 ret = PTR_ERR(dev->anon_inode); 581 DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret); 582 goto err_free; 583 } 584 585 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 586 ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL); 587 if (ret) 588 goto err_minors; 589 } 590 591 if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { 592 ret = drm_minor_alloc(dev, DRM_MINOR_RENDER); 593 if (ret) 594 goto err_minors; 595 } 596 597 ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY); 598 if (ret) 599 goto err_minors; 600 601 if (drm_ht_create(&dev->map_hash, 12)) 602 goto err_minors; 603 604 ret = drm_ctxbitmap_init(dev); 605 if (ret) { 606 DRM_ERROR("Cannot allocate memory for context bitmap.\n"); 607 goto err_ht; 608 } 609 610 if (driver->driver_features & DRIVER_GEM) { 611 ret = drm_gem_init(dev); 612 if (ret) { 613 DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n"); 614 goto err_ctxbitmap; 615 } 616 } 617 618 return dev; 619 620err_ctxbitmap: 621 drm_ctxbitmap_cleanup(dev); 622err_ht: 623 drm_ht_remove(&dev->map_hash); 624err_minors: 625 drm_minor_free(dev, DRM_MINOR_LEGACY); 626 drm_minor_free(dev, DRM_MINOR_RENDER); 627 drm_minor_free(dev, DRM_MINOR_CONTROL); 628 drm_fs_inode_free(dev->anon_inode); 629err_free: 630 mutex_destroy(&dev->master_mutex); 631 kfree(dev); 632 return NULL; 633} 634EXPORT_SYMBOL(drm_dev_alloc); 635 636static void drm_dev_release(struct kref *ref) 637{ 638 struct drm_device *dev = container_of(ref, struct drm_device, ref); 639 640 if (dev->driver->driver_features & DRIVER_GEM) 641 drm_gem_destroy(dev); 642 643 drm_ctxbitmap_cleanup(dev); 644 drm_ht_remove(&dev->map_hash); 645 drm_fs_inode_free(dev->anon_inode); 646 647 drm_minor_free(dev, DRM_MINOR_LEGACY); 648 drm_minor_free(dev, DRM_MINOR_RENDER); 649 drm_minor_free(dev, DRM_MINOR_CONTROL); 650 651 kfree(dev->devname); 652 653 mutex_destroy(&dev->master_mutex); 654 kfree(dev); 655} 656 657/** 658 * drm_dev_ref - Take reference of a DRM device 659 * @dev: device to take reference of or NULL 660 * 661 * This increases the ref-count of @dev by one. You *must* already own a 662 * reference when calling this. Use drm_dev_unref() to drop this reference 663 * again. 664 * 665 * This function never fails. However, this function does not provide *any* 666 * guarantee whether the device is alive or running. It only provides a 667 * reference to the object and the memory associated with it. 668 */ 669void drm_dev_ref(struct drm_device *dev) 670{ 671 if (dev) 672 kref_get(&dev->ref); 673} 674EXPORT_SYMBOL(drm_dev_ref); 675 676/** 677 * drm_dev_unref - Drop reference of a DRM device 678 * @dev: device to drop reference of or NULL 679 * 680 * This decreases the ref-count of @dev by one. The device is destroyed if the 681 * ref-count drops to zero. 682 */ 683void drm_dev_unref(struct drm_device *dev) 684{ 685 if (dev) 686 kref_put(&dev->ref, drm_dev_release); 687} 688EXPORT_SYMBOL(drm_dev_unref); 689 690/** 691 * drm_dev_register - Register DRM device 692 * @dev: Device to register 693 * 694 * Register the DRM device @dev with the system, advertise device to user-space 695 * and start normal device operation. @dev must be allocated via drm_dev_alloc() 696 * previously. 697 * 698 * Never call this twice on any device! 699 * 700 * RETURNS: 701 * 0 on success, negative error code on failure. 702 */ 703int drm_dev_register(struct drm_device *dev, unsigned long flags) 704{ 705 int ret; 706 707 mutex_lock(&drm_global_mutex); 708 709 ret = drm_minor_register(dev, DRM_MINOR_CONTROL); 710 if (ret) 711 goto err_minors; 712 713 ret = drm_minor_register(dev, DRM_MINOR_RENDER); 714 if (ret) 715 goto err_minors; 716 717 ret = drm_minor_register(dev, DRM_MINOR_LEGACY); 718 if (ret) 719 goto err_minors; 720 721 if (dev->driver->load) { 722 ret = dev->driver->load(dev, flags); 723 if (ret) 724 goto err_minors; 725 } 726 727 /* setup grouping for legacy outputs */ 728 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 729 ret = drm_mode_group_init_legacy_group(dev, 730 &dev->primary->mode_group); 731 if (ret) 732 goto err_unload; 733 } 734 735 ret = 0; 736 goto out_unlock; 737 738err_unload: 739 if (dev->driver->unload) 740 dev->driver->unload(dev); 741err_minors: 742 drm_minor_unregister(dev, DRM_MINOR_LEGACY); 743 drm_minor_unregister(dev, DRM_MINOR_RENDER); 744 drm_minor_unregister(dev, DRM_MINOR_CONTROL); 745out_unlock: 746 mutex_unlock(&drm_global_mutex); 747 return ret; 748} 749EXPORT_SYMBOL(drm_dev_register); 750 751/** 752 * drm_dev_unregister - Unregister DRM device 753 * @dev: Device to unregister 754 * 755 * Unregister the DRM device from the system. This does the reverse of 756 * drm_dev_register() but does not deallocate the device. The caller must call 757 * drm_dev_unref() to drop their final reference. 758 */ 759void drm_dev_unregister(struct drm_device *dev) 760{ 761 struct drm_map_list *r_list, *list_temp; 762 763 drm_lastclose(dev); 764 765 if (dev->driver->unload) 766 dev->driver->unload(dev); 767 768 if (dev->agp) 769 drm_pci_agp_destroy(dev); 770 771 drm_vblank_cleanup(dev); 772 773 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) 774 drm_rmmap(dev, r_list->map); 775 776 drm_minor_unregister(dev, DRM_MINOR_LEGACY); 777 drm_minor_unregister(dev, DRM_MINOR_RENDER); 778 drm_minor_unregister(dev, DRM_MINOR_CONTROL); 779} 780EXPORT_SYMBOL(drm_dev_unregister);