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( &current->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( &current->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

Reply via email to