drm: Avoid use-before-null-test on dev in drm_cleanup().
[safe/jmp/linux-2.6] / drivers / gpu / drm / drm_drv.c
index 3cb87a9..febb517 100644 (file)
@@ -74,6 +74,9 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
 
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
+
        DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -123,6 +126,23 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),
        DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
 };
 
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
@@ -138,8 +158,6 @@ static struct drm_ioctl_desc drm_ioctls[] = {
  */
 int drm_lastclose(struct drm_device * dev)
 {
-       struct drm_magic_entry *pt, *next;
-       struct drm_map_list *r_list, *list_t;
        struct drm_vma_entry *vma, *vma_temp;
        int i;
 
@@ -149,13 +167,7 @@ int drm_lastclose(struct drm_device * dev)
                dev->driver->lastclose(dev);
        DRM_DEBUG("driver lastclose completed\n");
 
-       if (dev->unique) {
-               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
-               dev->unique = NULL;
-               dev->unique_len = 0;
-       }
-
-       if (dev->irq_enabled)
+       if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
                drm_irq_uninstall(dev);
 
        mutex_lock(&dev->struct_mutex);
@@ -164,18 +176,9 @@ int drm_lastclose(struct drm_device * dev)
        drm_drawable_free_all(dev);
        del_timer(&dev->timer);
 
-       /* Clear pid list */
-       if (dev->magicfree.next) {
-               list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
-                       list_del(&pt->head);
-                       drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
-                       drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-               }
-               drm_ht_remove(&dev->magiclist);
-       }
-
        /* Clear AGP information */
-       if (drm_core_has_AGP(dev) && dev->agp) {
+       if (drm_core_has_AGP(dev) && dev->agp &&
+           !drm_core_check_feature(dev, DRIVER_MODESET)) {
                struct drm_agp_mem *entry, *tempe;
 
                /* Remove AGP resources, but leave dev->agp
@@ -194,7 +197,8 @@ int drm_lastclose(struct drm_device * dev)
                dev->agp->acquired = 0;
                dev->agp->enabled = 0;
        }
-       if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
+       if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg &&
+           !drm_core_check_feature(dev, DRIVER_MODESET)) {
                drm_sg_cleanup(dev->sg);
                dev->sg = NULL;
        }
@@ -205,13 +209,6 @@ int drm_lastclose(struct drm_device * dev)
                drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
        }
 
-       list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
-               if (!(r_list->map->flags & _DRM_DRIVER)) {
-                       drm_rmmap_locked(dev, r_list->map);
-                       r_list = NULL;
-               }
-       }
-
        if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
                for (i = 0; i < dev->queue_count; i++) {
                        if (dev->queuelist[i]) {
@@ -228,14 +225,11 @@ int drm_lastclose(struct drm_device * dev)
        }
        dev->queue_count = 0;
 
-       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
+           !drm_core_check_feature(dev, DRIVER_MODESET))
                drm_dma_takedown(dev);
 
-       if (dev->lock.hw_lock) {
-               dev->sigdata.lock = dev->lock.hw_lock = NULL;   /* SHM removed */
-               dev->lock.file_priv = NULL;
-               wake_up_interruptible(&dev->lock.lock_queue);
-       }
+       dev->dev_mapping = NULL;
        mutex_unlock(&dev->struct_mutex);
 
        DRM_DEBUG("lastclose completed\n");
@@ -331,6 +325,12 @@ static void drm_cleanup(struct drm_device * dev)
        drm_ht_remove(&dev->map_hash);
        drm_ctxbitmap_cleanup(dev);
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               drm_put_minor(&dev->control);
+
+       if (dev->driver->driver_features & DRIVER_GEM)
+               drm_gem_destroy(dev);
+
        drm_put_minor(&dev->primary);
        if (drm_put_dev(dev))
                DRM_ERROR("Cannot unload module\n");
@@ -488,7 +488,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
                retcode = -EINVAL;
        } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
                   ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
-                  ((ioctl->flags & DRM_MASTER) && !file_priv->master)) {
+                  ((ioctl->flags & DRM_MASTER) && !file_priv->is_master)) {
                retcode = -EACCES;
        } else {
                if (cmd & (IOC_IN | IOC_OUT)) {