linux/drivers/gpu/drm/drm_stub.c
<<
>>
Prefs
   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 "drmP.h"
  37#include "drm_core.h"
  38
  39unsigned int drm_debug = 0;     /* 1 to enable debug output */
  40EXPORT_SYMBOL(drm_debug);
  41
  42MODULE_AUTHOR(CORE_AUTHOR);
  43MODULE_DESCRIPTION(CORE_DESC);
  44MODULE_LICENSE("GPL and additional rights");
  45MODULE_PARM_DESC(debug, "Enable debug output");
  46
  47module_param_named(debug, drm_debug, int, 0600);
  48
  49struct idr drm_minors_idr;
  50
  51struct class *drm_class;
  52struct proc_dir_entry *drm_proc_root;
  53struct dentry *drm_debugfs_root;
  54void drm_ut_debug_printk(unsigned int request_level,
  55                         const char *prefix,
  56                         const char *function_name,
  57                         const char *format, ...)
  58{
  59        va_list args;
  60
  61        if (drm_debug & request_level) {
  62                if (function_name)
  63                        printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
  64                va_start(args, format);
  65                vprintk(format, args);
  66                va_end(args);
  67        }
  68}
  69EXPORT_SYMBOL(drm_ut_debug_printk);
  70static int drm_minor_get_id(struct drm_device *dev, int type)
  71{
  72        int new_id;
  73        int ret;
  74        int base = 0, limit = 63;
  75
  76        if (type == DRM_MINOR_CONTROL) {
  77                base += 64;
  78                limit = base + 127;
  79        } else if (type == DRM_MINOR_RENDER) {
  80                base += 128;
  81                limit = base + 255;
  82        }
  83
  84again:
  85        if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
  86                DRM_ERROR("Out of memory expanding drawable idr\n");
  87                return -ENOMEM;
  88        }
  89        mutex_lock(&dev->struct_mutex);
  90        ret = idr_get_new_above(&drm_minors_idr, NULL,
  91                                base, &new_id);
  92        mutex_unlock(&dev->struct_mutex);
  93        if (ret == -EAGAIN) {
  94                goto again;
  95        } else if (ret) {
  96                return ret;
  97        }
  98
  99        if (new_id >= limit) {
 100                idr_remove(&drm_minors_idr, new_id);
 101                return -EINVAL;
 102        }
 103        return new_id;
 104}
 105
 106struct drm_master *drm_master_create(struct drm_minor *minor)
 107{
 108        struct drm_master *master;
 109
 110        master = kzalloc(sizeof(*master), GFP_KERNEL);
 111        if (!master)
 112                return NULL;
 113
 114        kref_init(&master->refcount);
 115        spin_lock_init(&master->lock.spinlock);
 116        init_waitqueue_head(&master->lock.lock_queue);
 117        drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
 118        INIT_LIST_HEAD(&master->magicfree);
 119        master->minor = minor;
 120
 121        list_add_tail(&master->head, &minor->master_list);
 122
 123        return master;
 124}
 125
 126struct drm_master *drm_master_get(struct drm_master *master)
 127{
 128        kref_get(&master->refcount);
 129        return master;
 130}
 131
 132static void drm_master_destroy(struct kref *kref)
 133{
 134        struct drm_master *master = container_of(kref, struct drm_master, refcount);
 135        struct drm_magic_entry *pt, *next;
 136        struct drm_device *dev = master->minor->dev;
 137        struct drm_map_list *r_list, *list_temp;
 138
 139        list_del(&master->head);
 140
 141        if (dev->driver->master_destroy)
 142                dev->driver->master_destroy(dev, master);
 143
 144        list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
 145                if (r_list->master == master) {
 146                        drm_rmmap_locked(dev, r_list->map);
 147                        r_list = NULL;
 148                }
 149        }
 150
 151        if (master->unique) {
 152                kfree(master->unique);
 153                master->unique = NULL;
 154                master->unique_len = 0;
 155        }
 156
 157        list_for_each_entry_safe(pt, next, &master->magicfree, head) {
 158                list_del(&pt->head);
 159                drm_ht_remove_item(&master->magiclist, &pt->hash_item);
 160                kfree(pt);
 161        }
 162
 163        drm_ht_remove(&master->magiclist);
 164
 165        kfree(master);
 166}
 167
 168void drm_master_put(struct drm_master **master)
 169{
 170        kref_put(&(*master)->refcount, drm_master_destroy);
 171        *master = NULL;
 172}
 173
 174int drm_setmaster_ioctl(struct drm_device *dev, void *data,
 175                        struct drm_file *file_priv)
 176{
 177        if (file_priv->is_master)
 178                return 0;
 179
 180        if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
 181                return -EINVAL;
 182
 183        if (!file_priv->master)
 184                return -EINVAL;
 185
 186        if (!file_priv->minor->master &&
 187            file_priv->minor->master != file_priv->master) {
 188                mutex_lock(&dev->struct_mutex);
 189                file_priv->minor->master = drm_master_get(file_priv->master);
 190                file_priv->is_master = 1;
 191                mutex_unlock(&dev->struct_mutex);
 192        }
 193
 194        return 0;
 195}
 196
 197int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
 198                         struct drm_file *file_priv)
 199{
 200        if (!file_priv->is_master)
 201                return -EINVAL;
 202
 203        if (!file_priv->minor->master)
 204                return -EINVAL;
 205
 206        mutex_lock(&dev->struct_mutex);
 207        drm_master_put(&file_priv->minor->master);
 208        file_priv->is_master = 0;
 209        mutex_unlock(&dev->struct_mutex);
 210        return 0;
 211}
 212
 213static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
 214                           const struct pci_device_id *ent,
 215                           struct drm_driver *driver)
 216{
 217        int retcode;
 218
 219        INIT_LIST_HEAD(&dev->filelist);
 220        INIT_LIST_HEAD(&dev->ctxlist);
 221        INIT_LIST_HEAD(&dev->vmalist);
 222        INIT_LIST_HEAD(&dev->maplist);
 223
 224        spin_lock_init(&dev->count_lock);
 225        spin_lock_init(&dev->drw_lock);
 226        init_timer(&dev->timer);
 227        mutex_init(&dev->struct_mutex);
 228        mutex_init(&dev->ctxlist_mutex);
 229
 230        idr_init(&dev->drw_idr);
 231
 232        dev->pdev = pdev;
 233        dev->pci_device = pdev->device;
 234        dev->pci_vendor = pdev->vendor;
 235
 236#ifdef __alpha__
 237        dev->hose = pdev->sysdata;
 238#endif
 239
 240        if (drm_ht_create(&dev->map_hash, 12)) {
 241                return -ENOMEM;
 242        }
 243
 244        /* the DRM has 6 basic counters */
 245        dev->counters = 6;
 246        dev->types[0] = _DRM_STAT_LOCK;
 247        dev->types[1] = _DRM_STAT_OPENS;
 248        dev->types[2] = _DRM_STAT_CLOSES;
 249        dev->types[3] = _DRM_STAT_IOCTLS;
 250        dev->types[4] = _DRM_STAT_LOCKS;
 251        dev->types[5] = _DRM_STAT_UNLOCKS;
 252
 253        dev->driver = driver;
 254
 255        if (drm_core_has_AGP(dev)) {
 256                if (drm_device_is_agp(dev))
 257                        dev->agp = drm_agp_init(dev);
 258                if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
 259                    && (dev->agp == NULL)) {
 260                        DRM_ERROR("Cannot initialize the agpgart module.\n");
 261                        retcode = -EINVAL;
 262                        goto error_out_unreg;
 263                }
 264                if (drm_core_has_MTRR(dev)) {
 265                        if (dev->agp)
 266                                dev->agp->agp_mtrr =
 267                                    mtrr_add(dev->agp->agp_info.aper_base,
 268                                             dev->agp->agp_info.aper_size *
 269                                             1024 * 1024, MTRR_TYPE_WRCOMB, 1);
 270                }
 271        }
 272
 273
 274        retcode = drm_ctxbitmap_init(dev);
 275        if (retcode) {
 276                DRM_ERROR("Cannot allocate memory for context bitmap.\n");
 277                goto error_out_unreg;
 278        }
 279
 280        if (driver->driver_features & DRIVER_GEM) {
 281                retcode = drm_gem_init(dev);
 282                if (retcode) {
 283                        DRM_ERROR("Cannot initialize graphics execution "
 284                                  "manager (GEM)\n");
 285                        goto error_out_unreg;
 286                }
 287        }
 288
 289        return 0;
 290
 291      error_out_unreg:
 292        drm_lastclose(dev);
 293        return retcode;
 294}
 295
 296
 297/**
 298 * Get a secondary minor number.
 299 *
 300 * \param dev device data structure
 301 * \param sec-minor structure to hold the assigned minor
 302 * \return negative number on failure.
 303 *
 304 * Search an empty entry and initialize it to the given parameters, and
 305 * create the proc init entry via proc_init(). This routines assigns
 306 * minor numbers to secondary heads of multi-headed cards
 307 */
 308static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
 309{
 310        struct drm_minor *new_minor;
 311        int ret;
 312        int minor_id;
 313
 314        DRM_DEBUG("\n");
 315
 316        minor_id = drm_minor_get_id(dev, type);
 317        if (minor_id < 0)
 318                return minor_id;
 319
 320        new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
 321        if (!new_minor) {
 322                ret = -ENOMEM;
 323                goto err_idr;
 324        }
 325
 326        new_minor->type = type;
 327        new_minor->device = MKDEV(DRM_MAJOR, minor_id);
 328        new_minor->dev = dev;
 329        new_minor->index = minor_id;
 330        INIT_LIST_HEAD(&new_minor->master_list);
 331
 332        idr_replace(&drm_minors_idr, new_minor, minor_id);
 333
 334        if (type == DRM_MINOR_LEGACY) {
 335                ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
 336                if (ret) {
 337                        DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
 338                        goto err_mem;
 339                }
 340        } else
 341                new_minor->proc_root = NULL;
 342
 343#if defined(CONFIG_DEBUG_FS)
 344        ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
 345        if (ret) {
 346                DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
 347                goto err_g2;
 348        }
 349#endif
 350
 351        ret = drm_sysfs_device_add(new_minor);
 352        if (ret) {
 353                printk(KERN_ERR
 354                       "DRM: Error sysfs_device_add.\n");
 355                goto err_g2;
 356        }
 357        *minor = new_minor;
 358
 359        DRM_DEBUG("new minor assigned %d\n", minor_id);
 360        return 0;
 361
 362
 363err_g2:
 364        if (new_minor->type == DRM_MINOR_LEGACY)
 365                drm_proc_cleanup(new_minor, drm_proc_root);
 366err_mem:
 367        kfree(new_minor);
 368err_idr:
 369        idr_remove(&drm_minors_idr, minor_id);
 370        *minor = NULL;
 371        return ret;
 372}
 373
 374/**
 375 * Register.
 376 *
 377 * \param pdev - PCI device structure
 378 * \param ent entry from the PCI ID table with device type flags
 379 * \return zero on success or a negative number on failure.
 380 *
 381 * Attempt to gets inter module "drm" information. If we are first
 382 * then register the character device and inter module information.
 383 * Try and register, if we fail to register, backout previous work.
 384 */
 385int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
 386                struct drm_driver *driver)
 387{
 388        struct drm_device *dev;
 389        int ret;
 390
 391        DRM_DEBUG("\n");
 392
 393        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 394        if (!dev)
 395                return -ENOMEM;
 396
 397        ret = pci_enable_device(pdev);
 398        if (ret)
 399                goto err_g1;
 400
 401        pci_set_master(pdev);
 402        if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
 403                printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
 404                goto err_g2;
 405        }
 406
 407        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 408                pci_set_drvdata(pdev, dev);
 409                ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
 410                if (ret)
 411                        goto err_g2;
 412        }
 413
 414        if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
 415                goto err_g3;
 416
 417        if (dev->driver->load) {
 418                ret = dev->driver->load(dev, ent->driver_data);
 419                if (ret)
 420                        goto err_g4;
 421        }
 422
 423        /* setup the grouping for the legacy output */
 424        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 425                ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
 426                if (ret)
 427                        goto err_g4;
 428        }
 429
 430        list_add_tail(&dev->driver_item, &driver->device_list);
 431
 432        DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
 433                 driver->name, driver->major, driver->minor, driver->patchlevel,
 434                 driver->date, pci_name(pdev), dev->primary->index);
 435
 436        return 0;
 437
 438err_g4:
 439        drm_put_minor(&dev->primary);
 440err_g3:
 441        if (drm_core_check_feature(dev, DRIVER_MODESET))
 442                drm_put_minor(&dev->control);
 443err_g2:
 444        pci_disable_device(pdev);
 445err_g1:
 446        kfree(dev);
 447        return ret;
 448}
 449EXPORT_SYMBOL(drm_get_dev);
 450
 451/**
 452 * Put a secondary minor number.
 453 *
 454 * \param sec_minor - structure to be released
 455 * \return always zero
 456 *
 457 * Cleans up the proc resources. Not legal for this to be the
 458 * last minor released.
 459 *
 460 */
 461int drm_put_minor(struct drm_minor **minor_p)
 462{
 463        struct drm_minor *minor = *minor_p;
 464
 465        DRM_DEBUG("release secondary minor %d\n", minor->index);
 466
 467        if (minor->type == DRM_MINOR_LEGACY)
 468                drm_proc_cleanup(minor, drm_proc_root);
 469#if defined(CONFIG_DEBUG_FS)
 470        drm_debugfs_cleanup(minor);
 471#endif
 472
 473        drm_sysfs_device_remove(minor);
 474
 475        idr_remove(&drm_minors_idr, minor->index);
 476
 477        kfree(minor);
 478        *minor_p = NULL;
 479        return 0;
 480}
 481
 482/**
 483 * Called via drm_exit() at module unload time or when pci device is
 484 * unplugged.
 485 *
 486 * Cleans up all DRM device, calling drm_lastclose().
 487 *
 488 * \sa drm_init
 489 */
 490void drm_put_dev(struct drm_device *dev)
 491{
 492        struct drm_driver *driver;
 493        struct drm_map_list *r_list, *list_temp;
 494
 495        DRM_DEBUG("\n");
 496
 497        if (!dev) {
 498                DRM_ERROR("cleanup called no dev\n");
 499                return;
 500        }
 501        driver = dev->driver;
 502
 503        drm_vblank_cleanup(dev);
 504
 505        drm_lastclose(dev);
 506
 507        if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
 508            dev->agp && dev->agp->agp_mtrr >= 0) {
 509                int retval;
 510                retval = mtrr_del(dev->agp->agp_mtrr,
 511                                  dev->agp->agp_info.aper_base,
 512                                  dev->agp->agp_info.aper_size * 1024 * 1024);
 513                DRM_DEBUG("mtrr_del=%d\n", retval);
 514        }
 515
 516        if (dev->driver->unload)
 517                dev->driver->unload(dev);
 518
 519        if (drm_core_has_AGP(dev) && dev->agp) {
 520                kfree(dev->agp);
 521                dev->agp = NULL;
 522        }
 523
 524        list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
 525                drm_rmmap(dev, r_list->map);
 526        drm_ht_remove(&dev->map_hash);
 527
 528        drm_ctxbitmap_cleanup(dev);
 529
 530        if (drm_core_check_feature(dev, DRIVER_MODESET))
 531                drm_put_minor(&dev->control);
 532
 533        if (driver->driver_features & DRIVER_GEM)
 534                drm_gem_destroy(dev);
 535
 536        drm_put_minor(&dev->primary);
 537
 538        if (dev->devname) {
 539                kfree(dev->devname);
 540                dev->devname = NULL;
 541        }
 542        kfree(dev);
 543}
 544EXPORT_SYMBOL(drm_put_dev);
 545