diff options
Diffstat (limited to 'linux-core/drm_context.c')
-rw-r--r-- | linux-core/drm_context.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c index 82e90bcc4..474b5ba01 100644 --- a/linux-core/drm_context.c +++ b/linux-core/drm_context.c @@ -402,6 +402,7 @@ 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 ctx; if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) ) @@ -422,6 +423,20 @@ int DRM(addctx)( struct inode *inode, struct file *filp, if ( ctx.handle != DRM_KERNEL_CONTEXT ) DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */ #endif + ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST ); + if ( !ctx_entry ) { + DRM_DEBUG("out of memory\n"); + return -ENOMEM; + } + + 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( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) ) return -EFAULT; @@ -544,6 +559,20 @@ int DRM(rmctx)( struct inode *inode, struct file *filp, 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; } |