Fedora Core 2.6.11-1.35_FC3 kernel
[linux-2.6.git] / drivers / char / drm / drm_context.h
index 64d32d6..b99c994 100644 (file)
 
 #include "drmP.h"
 
-#if !__HAVE_CTX_BITMAP
-#error "__HAVE_CTX_BITMAP must be defined"
-#endif
-
-
 /******************************************************************/
 /** \name Context bitmap support */
 /*@{*/
@@ -214,12 +209,11 @@ int DRM(getsareactx)(struct inode *inode, struct file *filp,
 {
        drm_file_t      *priv   = filp->private_data;
        drm_device_t    *dev    = priv->dev;
+       drm_ctx_priv_map_t __user *argp = (void __user *)arg;
        drm_ctx_priv_map_t request;
        drm_map_t *map;
 
-       if (copy_from_user(&request,
-                          (drm_ctx_priv_map_t *)arg,
-                          sizeof(request)))
+       if (copy_from_user(&request, argp, sizeof(request)))
                return -EFAULT;
 
        down(&dev->struct_sem);
@@ -232,7 +226,7 @@ int DRM(getsareactx)(struct inode *inode, struct file *filp,
        up(&dev->struct_sem);
 
        request.handle = map->handle;
-       if (copy_to_user((drm_ctx_priv_map_t *)arg, &request, sizeof(request)))
+       if (copy_to_user(argp, &request, sizeof(request)))
                return -EFAULT;
        return 0;
 }
@@ -260,7 +254,7 @@ int DRM(setsareactx)(struct inode *inode, struct file *filp,
        struct list_head *list;
 
        if (copy_from_user(&request,
-                          (drm_ctx_priv_map_t *)arg,
+                          (drm_ctx_priv_map_t __user *)arg,
                           sizeof(request)))
                return -EFAULT;
 
@@ -363,10 +357,11 @@ int DRM(resctx)( struct inode *inode, struct file *filp,
                 unsigned int cmd, unsigned long arg )
 {
        drm_ctx_res_t res;
+       drm_ctx_t __user *argp = (void __user *)arg;
        drm_ctx_t ctx;
        int i;
 
-       if ( copy_from_user( &res, (drm_ctx_res_t *)arg, sizeof(res) ) )
+       if ( copy_from_user( &res, argp, sizeof(res) ) )
                return -EFAULT;
 
        if ( res.count >= DRM_RESERVED_CONTEXTS ) {
@@ -380,7 +375,7 @@ int DRM(resctx)( struct inode *inode, struct file *filp,
        }
        res.count = DRM_RESERVED_CONTEXTS;
 
-       if ( copy_to_user( (drm_ctx_res_t *)arg, &res, sizeof(res) ) )
+       if ( copy_to_user( argp, &res, sizeof(res) ) )
                return -EFAULT;
        return 0;
 }
@@ -401,9 +396,11 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
+       drm_ctx_list_t * ctx_entry;
+       drm_ctx_t __user *argp = (void __user *)arg;
        drm_ctx_t ctx;
 
-       if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
+       if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
                return -EFAULT;
 
        ctx.handle = DRM(ctxbitmap_next)( dev );
@@ -417,12 +414,29 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
                                /* Should this return -EBUSY instead? */
                return -ENOMEM;
        }
-#ifdef DRIVER_CTX_CTOR
+
        if ( ctx.handle != DRM_KERNEL_CONTEXT )
-               DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
-#endif
+       {
+               if (dev->fn_tbl.context_ctor)
+                       dev->fn_tbl.context_ctor(dev, ctx.handle);
+       }
+
+       ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
+       if ( !ctx_entry ) {
+               DRM_DEBUG("out of memory\n");
+               return -ENOMEM;
+       }
 
-       if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
+       INIT_LIST_HEAD( &ctx_entry->head );
+       ctx_entry->handle = ctx.handle;
+       ctx_entry->tag = priv;
+
+       down( &dev->ctxlist_sem );
+       list_add( &ctx_entry->head, &dev->ctxlist->head );
+       ++dev->ctx_count;
+       up( &dev->ctxlist_sem );
+
+       if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
                return -EFAULT;
        return 0;
 }
@@ -446,15 +460,16 @@ int DRM(modctx)( struct inode *inode, struct file *filp,
 int DRM(getctx)( struct inode *inode, struct file *filp,
                 unsigned int cmd, unsigned long arg )
 {
+       drm_ctx_t __user *argp = (void __user *)arg;
        drm_ctx_t ctx;
 
-       if ( copy_from_user( &ctx, (drm_ctx_t*)arg, sizeof(ctx) ) )
+       if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
                return -EFAULT;
 
        /* This is 0, because we don't handle any context flags */
        ctx.flags = 0;
 
-       if ( copy_to_user( (drm_ctx_t*)arg, &ctx, sizeof(ctx) ) )
+       if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
                return -EFAULT;
        return 0;
 }
@@ -477,7 +492,7 @@ int DRM(switchctx)( struct inode *inode, struct file *filp,
        drm_device_t *dev = priv->dev;
        drm_ctx_t ctx;
 
-       if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
+       if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
                return -EFAULT;
 
        DRM_DEBUG( "%d\n", ctx.handle );
@@ -502,7 +517,7 @@ int DRM(newctx)( struct inode *inode, struct file *filp,
        drm_device_t *dev = priv->dev;
        drm_ctx_t ctx;
 
-       if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
+       if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
                return -EFAULT;
 
        DRM_DEBUG( "%d\n", ctx.handle );
@@ -529,7 +544,7 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
        drm_device_t *dev = priv->dev;
        drm_ctx_t ctx;
 
-       if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
+       if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
                return -EFAULT;
 
        DRM_DEBUG( "%d\n", ctx.handle );
@@ -537,13 +552,27 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
                priv->remove_auth_on_close = 1;
        }
        if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
-#ifdef DRIVER_CTX_DTOR
-               DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */
-#endif
+               if (dev->fn_tbl.context_dtor)
+                       dev->fn_tbl.context_dtor(dev, ctx.handle);
                DRM(ctxbitmap_free)( dev, ctx.handle );
        }
 
+       down( &dev->ctxlist_sem );
+       if ( !list_empty( &dev->ctxlist->head ) ) {
+               drm_ctx_list_t *pos, *n;
+
+               list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+                       if ( pos->handle == ctx.handle ) {
+                               list_del( &pos->head );
+                               DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+                               --dev->ctx_count;
+                       }
+               }
+       }
+       up( &dev->ctxlist_sem );
+
        return 0;
 }
 
 /*@}*/
+