Keith Whitwell writes: > Sounds good Paul. I think it's worthwhile to at least investigate this > as it'd be a cleaner result all round at the end.
Based on Egbert's comments about the use of an idr structure restricting our choice of token values, I have taken an alternative approach where I put the user token in the drm_map_list_t structure, which is private to the kernel. This patch is against the current DRM code in the kernel tree. The DRM code in CVS looks a bit different and I'm not sure where it is up to. I am currently assigning completely arbitrary 32-bit tokens for maps just to see how that works, and it seems to be fine on my G5 (which has AGP and a radeon 9600 card). I think it would be preferable to use Egbert's code which uses the map->offset value if it fits into 32 bits in the longer term. I am also assigning 32-bit tokens even if CONFIG_COMPAT isn't defined. For 64-bit kernels that don't have CONFIG_COMPAT defined, do we still want to generate 32-bit tokens? We will have to if we make the tokens passed between the X server and the client 32-bit. If people don't like me adding the dev->agp_buffer_token field, the alternative would be to search the dev->maplist list to find the token for dev->agp_buffer_list in drm_mapbufs. I didn't see the point in throwing away the token and then having to search for it, though. I have incorporated the drm_core_findmap_by_base from Egbert's patch. Nothing in the kernel tree's DRM seems to need it at present. Comments? Paul. diff -urN linux-2.6/drivers/char/drm/drmP.h g5-ppc64-drm/drivers/char/drm/drmP.h --- linux-2.6/drivers/char/drm/drmP.h 2005-06-27 13:26:27.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/drmP.h 2005-07-04 08:56:35.000000000 +1000 @@ -531,6 +531,7 @@ 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; @@ -736,6 +737,7 @@ 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; @@ -1035,16 +1037,23 @@ drm_ioremapfree( map->handle, map->size, dev ); } -static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset) +static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, 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; +} + +static __inline__ struct drm_map *drm_core_findmap_by_base(struct drm_device *dev, unsigned long offset) +{ + drm_map_list_t *_entry; + + list_for_each_entry(_entry, &dev->maplist->head, head) + if (_entry->map && _entry->map->offset == offset) return _entry->map; - } - } return NULL; } diff -urN linux-2.6/drivers/char/drm/drm_bufs.c g5-ppc64-drm/drivers/char/drm/drm_bufs.c --- linux-2.6/drivers/char/drm/drm_bufs.c 2005-06-27 13:26:27.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/drm_bufs.c 2005-07-04 10:43:39.000000000 +1000 @@ -60,14 +60,10 @@ } EXPORT_SYMBOL(drm_order); -#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; -#endif /** * Ioctl to specify a range of memory that is available for mapping by a non-root process. @@ -90,6 +86,7 @@ drm_map_t *map; drm_map_t __user *argp = (void __user *)arg; drm_map_list_t *list; + unsigned long handle; if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */ @@ -196,17 +193,16 @@ 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 = handle = map32_handle += PAGE_SIZE; + up(&dev->struct_sem); if ( copy_to_user( argp, map, sizeof(*map) ) ) return -EFAULT; - if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset))) + if (put_user(handle, &argp->handle)) return -EFAULT; return 0; } @@ -251,7 +247,7 @@ r_list = list_entry(list, drm_map_list_t, head); if(r_list->map && - r_list->map->offset == (unsigned long) request.handle && + r_list->user_token == (unsigned long) request.handle && r_list->map->flags & _DRM_REMOVABLE) break; } @@ -1199,6 +1195,7 @@ if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) || (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) { drm_map_t *map = dev->agp_buffer_map; + unsigned long token = dev->agp_buffer_token; if ( !map ) { retcode = -EINVAL; @@ -1210,10 +1208,10 @@ #else down_write( ¤t->mm->mmap_sem ); #endif - virtual = do_mmap( filp, 0, map->size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - (unsigned long)map->offset ); + virtual = do_mmap(filp, 0, map->size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + token); #if LINUX_VERSION_CODE <= 0x020402 up( ¤t->mm->mmap_sem ); #else diff -urN linux-2.6/drivers/char/drm/drm_ioctl.c g5-ppc64-drm/drivers/char/drm/drm_ioctl.c --- linux-2.6/drivers/char/drm/drm_ioctl.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/drm_ioctl.c 2005-07-03 21:59:47.000000000 +1000 @@ -208,7 +208,7 @@ 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 -urN linux-2.6/drivers/char/drm/drm_proc.c g5-ppc64-drm/drivers/char/drm/drm_proc.c --- linux-2.6/drivers/char/drm/drm_proc.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/drm_proc.c 2005-07-03 17:44:47.000000000 +1000 @@ -232,13 +232,13 @@ if(!map) continue; if (map->type < 0 || map->type > 4) 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); + r_list->user_token); if (map->mtrr < 0) { DRM_PROC_PRINT("none\n"); } else { diff -urN linux-2.6/drivers/char/drm/drm_vm.c g5-ppc64-drm/drivers/char/drm/drm_vm.c --- linux-2.6/drivers/char/drm/drm_vm.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/drm_vm.c 2005-07-04 10:43:54.000000000 +1000 @@ -71,12 +71,13 @@ r_list = list_entry(list, drm_map_list_t, head); map = r_list->map; if (!map) continue; - if (map->offset == VM_OFFSET(vma)) break; + 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; @@ -558,13 +559,10 @@ 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)) break; + if (r_list->user_token == VM_OFFSET(vma)) break; } if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) @@ -603,7 +601,7 @@ /* 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; @@ -626,12 +624,12 @@ offset = dev->driver->get_reg_ofs(dev); #ifdef __sparc__ if (io_remap_pfn_range(DRM_RPR_ARG(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)) #else if (io_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 @@ -639,7 +637,7 @@ 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 -urN linux-2.6/drivers/char/drm/ffb_drv.c g5-ppc64-drm/drivers/char/drm/ffb_drv.c --- linux-2.6/drivers/char/drm/ffb_drv.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/ffb_drv.c 2005-07-03 17:44:47.000000000 +1000 @@ -152,14 +152,11 @@ return NULL; list_for_each(list, &dev->maplist->head) { - unsigned long uoff; - r_list = (drm_map_list_t *)list; map = r_list->map; if (!map) continue; - uoff = (map->offset & 0xffffffff); - if (uoff == off) + if (r_list->user_token == off) return map; } diff -urN linux-2.6/drivers/char/drm/gamma_dma.c g5-ppc64-drm/drivers/char/drm/gamma_dma.c --- linux-2.6/drivers/char/drm/gamma_dma.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/gamma_dma.c 2005-07-04 09:00:17.000000000 +1000 @@ -661,6 +661,7 @@ buf = dma->buflist[GLINT_DRI_BUF_COUNT]; } else { + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); drm_core_ioremap( dev->agp_buffer_map, dev); @@ -844,8 +845,9 @@ r_list = NULL; 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) break; + if (r_list->map && + r_list->user_token == request.handle) + break; } if (list == &(dev->maplist->head)) { up(&dev->struct_sem); diff -urN linux-2.6/drivers/char/drm/i810_dma.c g5-ppc64-drm/drivers/char/drm/i810_dma.c --- linux-2.6/drivers/char/drm/i810_dma.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/i810_dma.c 2005-07-04 08:57:54.000000000 +1000 @@ -351,6 +351,7 @@ 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 -urN linux-2.6/drivers/char/drm/i830_dma.c g5-ppc64-drm/drivers/char/drm/i830_dma.c --- linux-2.6/drivers/char/drm/i830_dma.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/i830_dma.c 2005-07-04 08:58:02.000000000 +1000 @@ -358,6 +358,7 @@ 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 -urN linux-2.6/drivers/char/drm/mga_dma.c g5-ppc64-drm/drivers/char/drm/mga_dma.c --- linux-2.6/drivers/char/drm/mga_dma.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/mga_dma.c 2005-07-04 08:58:11.000000000 +1000 @@ -476,6 +476,7 @@ mga_do_cleanup_dma( 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( "failed to find dma buffer region!\n" ); diff -urN linux-2.6/drivers/char/drm/r128_cce.c g5-ppc64-drm/drivers/char/drm/r128_cce.c --- linux-2.6/drivers/char/drm/r128_cce.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/r128_cce.c 2005-07-04 08:58:30.000000000 +1000 @@ -487,6 +487,7 @@ 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"); diff -urN linux-2.6/drivers/char/drm/radeon_cp.c g5-ppc64-drm/drivers/char/drm/radeon_cp.c --- linux-2.6/drivers/char/drm/radeon_cp.c 2005-04-26 15:37:56.000000000 +1000 +++ g5-ppc64-drm/drivers/char/drm/radeon_cp.c 2005-07-04 08:59:23.000000000 +1000 @@ -1407,6 +1407,7 @@ 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"); ------------------------------------------------------- SF.Net email is sponsored by: Discover Easy Linux Migration Strategies from IBM. Find simple to follow Roadmaps, straightforward articles, informative Webcasts and more! Get everything you need to get up to speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel