From 6bb28dade35ef35f5e677bb1d2c2107dc588750e Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 3 Mar 2004 21:16:36 +0000 Subject: Merge changes from DRI trunk. Obtained from: DRI trunk --- linux-core/drmP.h | 41 ++++++++++++++++++++++++----------------- linux-core/drm_agpsupport.c | 6 +++++- linux-core/drm_context.c | 29 +++++++++++++++++++++++++++++ linux-core/drm_drv.c | 26 ++++++++++++++++++++++++++ linux-core/drm_memory_debug.h | 1 + linux/drmP.h | 41 ++++++++++++++++++++++++----------------- linux/drm_agpsupport.h | 6 +++++- linux/drm_context.h | 29 +++++++++++++++++++++++++++++ linux/drm_drv.h | 26 ++++++++++++++++++++++++++ linux/drm_memory_debug.h | 1 + shared-core/sis_mm.c | 4 ++++ shared/sis_mm.c | 4 ++++ 12 files changed, 178 insertions(+), 36 deletions(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index b7b346d4..c2c14dbd 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -158,6 +158,7 @@ #define DRM_MEM_CTXBITMAP 18 #define DRM_MEM_STUB 19 #define DRM_MEM_SGLISTS 20 +#define DRM_MEM_CTXLIST 21 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) @@ -201,6 +202,14 @@ prefetch(pos->member.next)) #endif +#ifndef list_for_each_entry_safe +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) static inline struct page * vmalloc_to_page(void * vmalloc_addr) { @@ -309,19 +318,6 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr) DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \ } while (0) -#ifndef VMAP_4_ARGS - -#define DRM_IOREMAPAGP(map, dev) \ - (map)->handle = DRM(ioremap_agp)( (map)->offset, (map)->size, (dev) ) - -#define DRM_IOREMAPAGPFREE(map) \ - do { \ - if ( (map)->handle && (map)->size ) \ - DRM(ioremap_agp_free)( (map)->handle, (map)->size ); \ - } while (0) - -#endif - /** * Find mapping. * @@ -651,6 +647,15 @@ typedef struct drm_map_list { typedef drm_map_t drm_local_map_t; +/** + * Context handle list + */ +typedef struct drm_ctx_list { + struct list_head head; /**< list head */ + drm_context_t handle; /**< context handle */ + drm_file_t *tag; /**< associated fd private data */ +} drm_ctx_list_t; + #if __HAVE_VBL_IRQ typedef struct drm_vbl_sig { @@ -711,6 +716,12 @@ typedef struct drm_device { drm_map_list_t *maplist; /**< Linked list of regions */ int map_count; /**< Number of mappable regions */ + /** \name Context handle management */ + /*@{*/ + drm_ctx_list_t *ctxlist; /**< Linked list of context handles */ + int ctx_count; /**< Number of context handles */ + struct semaphore ctxlist_sem; /**< For ctxlist */ + drm_map_t **context_sareas; /**< per-context SAREA's */ int max_context; @@ -846,10 +857,6 @@ extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); #if __REALLY_HAVE_AGP -#ifndef VMAP_4_ARGS -extern void *DRM(ioremap_agp)(unsigned long offset, unsigned long size, drm_device_t *dev); -extern void DRM(ioremap_agp_free)(void *pt, unsigned long size); -#endif extern DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type); extern int DRM(free_agp)(DRM_AGP_MEM *handle, int pages); extern int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start); diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 0f281b57..f83651af 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -104,7 +104,11 @@ int DRM(agp_acquire)(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; int retcode; - if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) + if (!dev->agp) + return -ENODEV; + if (dev->agp->acquired) + return -EBUSY; + if (!drm_agp->acquire) return -EINVAL; #ifndef VMAP_4_ARGS if ( dev->agp->cant_use_aperture ) diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c index 82e90bcc..474b5ba0 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; } diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index d0dceaab..3eec29a0 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -329,6 +329,12 @@ static int DRM(setup)( drm_device_t *dev ) memset(dev->maplist, 0, sizeof(*dev->maplist)); INIT_LIST_HEAD(&dev->maplist->head); + dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist), + DRM_MEM_CTXLIST); + if(dev->ctxlist == NULL) return -ENOMEM; + memset(dev->ctxlist, 0, sizeof(*dev->ctxlist)); + INIT_LIST_HEAD(&dev->ctxlist->head); + dev->vmalist = NULL; dev->sigdata.lock = dev->lock.hw_lock = NULL; init_waitqueue_head( &dev->lock.lock_queue ); @@ -567,6 +573,7 @@ static int DRM(probe)(struct pci_dev *pdev) dev->count_lock = SPIN_LOCK_UNLOCKED; init_timer( &dev->timer ); sema_init( &dev->struct_sem, 1 ); + sema_init( &dev->ctxlist_sem, 1 ); if ((dev->minor = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) return -EPERM; @@ -896,6 +903,25 @@ int DRM(release)( struct inode *inode, struct file *filp ) DRM(fasync)( -1, filp, 0 ); + 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->tag == priv && + pos->handle != DRM_KERNEL_CONTEXT ) { +#ifdef DRIVER_CTX_DTOR + DRIVER_CTX_DTOR(pos->handle); +#endif + DRM(ctxbitmap_free)( dev, pos->handle ); + + list_del( &pos->head ); + DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST ); + } + } + } + up( &dev->ctxlist_sem ); + down( &dev->struct_sem ); if ( priv->remove_auth_on_close == 1 ) { drm_file_t *temp = dev->file_first; diff --git a/linux-core/drm_memory_debug.h b/linux-core/drm_memory_debug.h index fae419ec..2a2e7d79 100644 --- a/linux-core/drm_memory_debug.h +++ b/linux-core/drm_memory_debug.h @@ -68,6 +68,7 @@ static drm_mem_stats_t DRM(mem_stats)[] = { [DRM_MEM_TOTALAGP] = { "totalagp" }, [DRM_MEM_BOUNDAGP] = { "boundagp" }, [DRM_MEM_CTXBITMAP] = { "ctxbitmap"}, + [DRM_MEM_CTXLIST] = { "ctxlist" }, [DRM_MEM_STUB] = { "stub" }, { NULL, 0, } /* Last entry must be null */ }; diff --git a/linux/drmP.h b/linux/drmP.h index b7b346d4..c2c14dbd 100644 --- a/linux/drmP.h +++ b/linux/drmP.h @@ -158,6 +158,7 @@ #define DRM_MEM_CTXBITMAP 18 #define DRM_MEM_STUB 19 #define DRM_MEM_SGLISTS 20 +#define DRM_MEM_CTXLIST 21 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) @@ -201,6 +202,14 @@ prefetch(pos->member.next)) #endif +#ifndef list_for_each_entry_safe +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) static inline struct page * vmalloc_to_page(void * vmalloc_addr) { @@ -309,19 +318,6 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr) DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \ } while (0) -#ifndef VMAP_4_ARGS - -#define DRM_IOREMAPAGP(map, dev) \ - (map)->handle = DRM(ioremap_agp)( (map)->offset, (map)->size, (dev) ) - -#define DRM_IOREMAPAGPFREE(map) \ - do { \ - if ( (map)->handle && (map)->size ) \ - DRM(ioremap_agp_free)( (map)->handle, (map)->size ); \ - } while (0) - -#endif - /** * Find mapping. * @@ -651,6 +647,15 @@ typedef struct drm_map_list { typedef drm_map_t drm_local_map_t; +/** + * Context handle list + */ +typedef struct drm_ctx_list { + struct list_head head; /**< list head */ + drm_context_t handle; /**< context handle */ + drm_file_t *tag; /**< associated fd private data */ +} drm_ctx_list_t; + #if __HAVE_VBL_IRQ typedef struct drm_vbl_sig { @@ -711,6 +716,12 @@ typedef struct drm_device { drm_map_list_t *maplist; /**< Linked list of regions */ int map_count; /**< Number of mappable regions */ + /** \name Context handle management */ + /*@{*/ + drm_ctx_list_t *ctxlist; /**< Linked list of context handles */ + int ctx_count; /**< Number of context handles */ + struct semaphore ctxlist_sem; /**< For ctxlist */ + drm_map_t **context_sareas; /**< per-context SAREA's */ int max_context; @@ -846,10 +857,6 @@ extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); #if __REALLY_HAVE_AGP -#ifndef VMAP_4_ARGS -extern void *DRM(ioremap_agp)(unsigned long offset, unsigned long size, drm_device_t *dev); -extern void DRM(ioremap_agp_free)(void *pt, unsigned long size); -#endif extern DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type); extern int DRM(free_agp)(DRM_AGP_MEM *handle, int pages); extern int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start); diff --git a/linux/drm_agpsupport.h b/linux/drm_agpsupport.h index 0f281b57..f83651af 100644 --- a/linux/drm_agpsupport.h +++ b/linux/drm_agpsupport.h @@ -104,7 +104,11 @@ int DRM(agp_acquire)(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; int retcode; - if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) + if (!dev->agp) + return -ENODEV; + if (dev->agp->acquired) + return -EBUSY; + if (!drm_agp->acquire) return -EINVAL; #ifndef VMAP_4_ARGS if ( dev->agp->cant_use_aperture ) diff --git a/linux/drm_context.h b/linux/drm_context.h index 82e90bcc..474b5ba0 100644 --- a/linux/drm_context.h +++ b/linux/drm_context.h @@ -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; } diff --git a/linux/drm_drv.h b/linux/drm_drv.h index d0dceaab..3eec29a0 100644 --- a/linux/drm_drv.h +++ b/linux/drm_drv.h @@ -329,6 +329,12 @@ static int DRM(setup)( drm_device_t *dev ) memset(dev->maplist, 0, sizeof(*dev->maplist)); INIT_LIST_HEAD(&dev->maplist->head); + dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist), + DRM_MEM_CTXLIST); + if(dev->ctxlist == NULL) return -ENOMEM; + memset(dev->ctxlist, 0, sizeof(*dev->ctxlist)); + INIT_LIST_HEAD(&dev->ctxlist->head); + dev->vmalist = NULL; dev->sigdata.lock = dev->lock.hw_lock = NULL; init_waitqueue_head( &dev->lock.lock_queue ); @@ -567,6 +573,7 @@ static int DRM(probe)(struct pci_dev *pdev) dev->count_lock = SPIN_LOCK_UNLOCKED; init_timer( &dev->timer ); sema_init( &dev->struct_sem, 1 ); + sema_init( &dev->ctxlist_sem, 1 ); if ((dev->minor = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) return -EPERM; @@ -896,6 +903,25 @@ int DRM(release)( struct inode *inode, struct file *filp ) DRM(fasync)( -1, filp, 0 ); + 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->tag == priv && + pos->handle != DRM_KERNEL_CONTEXT ) { +#ifdef DRIVER_CTX_DTOR + DRIVER_CTX_DTOR(pos->handle); +#endif + DRM(ctxbitmap_free)( dev, pos->handle ); + + list_del( &pos->head ); + DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST ); + } + } + } + up( &dev->ctxlist_sem ); + down( &dev->struct_sem ); if ( priv->remove_auth_on_close == 1 ) { drm_file_t *temp = dev->file_first; diff --git a/linux/drm_memory_debug.h b/linux/drm_memory_debug.h index fae419ec..2a2e7d79 100644 --- a/linux/drm_memory_debug.h +++ b/linux/drm_memory_debug.h @@ -68,6 +68,7 @@ static drm_mem_stats_t DRM(mem_stats)[] = { [DRM_MEM_TOTALAGP] = { "totalagp" }, [DRM_MEM_BOUNDAGP] = { "boundagp" }, [DRM_MEM_CTXBITMAP] = { "ctxbitmap"}, + [DRM_MEM_CTXLIST] = { "ctxlist" }, [DRM_MEM_STUB] = { "stub" }, { NULL, 0, } /* Last entry must be null */ }; diff --git a/shared-core/sis_mm.c b/shared-core/sis_mm.c index b6ff069d..092096c4 100644 --- a/shared-core/sis_mm.c +++ b/shared-core/sis_mm.c @@ -34,8 +34,12 @@ #include "sis_drv.h" #include "sis_ds.h" #if defined(__linux__) && defined(CONFIG_FB_SIS) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#include