diff options
-rw-r--r-- | linux-core/drmP.h | 27 | ||||
-rw-r--r-- | linux-core/drm_bufs.c | 80 | ||||
-rw-r--r-- | linux-core/drm_context.c | 15 | ||||
-rw-r--r-- | linux-core/drm_ioctl.c | 2 | ||||
-rw-r--r-- | linux-core/drm_proc.c | 6 | ||||
-rw-r--r-- | linux-core/drm_scatter.c | 11 | ||||
-rw-r--r-- | linux-core/drm_vm.c | 22 | ||||
-rw-r--r-- | linux-core/i810_dma.c | 1 | ||||
-rw-r--r-- | linux-core/i830_dma.c | 1 | ||||
-rw-r--r-- | linux-core/mga_ioc32.c | 68 | ||||
-rw-r--r-- | shared-core/mga_dma.c | 1 | ||||
-rw-r--r-- | shared-core/mga_drm.h | 2 | ||||
-rw-r--r-- | shared-core/r128_cce.c | 6 | ||||
-rw-r--r-- | shared-core/radeon_cp.c | 1 |
14 files changed, 185 insertions, 58 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 2b4dbcf6..4f677471 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -100,12 +100,13 @@ #define DRIVER_USE_MTRR 0x4 #define DRIVER_PCI_DMA 0x8 #define DRIVER_SG 0x10 -#define DRIVER_FB_DMA 0x20 -#define DRIVER_HAVE_DMA 0x40 -#define DRIVER_HAVE_IRQ 0x80 -#define DRIVER_IRQ_SHARED 0x100 -#define DRIVER_IRQ_VBL 0x200 -#define DRIVER_DMA_QUEUE 0x400 +#define DRIVER_HAVE_DMA 0x20 +#define DRIVER_HAVE_IRQ 0x40 +#define DRIVER_IRQ_SHARED 0x80 +#define DRIVER_IRQ_VBL 0x100 +#define DRIVER_DMA_QUEUE 0x200 +#define DRIVER_FB_DMA 0x400 + /*@}*/ @@ -499,6 +500,7 @@ typedef struct drm_dma_handle { typedef struct drm_map_list { struct list_head head; /**< list head */ drm_map_t *map; /**< mapping */ + unsigned int user_token; } drm_map_list_t; typedef drm_map_t drm_local_map_t; @@ -729,6 +731,7 @@ typedef struct drm_device { struct drm_driver *driver; drm_local_map_t *agp_buffer_map; + unsigned int agp_buffer_token; drm_head_t primary; /**< primary screen head */ } drm_device_t; @@ -1019,16 +1022,12 @@ static __inline__ void drm_core_ioremapfree(struct drm_map *map, } static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, - unsigned long offset) + unsigned int token) { - struct list_head *_list; - list_for_each(_list, &dev->maplist->head) { - drm_map_list_t *_entry = - list_entry(_list, drm_map_list_t, head); - if (_entry->map && _entry->map->offset == offset) { + drm_map_list_t *_entry; + list_for_each_entry(_entry, &dev->maplist->head, head) + if (_entry->user_token == token) return _entry->map; - } - } return NULL; } diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index 416d7d8c..bad02f2d 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -56,8 +56,7 @@ static drm_local_map_t *drm_find_matching_map(drm_device_t *dev, list_for_each(list, &dev->maplist->head) { drm_map_list_t *entry = list_entry(list, drm_map_list_t, head); if (entry->map && map->type == entry->map->type && - ((entry->map->offset == map->offset) || - (map->type == _DRM_SHM))) { + entry->map->offset == map->offset) { return entry->map; } } @@ -65,13 +64,42 @@ static drm_local_map_t *drm_find_matching_map(drm_device_t *dev, return NULL; } -#ifdef CONFIG_COMPAT + /* - * Used to allocate 32-bit handles for _DRM_SHM regions - * The 0x10000000 value is chosen to be out of the way of - * FB/register and GART physical addresses. + * Used to allocate 32-bit handles for mappings. */ -static unsigned int map32_handle = 0x10000000; +#define START_RANGE 0x10000000 +#define END_RANGE 0x40000000 + +#ifdef _LP64 +static __inline__ unsigned int HandleID(unsigned long lhandle, drm_device_t *dev) +{ + static unsigned int map32_handle = START_RANGE; + unsigned int hash; + + if (lhandle & 0xffffffff00000000) { + hash = map32_handle; + map32_handle += PAGE_SIZE; + if (map32_handle > END_RANGE) + map32_handle = START_RANGE; + } else + hash = lhandle; + + while (1) { + drm_map_list_t *_entry; + list_for_each_entry(_entry, &dev->maplist->head,head) { + if (_entry->user_token == hash) + break; + } + if (&_entry->head == &dev->maplist->head) + return hash; + + hash += PAGE_SIZE; + map32_handle += PAGE_SIZE; + } +} +#else +# define HandleID(x,dev) (unsigned int)(x) #endif /** @@ -228,7 +256,7 @@ int drm_addmap(drm_device_t * dev, unsigned int offset, drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EINVAL; } - map->offset += dev->sg->handle; + map->offset += (unsigned long)dev->sg->virtual; break; case _DRM_CONSISTENT: { /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G. @@ -260,13 +288,11 @@ int drm_addmap(drm_device_t * dev, unsigned int offset, down(&dev->struct_sem); list_add(&list->head, &dev->maplist->head); -#ifdef CONFIG_COMPAT - /* Assign a 32-bit handle for _DRM_SHM mappings */ + /* Assign a 32-bit handle */ /* We do it here so that dev->struct_sem protects the increment */ - if (map->type == _DRM_SHM) - map->offset = map32_handle += PAGE_SIZE; -#endif - + list->user_token = HandleID(map->type==_DRM_SHM + ? (unsigned long)map->handle + : map->offset, dev); up(&dev->struct_sem); *map_ptr = map; @@ -283,6 +309,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, drm_map_t *map_ptr; drm_map_t __user *argp = (void __user *)arg; int err; + unsigned long handle = 0; if (!(filp->f_mode & 3)) return -EACCES; /* Require read/write */ @@ -301,13 +328,20 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, return err; } - if (copy_to_user(argp, map_ptr, sizeof(*map_ptr))) - return -EFAULT; - if (map_ptr->type != _DRM_SHM) { - if (copy_to_user(&argp->handle, - &map_ptr->offset, sizeof(map_ptr->offset))) + { + drm_map_list_t *_entry; + list_for_each_entry(_entry, &dev->maplist->head, head) { + if (_entry->map == map_ptr) + handle = _entry->user_token; + } + if (!handle) return -EFAULT; } + + if (copy_to_user(argp, map_ptr, sizeof(*map_ptr))) + return -EFAULT; + if (put_user(handle, &argp->handle)) + return -EFAULT; return 0; } @@ -422,7 +456,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head); if (r_list->map && - r_list->map->handle == request.handle && + r_list->user_token == (unsigned long) request.handle && r_list->map->flags & _DRM_REMOVABLE) { map = r_list->map; break; @@ -991,7 +1025,8 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) buf->offset = (dma->byte_count + offset); buf->bus_address = agp_offset + offset; - buf->address = (void *)(agp_offset + offset + dev->sg->handle); + buf->address = (void *)(agp_offset + offset + + (unsigned long)dev->sg->virtual); buf->next = NULL; buf->waiting = 0; buf->pending = 0; @@ -1517,6 +1552,7 @@ int drm_mapbufs(struct inode *inode, struct file *filp, || (drm_core_check_feature(dev, DRIVER_FB_DMA) && (dma->flags & _DRM_DMA_USE_FB))) { drm_map_t *map = dev->agp_buffer_map; + unsigned long token = dev->agp_buffer_token; if (!map) { retcode = -EINVAL; @@ -1530,7 +1566,7 @@ int drm_mapbufs(struct inode *inode, struct file *filp, virtual = do_mmap(filp, 0, map->size, PROT_READ | PROT_WRITE, MAP_SHARED, - (unsigned long)map->offset); + token); #if LINUX_VERSION_CODE <= 0x020402 up(¤t->mm->mmap_sem); #else diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c index baa8437d..5947c8e6 100644 --- a/linux-core/drm_context.c +++ b/linux-core/drm_context.c @@ -217,6 +217,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp, drm_ctx_priv_map_t __user *argp = (void __user *)arg; drm_ctx_priv_map_t request; drm_map_t *map; + drm_map_list_t *_entry; if (copy_from_user(&request, argp, sizeof(request))) return -EFAULT; @@ -231,7 +232,16 @@ int drm_getsareactx(struct inode *inode, struct file *filp, map = dev->context_sareas[request.ctx_id]; up(&dev->struct_sem); - request.handle = map->handle; + request.handle = 0; + list_for_each_entry(_entry, &dev->maplist->head,head) { + if (_entry->map == map) { + request.handle = (void *)(unsigned long)_entry->user_token; + break; + } + } + if (request.handle == 0) + return -EINVAL; + if (copy_to_user(argp, &request, sizeof(request))) return -EFAULT; return 0; @@ -266,7 +276,8 @@ int drm_setsareactx(struct inode *inode, struct file *filp, down(&dev->struct_sem); list_for_each(list, &dev->maplist->head) { r_list = list_entry(list, drm_map_list_t, head); - if (r_list->map && r_list->map->handle == request.handle) + if (r_list->map + && r_list->user_token == (unsigned long) request.handle) goto found; } bad: diff --git a/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c index eac89ea6..e0998d53 100644 --- a/linux-core/drm_ioctl.c +++ b/linux-core/drm_ioctl.c @@ -211,7 +211,7 @@ int drm_getmap(struct inode *inode, struct file *filp, map.size = r_list->map->size; map.type = r_list->map->type; map.flags = r_list->map->flags; - map.handle = r_list->map->handle; + map.handle = (void *)(unsigned long) r_list->user_token; map.mtrr = r_list->map->mtrr; up(&dev->struct_sem); diff --git a/linux-core/drm_proc.c b/linux-core/drm_proc.c index 94aea2b7..3e2b3ba0 100644 --- a/linux-core/drm_proc.c +++ b/linux-core/drm_proc.c @@ -238,11 +238,13 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, type = "??"; else type = types[map->type]; - DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", + DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08x ", i, map->offset, map->size, - type, map->flags, (unsigned long)map->handle); + type, map->flags, + r_list->user_token); + if (map->mtrr < 0) { DRM_PROC_PRINT("none\n"); } else { diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c index 342e7572..1647303d 100644 --- a/linux-core/drm_scatter.c +++ b/linux-core/drm_scatter.c @@ -58,6 +58,12 @@ void drm_sg_cleanup(drm_sg_mem_t * entry) drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS); } +#ifdef _LP64 +# define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1))) +#else +# define ScatterHandle(x) (unsigned int)(x) +#endif + int drm_sg_alloc(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -125,12 +131,13 @@ int drm_sg_alloc(struct inode *inode, struct file *filp, */ memset(entry->virtual, 0, pages << PAGE_SHIFT); - entry->handle = (unsigned long)entry->virtual; + entry->handle = ScatterHandle((unsigned long)entry->virtual); DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle); DRM_DEBUG("sg alloc virtual = %p\n", entry->virtual); - for (i = entry->handle, j = 0; j < pages; i += PAGE_SIZE, j++) { + for (i = (unsigned long)entry->virtual, j = 0; j < pages; + i += PAGE_SIZE, j++) { entry->pagelist[j] = vmalloc_to_page((void *)i); if (!entry->pagelist[j]) goto failed; diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 227dc663..b253991f 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -75,13 +75,13 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, map = r_list->map; if (!map) continue; - if (map->offset == VM_OFFSET(vma)) + if (r_list->user_token == VM_OFFSET(vma)) break; } if (map && map->type == _DRM_AGP) { unsigned long offset = address - vma->vm_start; - unsigned long baddr = VM_OFFSET(vma) + offset; + unsigned long baddr = map->offset + offset; struct drm_agp_mem *agpmem; struct page *page; @@ -319,7 +319,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, return NOPAGE_OOM; /* Nothing allocated */ offset = address - vma->vm_start; - map_offset = map->offset - dev->sg->handle; + map_offset = map->offset - (unsigned long)dev->sg->virtual; page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); page = entry->pagelist[page_offset]; get_page(page); @@ -586,14 +586,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) for performance, even if the list was a bit longer. */ list_for_each(list, &dev->maplist->head) { - unsigned long off; r_list = list_entry(list, drm_map_list_t, head); map = r_list->map; if (!map) continue; - off = dev->driver->get_map_ofs(map); - if (off == VM_OFFSET(vma)) + if (r_list->user_token == VM_OFFSET(vma)) break; } @@ -636,7 +634,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: - if (VM_OFFSET(vma) >= __pa(high_memory)) { + if (map->offset >= __pa(high_memory)) { #if defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; @@ -659,13 +657,13 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) #endif offset = dev->driver->get_reg_ofs(dev); #ifdef __sparc__ - if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, - VM_OFFSET(vma) + offset, + if (io_remap_pfn_range(vma, vma->vm_start, + (map->offset + offset) >>PAGE_SHIFT, vma->vm_end - vma->vm_start, - vma->vm_page_prot, 0)) + vma->vm_page_prot)) #else if (remap_pfn_range(vma, vma->vm_start, - (VM_OFFSET(vma) + offset) >> PAGE_SHIFT, + (map->offset + offset) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) #endif @@ -673,7 +671,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," " offset = 0x%lx\n", map->type, - vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset); + vma->vm_start, vma->vm_end, map->offset + offset); vma->vm_ops = &drm_vm_ops; break; case _DRM_SHM: diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c index 9e0634a5..2f0484ee 100644 --- a/linux-core/i810_dma.c +++ b/linux-core/i810_dma.c @@ -373,6 +373,7 @@ static int i810_dma_initialize(drm_device_t * dev, DRM_ERROR("can not find mmio map!\n"); return -EINVAL; } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { dev->dev_private = (void *)dev_priv; diff --git a/linux-core/i830_dma.c b/linux-core/i830_dma.c index 1c44f70d..022cecf3 100644 --- a/linux-core/i830_dma.c +++ b/linux-core/i830_dma.c @@ -366,6 +366,7 @@ static int i830_dma_initialize(drm_device_t * dev, DRM_ERROR("can not find mmio map!\n"); return -EINVAL; } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { dev->dev_private = (void *)dev_priv; diff --git a/linux-core/mga_ioc32.c b/linux-core/mga_ioc32.c index bc745cfa..5775cd63 100644 --- a/linux-core/mga_ioc32.c +++ b/linux-core/mga_ioc32.c @@ -1,3 +1,4 @@ + /** * \file mga_ioc32.c * @@ -129,9 +130,76 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); } +typedef struct drm_mga_drm_bootstrap32 { + u32 texture_handle; + u32 texture_size; + u32 primary_size; + u32 secondary_bin_count; + u32 secondary_bin_size; + u32 agp_mode; + u8 agp_size; +} drm_mga_dma_bootstrap32_t; + +static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, + unsigned long arg) +{ + drm_mga_dma_bootstrap32_t dma_bootstrap32; + drm_mga_dma_bootstrap_t __user *dma_bootstrap; + int err; + + if (copy_from_user(&dma_bootstrap32, (void __user *)arg, + sizeof(dma_bootstrap32))) + return -EFAULT; + + dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap)); + if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap)) + || __put_user(dma_bootstrap32.texture_handle, + &dma_bootstrap->texture_handle) + || __put_user(dma_bootstrap32.texture_size, + &dma_bootstrap->texture_size) + || __put_user(dma_bootstrap32.primary_size, + &dma_bootstrap->primary_size) + || __put_user(dma_bootstrap32.secondary_bin_count, + &dma_bootstrap->secondary_bin_count) + || __put_user(dma_bootstrap32.secondary_bin_size, + &dma_bootstrap->secondary_bin_size) + || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode) + || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) + return -EFAULT; + + err = drm_ioctl(file->f_dentry->d_inode, file, + DRM_IOCTL_MGA_DMA_BOOTSTRAP, + (unsigned long)dma_bootstrap); + if (err) + return err; + + if (__get_user(dma_bootstrap32.texture_handle, + &dma_bootstrap->texture_handle) + || __get_user(dma_bootstrap32.texture_size, + &dma_bootstrap->texture_size) + || __get_user(dma_bootstrap32.primary_size, + &dma_bootstrap->primary_size) + || __get_user(dma_bootstrap32.secondary_bin_count, + &dma_bootstrap->secondary_bin_count) + || __get_user(dma_bootstrap32.secondary_bin_size, + &dma_bootstrap->secondary_bin_size) + || __get_user(dma_bootstrap32.agp_mode, + &dma_bootstrap->agp_mode) + || __get_user(dma_bootstrap32.agp_size, + &dma_bootstrap->agp_size)) + return -EFAULT; + + if (copy_to_user((void __user *)arg, &dma_bootstrap32, + sizeof(dma_bootstrap32))) + return -EFAULT; + + return 0; +} + drm_ioctl_compat_t *mga_compat_ioctls[] = { [DRM_MGA_INIT] = compat_mga_init, [DRM_MGA_GETPARAM] = compat_mga_getparam, + [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap, }; /** diff --git a/shared-core/mga_dma.c b/shared-core/mga_dma.c index 31df5d6e..005c5234 100644 --- a/shared-core/mga_dma.c +++ b/shared-core/mga_dma.c @@ -819,6 +819,7 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) DRM_ERROR("failed to find primary dma region!\n"); return DRM_ERR(EINVAL); } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("failed to find dma buffer region!\n"); diff --git a/shared-core/mga_drm.h b/shared-core/mga_drm.h index 5b8f1564..5bcdbfab 100644 --- a/shared-core/mga_drm.h +++ b/shared-core/mga_drm.h @@ -312,7 +312,7 @@ typedef struct drm_mga_dma_bootstrap { * an IOMMU) is being used for "AGP" textures. */ /*@{*/ - drm_handle_t texture_handle; /**< Handle used to map AGP textures. */ + unsigned long texture_handle; /**< Handle used to map AGP textures. */ uint32_t texture_size; /**< Size of the AGP texture region. */ /*@}*/ diff --git a/shared-core/r128_cce.c b/shared-core/r128_cce.c index 34348cf0..33553670 100644 --- a/shared-core/r128_cce.c +++ b/shared-core/r128_cce.c @@ -323,7 +323,8 @@ static void r128_cce_init_ring_buffer(drm_device_t * dev, ring_start = dev_priv->cce_ring->offset - dev->agp->base; else #endif - ring_start = dev_priv->cce_ring->offset - dev->sg->handle; + ring_start = dev_priv->cce_ring->offset - + (unsigned long)dev->sg->virtual; R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET); @@ -484,6 +485,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) r128_do_cleanup_cce(dev); return DRM_ERR(EINVAL); } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("could not find dma buffer region!\n"); @@ -535,7 +537,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) dev_priv->cce_buffers_offset = dev->agp->base; else #endif - dev_priv->cce_buffers_offset = dev->sg->handle; + dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual; dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle; dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 8694d043..09a473d7 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1423,6 +1423,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("could not find dma buffer region!\n"); |