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.14-rc4 607 lines 15 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/module.h> 35#include <linux/moduleparam.h> 36#include <linux/slab.h> 37#include <drm/drmP.h> 38#include <drm/drm_core.h> 39 40unsigned int drm_debug = 0; /* 1 to enable debug output */ 41EXPORT_SYMBOL(drm_debug); 42 43unsigned int drm_rnodes = 0; /* 1 to enable experimental render nodes API */ 44EXPORT_SYMBOL(drm_rnodes); 45 46unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ 47EXPORT_SYMBOL(drm_vblank_offdelay); 48 49unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ 50EXPORT_SYMBOL(drm_timestamp_precision); 51 52/* 53 * Default to use monotonic timestamps for wait-for-vblank and page-flip 54 * complete events. 55 */ 56unsigned int drm_timestamp_monotonic = 1; 57 58MODULE_AUTHOR(CORE_AUTHOR); 59MODULE_DESCRIPTION(CORE_DESC); 60MODULE_LICENSE("GPL and additional rights"); 61MODULE_PARM_DESC(debug, "Enable debug output"); 62MODULE_PARM_DESC(rnodes, "Enable experimental render nodes API"); 63MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); 64MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); 65MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); 66 67module_param_named(debug, drm_debug, int, 0600); 68module_param_named(rnodes, drm_rnodes, int, 0600); 69module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); 70module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); 71module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); 72 73struct idr drm_minors_idr; 74 75struct class *drm_class; 76struct dentry *drm_debugfs_root; 77 78int drm_err(const char *func, const char *format, ...) 79{ 80 struct va_format vaf; 81 va_list args; 82 int r; 83 84 va_start(args, format); 85 86 vaf.fmt = format; 87 vaf.va = &args; 88 89 r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf); 90 91 va_end(args); 92 93 return r; 94} 95EXPORT_SYMBOL(drm_err); 96 97void drm_ut_debug_printk(unsigned int request_level, 98 const char *prefix, 99 const char *function_name, 100 const char *format, ...) 101{ 102 struct va_format vaf; 103 va_list args; 104 105 if (drm_debug & request_level) { 106 va_start(args, format); 107 vaf.fmt = format; 108 vaf.va = &args; 109 110 if (function_name) 111 printk(KERN_DEBUG "[%s:%s], %pV", prefix, 112 function_name, &vaf); 113 else 114 printk(KERN_DEBUG "%pV", &vaf); 115 va_end(args); 116 } 117} 118EXPORT_SYMBOL(drm_ut_debug_printk); 119 120static int drm_minor_get_id(struct drm_device *dev, int type) 121{ 122 int ret; 123 int base = 0, limit = 63; 124 125 if (type == DRM_MINOR_CONTROL) { 126 base += 64; 127 limit = base + 63; 128 } else if (type == DRM_MINOR_RENDER) { 129 base += 128; 130 limit = base + 63; 131 } 132 133 mutex_lock(&dev->struct_mutex); 134 ret = idr_alloc(&drm_minors_idr, NULL, base, limit, GFP_KERNEL); 135 mutex_unlock(&dev->struct_mutex); 136 137 return ret == -ENOSPC ? -EINVAL : ret; 138} 139 140struct drm_master *drm_master_create(struct drm_minor *minor) 141{ 142 struct drm_master *master; 143 144 master = kzalloc(sizeof(*master), GFP_KERNEL); 145 if (!master) 146 return NULL; 147 148 kref_init(&master->refcount); 149 spin_lock_init(&master->lock.spinlock); 150 init_waitqueue_head(&master->lock.lock_queue); 151 drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER); 152 INIT_LIST_HEAD(&master->magicfree); 153 master->minor = minor; 154 155 list_add_tail(&master->head, &minor->master_list); 156 157 return master; 158} 159 160struct drm_master *drm_master_get(struct drm_master *master) 161{ 162 kref_get(&master->refcount); 163 return master; 164} 165EXPORT_SYMBOL(drm_master_get); 166 167static void drm_master_destroy(struct kref *kref) 168{ 169 struct drm_master *master = container_of(kref, struct drm_master, refcount); 170 struct drm_magic_entry *pt, *next; 171 struct drm_device *dev = master->minor->dev; 172 struct drm_map_list *r_list, *list_temp; 173 174 list_del(&master->head); 175 176 if (dev->driver->master_destroy) 177 dev->driver->master_destroy(dev, master); 178 179 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) { 180 if (r_list->master == master) { 181 drm_rmmap_locked(dev, r_list->map); 182 r_list = NULL; 183 } 184 } 185 186 if (master->unique) { 187 kfree(master->unique); 188 master->unique = NULL; 189 master->unique_len = 0; 190 } 191 192 kfree(dev->devname); 193 dev->devname = NULL; 194 195 list_for_each_entry_safe(pt, next, &master->magicfree, head) { 196 list_del(&pt->head); 197 drm_ht_remove_item(&master->magiclist, &pt->hash_item); 198 kfree(pt); 199 } 200 201 drm_ht_remove(&master->magiclist); 202 203 kfree(master); 204} 205 206void drm_master_put(struct drm_master **master) 207{ 208 kref_put(&(*master)->refcount, drm_master_destroy); 209 *master = NULL; 210} 211EXPORT_SYMBOL(drm_master_put); 212 213int drm_setmaster_ioctl(struct drm_device *dev, void *data, 214 struct drm_file *file_priv) 215{ 216 int ret = 0; 217 218 if (file_priv->is_master) 219 return 0; 220 221 if (file_priv->minor->master && file_priv->minor->master != file_priv->master) 222 return -EINVAL; 223 224 if (!file_priv->master) 225 return -EINVAL; 226 227 if (file_priv->minor->master) 228 return -EINVAL; 229 230 mutex_lock(&dev->struct_mutex); 231 file_priv->minor->master = drm_master_get(file_priv->master); 232 file_priv->is_master = 1; 233 if (dev->driver->master_set) { 234 ret = dev->driver->master_set(dev, file_priv, false); 235 if (unlikely(ret != 0)) { 236 file_priv->is_master = 0; 237 drm_master_put(&file_priv->minor->master); 238 } 239 } 240 mutex_unlock(&dev->struct_mutex); 241 242 return ret; 243} 244 245int drm_dropmaster_ioctl(struct drm_device *dev, void *data, 246 struct drm_file *file_priv) 247{ 248 if (!file_priv->is_master) 249 return -EINVAL; 250 251 if (!file_priv->minor->master) 252 return -EINVAL; 253 254 mutex_lock(&dev->struct_mutex); 255 if (dev->driver->master_drop) 256 dev->driver->master_drop(dev, file_priv, false); 257 drm_master_put(&file_priv->minor->master); 258 file_priv->is_master = 0; 259 mutex_unlock(&dev->struct_mutex); 260 return 0; 261} 262 263/** 264 * drm_get_minor - Allocate and register new DRM minor 265 * @dev: DRM device 266 * @minor: Pointer to where new minor is stored 267 * @type: Type of minor 268 * 269 * Allocate a new minor of the given type and register it. A pointer to the new 270 * minor is returned in @minor. 271 * Caller must hold the global DRM mutex. 272 * 273 * RETURNS: 274 * 0 on success, negative error code on failure. 275 */ 276static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, 277 int type) 278{ 279 struct drm_minor *new_minor; 280 int ret; 281 int minor_id; 282 283 DRM_DEBUG("\n"); 284 285 minor_id = drm_minor_get_id(dev, type); 286 if (minor_id < 0) 287 return minor_id; 288 289 new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL); 290 if (!new_minor) { 291 ret = -ENOMEM; 292 goto err_idr; 293 } 294 295 new_minor->type = type; 296 new_minor->device = MKDEV(DRM_MAJOR, minor_id); 297 new_minor->dev = dev; 298 new_minor->index = minor_id; 299 INIT_LIST_HEAD(&new_minor->master_list); 300 301 idr_replace(&drm_minors_idr, new_minor, minor_id); 302 303#if defined(CONFIG_DEBUG_FS) 304 ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root); 305 if (ret) { 306 DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); 307 goto err_mem; 308 } 309#endif 310 311 ret = drm_sysfs_device_add(new_minor); 312 if (ret) { 313 printk(KERN_ERR 314 "DRM: Error sysfs_device_add.\n"); 315 goto err_debugfs; 316 } 317 *minor = new_minor; 318 319 DRM_DEBUG("new minor assigned %d\n", minor_id); 320 return 0; 321 322 323err_debugfs: 324#if defined(CONFIG_DEBUG_FS) 325 drm_debugfs_cleanup(new_minor); 326err_mem: 327#endif 328 kfree(new_minor); 329err_idr: 330 idr_remove(&drm_minors_idr, minor_id); 331 *minor = NULL; 332 return ret; 333} 334 335/** 336 * drm_unplug_minor - Unplug DRM minor 337 * @minor: Minor to unplug 338 * 339 * Unplugs the given DRM minor but keeps the object. So after this returns, 340 * minor->dev is still valid so existing open-files can still access it to get 341 * device information from their drm_file ojects. 342 * If the minor is already unplugged or if @minor is NULL, nothing is done. 343 * The global DRM mutex must be held by the caller. 344 */ 345static void drm_unplug_minor(struct drm_minor *minor) 346{ 347 if (!minor || !minor->kdev) 348 return; 349 350#if defined(CONFIG_DEBUG_FS) 351 drm_debugfs_cleanup(minor); 352#endif 353 354 drm_sysfs_device_remove(minor); 355 idr_remove(&drm_minors_idr, minor->index); 356} 357 358/** 359 * drm_put_minor - Destroy DRM minor 360 * @minor: Minor to destroy 361 * 362 * This calls drm_unplug_minor() on the given minor and then frees it. Nothing 363 * is done if @minor is NULL. It is fine to call this on already unplugged 364 * minors. 365 * The global DRM mutex must be held by the caller. 366 */ 367static void drm_put_minor(struct drm_minor *minor) 368{ 369 if (!minor) 370 return; 371 372 DRM_DEBUG("release secondary minor %d\n", minor->index); 373 374 drm_unplug_minor(minor); 375 kfree(minor); 376} 377 378/** 379 * Called via drm_exit() at module unload time or when pci device is 380 * unplugged. 381 * 382 * Cleans up all DRM device, calling drm_lastclose(). 383 * 384 */ 385void drm_put_dev(struct drm_device *dev) 386{ 387 DRM_DEBUG("\n"); 388 389 if (!dev) { 390 DRM_ERROR("cleanup called no dev\n"); 391 return; 392 } 393 394 drm_dev_unregister(dev); 395 drm_dev_free(dev); 396} 397EXPORT_SYMBOL(drm_put_dev); 398 399void drm_unplug_dev(struct drm_device *dev) 400{ 401 /* for a USB device */ 402 if (drm_core_check_feature(dev, DRIVER_MODESET)) 403 drm_unplug_minor(dev->control); 404 if (dev->render) 405 drm_unplug_minor(dev->render); 406 drm_unplug_minor(dev->primary); 407 408 mutex_lock(&drm_global_mutex); 409 410 drm_device_set_unplugged(dev); 411 412 if (dev->open_count == 0) { 413 drm_put_dev(dev); 414 } 415 mutex_unlock(&drm_global_mutex); 416} 417EXPORT_SYMBOL(drm_unplug_dev); 418 419/** 420 * drm_dev_alloc - Allocate new drm device 421 * @driver: DRM driver to allocate device for 422 * @parent: Parent device object 423 * 424 * Allocate and initialize a new DRM device. No device registration is done. 425 * Call drm_dev_register() to advertice the device to user space and register it 426 * with other core subsystems. 427 * 428 * RETURNS: 429 * Pointer to new DRM device, or NULL if out of memory. 430 */ 431struct drm_device *drm_dev_alloc(struct drm_driver *driver, 432 struct device *parent) 433{ 434 struct drm_device *dev; 435 int ret; 436 437 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 438 if (!dev) 439 return NULL; 440 441 dev->dev = parent; 442 dev->driver = driver; 443 444 INIT_LIST_HEAD(&dev->filelist); 445 INIT_LIST_HEAD(&dev->ctxlist); 446 INIT_LIST_HEAD(&dev->vmalist); 447 INIT_LIST_HEAD(&dev->maplist); 448 INIT_LIST_HEAD(&dev->vblank_event_list); 449 450 spin_lock_init(&dev->count_lock); 451 spin_lock_init(&dev->event_lock); 452 mutex_init(&dev->struct_mutex); 453 mutex_init(&dev->ctxlist_mutex); 454 455 if (drm_ht_create(&dev->map_hash, 12)) 456 goto err_free; 457 458 ret = drm_ctxbitmap_init(dev); 459 if (ret) { 460 DRM_ERROR("Cannot allocate memory for context bitmap.\n"); 461 goto err_ht; 462 } 463 464 if (driver->driver_features & DRIVER_GEM) { 465 ret = drm_gem_init(dev); 466 if (ret) { 467 DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n"); 468 goto err_ctxbitmap; 469 } 470 } 471 472 return dev; 473 474err_ctxbitmap: 475 drm_ctxbitmap_cleanup(dev); 476err_ht: 477 drm_ht_remove(&dev->map_hash); 478err_free: 479 kfree(dev); 480 return NULL; 481} 482EXPORT_SYMBOL(drm_dev_alloc); 483 484/** 485 * drm_dev_free - Free DRM device 486 * @dev: DRM device to free 487 * 488 * Free a DRM device that has previously been allocated via drm_dev_alloc(). 489 * You must not use kfree() instead or you will leak memory. 490 * 491 * This must not be called once the device got registered. Use drm_put_dev() 492 * instead, which then calls drm_dev_free(). 493 */ 494void drm_dev_free(struct drm_device *dev) 495{ 496 drm_put_minor(dev->control); 497 drm_put_minor(dev->render); 498 drm_put_minor(dev->primary); 499 500 if (dev->driver->driver_features & DRIVER_GEM) 501 drm_gem_destroy(dev); 502 503 drm_ctxbitmap_cleanup(dev); 504 drm_ht_remove(&dev->map_hash); 505 506 kfree(dev->devname); 507 kfree(dev); 508} 509EXPORT_SYMBOL(drm_dev_free); 510 511/** 512 * drm_dev_register - Register DRM device 513 * @dev: Device to register 514 * 515 * Register the DRM device @dev with the system, advertise device to user-space 516 * and start normal device operation. @dev must be allocated via drm_dev_alloc() 517 * previously. 518 * 519 * Never call this twice on any device! 520 * 521 * RETURNS: 522 * 0 on success, negative error code on failure. 523 */ 524int drm_dev_register(struct drm_device *dev, unsigned long flags) 525{ 526 int ret; 527 528 mutex_lock(&drm_global_mutex); 529 530 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 531 ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); 532 if (ret) 533 goto out_unlock; 534 } 535 536 if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { 537 ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER); 538 if (ret) 539 goto err_control_node; 540 } 541 542 ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY); 543 if (ret) 544 goto err_render_node; 545 546 if (dev->driver->load) { 547 ret = dev->driver->load(dev, flags); 548 if (ret) 549 goto err_primary_node; 550 } 551 552 /* setup grouping for legacy outputs */ 553 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 554 ret = drm_mode_group_init_legacy_group(dev, 555 &dev->primary->mode_group); 556 if (ret) 557 goto err_unload; 558 } 559 560 ret = 0; 561 goto out_unlock; 562 563err_unload: 564 if (dev->driver->unload) 565 dev->driver->unload(dev); 566err_primary_node: 567 drm_unplug_minor(dev->primary); 568err_render_node: 569 drm_unplug_minor(dev->render); 570err_control_node: 571 drm_unplug_minor(dev->control); 572out_unlock: 573 mutex_unlock(&drm_global_mutex); 574 return ret; 575} 576EXPORT_SYMBOL(drm_dev_register); 577 578/** 579 * drm_dev_unregister - Unregister DRM device 580 * @dev: Device to unregister 581 * 582 * Unregister the DRM device from the system. This does the reverse of 583 * drm_dev_register() but does not deallocate the device. The caller must call 584 * drm_dev_free() to free all resources. 585 */ 586void drm_dev_unregister(struct drm_device *dev) 587{ 588 struct drm_map_list *r_list, *list_temp; 589 590 drm_lastclose(dev); 591 592 if (dev->driver->unload) 593 dev->driver->unload(dev); 594 595 if (dev->agp) 596 drm_pci_agp_destroy(dev); 597 598 drm_vblank_cleanup(dev); 599 600 list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) 601 drm_rmmap(dev, r_list->map); 602 603 drm_unplug_minor(dev->control); 604 drm_unplug_minor(dev->render); 605 drm_unplug_minor(dev->primary); 606} 607EXPORT_SYMBOL(drm_dev_unregister);