drm/i915: Only print "nothing to do" debug message as required.
[safe/jmp/linux-2.6] / drivers / gpu / drm / drm_stub.c
index 82f4657..a0c365f 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/slab.h>
 #include "drmP.h"
 #include "drm_core.h"
 
@@ -50,13 +51,37 @@ struct idr drm_minors_idr;
 
 struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
-
+struct dentry *drm_debugfs_root;
+void drm_ut_debug_printk(unsigned int request_level,
+                        const char *prefix,
+                        const char *function_name,
+                        const char *format, ...)
+{
+       va_list args;
+
+       if (drm_debug & request_level) {
+               if (function_name)
+                       printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
+               va_start(args, format);
+               vprintk(format, args);
+               va_end(args);
+       }
+}
+EXPORT_SYMBOL(drm_ut_debug_printk);
 static int drm_minor_get_id(struct drm_device *dev, int type)
 {
        int new_id;
        int ret;
        int base = 0, limit = 63;
 
+       if (type == DRM_MINOR_CONTROL) {
+                base += 64;
+                limit = base + 127;
+        } else if (type == DRM_MINOR_RENDER) {
+                base += 128;
+                limit = base + 255;
+        }
+
 again:
        if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
                DRM_ERROR("Out of memory expanding drawable idr\n");
@@ -79,6 +104,126 @@ again:
        return new_id;
 }
 
+struct drm_master *drm_master_create(struct drm_minor *minor)
+{
+       struct drm_master *master;
+
+       master = kzalloc(sizeof(*master), GFP_KERNEL);
+       if (!master)
+               return NULL;
+
+       kref_init(&master->refcount);
+       spin_lock_init(&master->lock.spinlock);
+       init_waitqueue_head(&master->lock.lock_queue);
+       drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
+       INIT_LIST_HEAD(&master->magicfree);
+       master->minor = minor;
+
+       list_add_tail(&master->head, &minor->master_list);
+
+       return master;
+}
+
+struct drm_master *drm_master_get(struct drm_master *master)
+{
+       kref_get(&master->refcount);
+       return master;
+}
+EXPORT_SYMBOL(drm_master_get);
+
+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;
+       struct drm_map_list *r_list, *list_temp;
+
+       list_del(&master->head);
+
+       if (dev->driver->master_destroy)
+               dev->driver->master_destroy(dev, master);
+
+       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;
+               }
+       }
+
+       if (master->unique) {
+               kfree(master->unique);
+               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);
+               kfree(pt);
+       }
+
+       drm_ht_remove(&master->magiclist);
+
+       kfree(master);
+}
+
+void drm_master_put(struct drm_master **master)
+{
+       kref_put(&(*master)->refcount, drm_master_destroy);
+       *master = NULL;
+}
+EXPORT_SYMBOL(drm_master_put);
+
+int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       int ret = 0;
+
+       if (file_priv->is_master)
+               return 0;
+
+       if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
+               return -EINVAL;
+
+       if (!file_priv->master)
+               return -EINVAL;
+
+       if (!file_priv->minor->master &&
+           file_priv->minor->master != file_priv->master) {
+               mutex_lock(&dev->struct_mutex);
+               file_priv->minor->master = drm_master_get(file_priv->master);
+               file_priv->is_master = 1;
+               if (dev->driver->master_set) {
+                       ret = dev->driver->master_set(dev, file_priv, false);
+                       if (unlikely(ret != 0)) {
+                               file_priv->is_master = 0;
+                               drm_master_put(&file_priv->minor->master);
+                       }
+               }
+               mutex_unlock(&dev->struct_mutex);
+       }
+
+       return 0;
+}
+
+int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       if (!file_priv->is_master)
+               return -EINVAL;
+
+       if (!file_priv->minor->master)
+               return -EINVAL;
+
+       mutex_lock(&dev->struct_mutex);
+       if (dev->driver->master_drop)
+               dev->driver->master_drop(dev, file_priv, false);
+       drm_master_put(&file_priv->minor->master);
+       file_priv->is_master = 0;
+       mutex_unlock(&dev->struct_mutex);
+       return 0;
+}
+
 static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
                           const struct pci_device_id *ent,
                           struct drm_driver *driver)
@@ -89,11 +234,11 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
        INIT_LIST_HEAD(&dev->ctxlist);
        INIT_LIST_HEAD(&dev->vmalist);
        INIT_LIST_HEAD(&dev->maplist);
+       INIT_LIST_HEAD(&dev->vblank_event_list);
 
        spin_lock_init(&dev->count_lock);
        spin_lock_init(&dev->drw_lock);
-       spin_lock_init(&dev->tasklet_lock);
-       spin_lock_init(&dev->lock.spinlock);
+       spin_lock_init(&dev->event_lock);
        init_timer(&dev->timer);
        mutex_init(&dev->struct_mutex);
        mutex_init(&dev->ctxlist_mutex);
@@ -107,7 +252,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
 #ifdef __alpha__
        dev->hose = pdev->sysdata;
 #endif
-       dev->irq = pdev->irq;
 
        if (drm_ht_create(&dev->map_hash, 12)) {
                return -ENOMEM;
@@ -142,9 +286,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
                }
        }
 
-       if (dev->driver->load)
-               if ((retcode = dev->driver->load(dev, ent->driver_data)))
-                       goto error_out_unreg;
 
        retcode = drm_ctxbitmap_init(dev);
        if (retcode) {
@@ -202,6 +343,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
        new_minor->device = MKDEV(DRM_MAJOR, minor_id);
        new_minor->dev = dev;
        new_minor->index = minor_id;
+       INIT_LIST_HEAD(&new_minor->master_list);
 
        idr_replace(&drm_minors_idr, new_minor, minor_id);
 
@@ -212,7 +354,15 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
                        goto err_mem;
                }
        } else
-               new_minor->dev_root = NULL;
+               new_minor->proc_root = NULL;
+
+#if defined(CONFIG_DEBUG_FS)
+       ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
+       if (ret) {
+               DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
+               goto err_g2;
+       }
+#endif
 
        ret = drm_sysfs_device_add(new_minor);
        if (ret) {
@@ -256,7 +406,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
 
        DRM_DEBUG("\n");
 
-       dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return -ENOMEM;
 
@@ -269,49 +419,50 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
                printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
                goto err_g2;
        }
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               pci_set_drvdata(pdev, dev);
+               ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
+               if (ret)
+                       goto err_g2;
+       }
+
        if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
-               goto err_g2;
+               goto err_g3;
 
-       DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+       if (dev->driver->load) {
+               ret = dev->driver->load(dev, ent->driver_data);
+               if (ret)
+                       goto err_g4;
+       }
+
+        /* setup the grouping for the legacy output */
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
+               if (ret)
+                       goto err_g4;
+       }
+
+       list_add_tail(&dev->driver_item, &driver->device_list);
+
+       DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
                 driver->name, driver->major, driver->minor, driver->patchlevel,
-                driver->date, dev->primary->index);
+                driver->date, pci_name(pdev), dev->primary->index);
 
        return 0;
 
+err_g4:
+       drm_put_minor(&dev->primary);
+err_g3:
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               drm_put_minor(&dev->control);
 err_g2:
        pci_disable_device(pdev);
 err_g1:
-       drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+       kfree(dev);
        return ret;
 }
-
-/**
- * Put a device minor number.
- *
- * \param dev device data structure
- * \return always zero
- *
- * Cleans up the proc resources. If it is the last minor then release the foreign
- * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
- * unregisters the character device.
- */
-int drm_put_dev(struct drm_device * dev)
-{
-       DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
-
-       if (dev->unique) {
-               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
-               dev->unique = NULL;
-               dev->unique_len = 0;
-       }
-       if (dev->devname) {
-               drm_free(dev->devname, strlen(dev->devname) + 1,
-                        DRM_MEM_DRIVER);
-               dev->devname = NULL;
-       }
-       drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
-       return 0;
-}
+EXPORT_SYMBOL(drm_get_dev);
 
 /**
  * Put a secondary minor number.
@@ -331,6 +482,10 @@ int drm_put_minor(struct drm_minor **minor_p)
 
        if (minor->type == DRM_MINOR_LEGACY)
                drm_proc_cleanup(minor, drm_proc_root);
+#if defined(CONFIG_DEBUG_FS)
+       drm_debugfs_cleanup(minor);
+#endif
+
        drm_sysfs_device_remove(minor);
 
        idr_remove(&drm_minors_idr, minor->index);
@@ -339,3 +494,67 @@ int drm_put_minor(struct drm_minor **minor_p)
        *minor_p = NULL;
        return 0;
 }
+
+/**
+ * Called via drm_exit() at module unload time or when pci device is
+ * unplugged.
+ *
+ * Cleans up all DRM device, calling drm_lastclose().
+ *
+ * \sa drm_init
+ */
+void drm_put_dev(struct drm_device *dev)
+{
+       struct drm_driver *driver;
+       struct drm_map_list *r_list, *list_temp;
+
+       DRM_DEBUG("\n");
+
+       if (!dev) {
+               DRM_ERROR("cleanup called no dev\n");
+               return;
+       }
+       driver = dev->driver;
+
+       drm_lastclose(dev);
+
+       if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+           dev->agp && dev->agp->agp_mtrr >= 0) {
+               int retval;
+               retval = mtrr_del(dev->agp->agp_mtrr,
+                                 dev->agp->agp_info.aper_base,
+                                 dev->agp->agp_info.aper_size * 1024 * 1024);
+               DRM_DEBUG("mtrr_del=%d\n", retval);
+       }
+
+       if (dev->driver->unload)
+               dev->driver->unload(dev);
+
+       if (drm_core_has_AGP(dev) && dev->agp) {
+               kfree(dev->agp);
+               dev->agp = NULL;
+       }
+
+       drm_vblank_cleanup(dev);
+
+       list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
+               drm_rmmap(dev, r_list->map);
+       drm_ht_remove(&dev->map_hash);
+
+       drm_ctxbitmap_cleanup(dev);
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               drm_put_minor(&dev->control);
+
+       if (driver->driver_features & DRIVER_GEM)
+               drm_gem_destroy(dev);
+
+       drm_put_minor(&dev->primary);
+
+       if (dev->devname) {
+               kfree(dev->devname);
+               dev->devname = NULL;
+       }
+       kfree(dev);
+}
+EXPORT_SYMBOL(drm_put_dev);