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
[email protected]
https://lists.sourceforge.net/lists/listinfo/dri-devel