]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/char/drm/drm_drv.c
drm: avoid kernel oops in some error paths calling drm_lastclose
[karo-tx-linux.git] / drivers / char / drm / drm_drv.c
index c4fa5a29582b515fadbbd4aa5ec6ab1d98089722..654b95cdd9a3ddf378d3054d8f8c312afb27ddf4 100644 (file)
@@ -75,8 +75,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
        [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
 
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_ROOT_ONLY},
        [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
        [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
        [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
@@ -118,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
 };
 
-#define DRIVER_IOCTL_COUNT     DRM_ARRAY_SIZE( drm_ioctls )
+#define DRIVER_IOCTL_COUNT     ARRAY_SIZE( drm_ioctls )
 
 /**
  * Take down the DRM device.
@@ -151,16 +151,16 @@ int drm_lastclose(drm_device_t * dev)
        if (dev->irq_enabled)
                drm_irq_uninstall(dev);
 
-       down(&dev->struct_sem);
+       mutex_lock(&dev->struct_mutex);
        del_timer(&dev->timer);
 
        /* Clear pid list */
-       for (i = 0; i < DRM_HASH_SIZE; i++) {
-               for (pt = dev->magiclist[i].head; pt; pt = next) {
-                       next = pt->next;
+       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);
                }
-               dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
        }
 
        /* Clear AGP information */
@@ -231,7 +231,7 @@ int drm_lastclose(drm_device_t * dev)
                dev->lock.filp = NULL;
                wake_up_interruptible(&dev->lock.lock_queue);
        }
-       up(&dev->struct_sem);
+       mutex_unlock(&dev->struct_mutex);
 
        DRM_DEBUG("lastclose completed\n");
        return 0;