aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_bufs.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@starflyer.(none)>2005-08-05 08:11:22 -0400
committerDave Airlie <airlied@linux.ie>2005-08-05 08:11:22 -0400
commitd1f2b55ad2c11f46e30547a9f7754e99b478348e (patch)
treecabf9060c4f6cb419c7ed7fdcbcc6b6a91a83ac1 /drivers/char/drm/drm_bufs.c
parentc73681e77b40697d16ada777adf2c6dc4db05917 (diff)
drm: updated DRM map patch for 32/64 bit systems
I basically combined Paul's patches with additions that I had made for PCI scatter gather. I also tried more carefully to avoid problems with the same token assigned multiple times while trying to use the base address in the token if possible to gain as much backward compatibility as possible for broken DRI clients. From: Paul Mackerras <paulus@samba.org> and Egbert Eich <eich@suse.de> Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/drm_bufs.c')
-rw-r--r--drivers/char/drm/drm_bufs.c81
1 files changed, 59 insertions, 22 deletions
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index fcc8d244f46f..d1e0b106c261 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -64,13 +64,41 @@ static drm_local_map_t *drm_find_matching_map(drm_device_t *dev,
64 return NULL; 64 return NULL;
65} 65}
66 66
67#ifdef CONFIG_COMPAT
68/* 67/*
69 * Used to allocate 32-bit handles for _DRM_SHM regions 68 * Used to allocate 32-bit handles for mappings.
70 * The 0x10000000 value is chosen to be out of the way of
71 * FB/register and GART physical addresses.
72 */ 69 */
73static unsigned int map32_handle = 0x10000000; 70#define START_RANGE 0x10000000
71#define END_RANGE 0x40000000
72
73#ifdef _LP64
74static __inline__ unsigned int HandleID(unsigned long lhandle, drm_device_t *dev)
75{
76 static unsigned int map32_handle = START_RANGE;
77 unsigned int hash;
78
79 if (lhandle & 0xffffffff00000000) {
80 hash = map32_handle;
81 map32_handle += PAGE_SIZE;
82 if (map32_handle > END_RANGE)
83 map32_handle = START_RANGE;
84 } else
85 hash = lhandle;
86
87 while (1) {
88 drm_map_list_t *_entry;
89 list_for_each_entry(_entry, &dev->maplist->head,head) {
90 if (_entry->user_token == hash)
91 break;
92 }
93 if (&_entry->head == &dev->maplist->head)
94 return hash;
95
96 hash += PAGE_SIZE;
97 map32_handle += PAGE_SIZE;
98 }
99}
100#else
101# define HandleID(x,dev) (unsigned int)(x)
74#endif 102#endif
75 103
76/** 104/**
@@ -198,7 +226,7 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
198 drm_free(map, sizeof(*map), DRM_MEM_MAPS); 226 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
199 return -EINVAL; 227 return -EINVAL;
200 } 228 }
201 map->offset += dev->sg->handle; 229 map->offset += (unsigned long)dev->sg->virtual;
202 break; 230 break;
203 case _DRM_CONSISTENT: 231 case _DRM_CONSISTENT:
204 /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G, 232 /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
@@ -229,12 +257,11 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
229 257
230 down(&dev->struct_sem); 258 down(&dev->struct_sem);
231 list_add(&list->head, &dev->maplist->head); 259 list_add(&list->head, &dev->maplist->head);
232#ifdef CONFIG_COMPAT 260 /* Assign a 32-bit handle */
233 /* Assign a 32-bit handle for _DRM_SHM mappings */
234 /* We do it here so that dev->struct_sem protects the increment */ 261 /* We do it here so that dev->struct_sem protects the increment */
235 if (map->type == _DRM_SHM) 262 list->user_token = HandleID(map->type==_DRM_SHM
236 map->offset = map32_handle += PAGE_SIZE; 263 ? (unsigned long)map->handle
237#endif 264 : map->offset, dev);
238 up(&dev->struct_sem); 265 up(&dev->struct_sem);
239 266
240 *map_ptr = map; 267 *map_ptr = map;
@@ -251,6 +278,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
251 drm_map_t *map_ptr; 278 drm_map_t *map_ptr;
252 drm_map_t __user *argp = (void __user *)arg; 279 drm_map_t __user *argp = (void __user *)arg;
253 int err; 280 int err;
281 unsigned long handle = 0;
254 282
255 if (!(filp->f_mode & 3)) 283 if (!(filp->f_mode & 3))
256 return -EACCES; /* Require read/write */ 284 return -EACCES; /* Require read/write */
@@ -259,22 +287,29 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
259 return -EFAULT; 287 return -EFAULT;
260 } 288 }
261 289
262 err = drm_addmap( dev, map.offset, map.size, map.type, map.flags, 290 err = drm_addmap(dev, map.offset, map.size, map.type, map.flags,
263 &map_ptr ); 291 &map_ptr);
264 292
265 if (err) { 293 if (err) {
266 return err; 294 return err;
267 } 295 }
268 296
269 if (copy_to_user(argp, map_ptr, sizeof(*map_ptr))) 297 {
270 return -EFAULT; 298 drm_map_list_t *_entry;
271 if (map_ptr->type != _DRM_SHM) { 299 list_for_each_entry(_entry, &dev->maplist->head, head) {
272 if (copy_to_user(&argp->handle, &map_ptr->offset, 300 if (_entry->map == map_ptr)
273 sizeof(map_ptr->offset))) 301 handle = _entry->user_token;
302 }
303 if (!handle)
274 return -EFAULT; 304 return -EFAULT;
275 } 305 }
306
307 if (copy_to_user(argp, map_ptr, sizeof(*map_ptr)))
308 return -EFAULT;
309 if (put_user(handle, &argp->handle))
310 return -EFAULT;
276 return 0; 311 return 0;
277} 312 }
278 313
279 314
280/** 315/**
@@ -388,7 +423,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
388 drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head); 423 drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
389 424
390 if (r_list->map && 425 if (r_list->map &&
391 r_list->map->handle == request.handle && 426 r_list->user_token == (unsigned long) request.handle &&
392 r_list->map->flags & _DRM_REMOVABLE) { 427 r_list->map->flags & _DRM_REMOVABLE) {
393 map = r_list->map; 428 map = r_list->map;
394 break; 429 break;
@@ -939,7 +974,8 @@ static int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
939 974
940 buf->offset = (dma->byte_count + offset); 975 buf->offset = (dma->byte_count + offset);
941 buf->bus_address = agp_offset + offset; 976 buf->bus_address = agp_offset + offset;
942 buf->address = (void *)(agp_offset + offset + dev->sg->handle); 977 buf->address = (void *)(agp_offset + offset
978 + (unsigned long)dev->sg->virtual);
943 buf->next = NULL; 979 buf->next = NULL;
944 buf->waiting = 0; 980 buf->waiting = 0;
945 buf->pending = 0; 981 buf->pending = 0;
@@ -1456,6 +1492,7 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
1456 || (drm_core_check_feature(dev, DRIVER_FB_DMA) 1492 || (drm_core_check_feature(dev, DRIVER_FB_DMA)
1457 && (dma->flags & _DRM_DMA_USE_FB))) { 1493 && (dma->flags & _DRM_DMA_USE_FB))) {
1458 drm_map_t *map = dev->agp_buffer_map; 1494 drm_map_t *map = dev->agp_buffer_map;
1495 unsigned long token = dev->agp_buffer_token;
1459 1496
1460 if ( !map ) { 1497 if ( !map ) {
1461 retcode = -EINVAL; 1498 retcode = -EINVAL;
@@ -1470,7 +1507,7 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
1470 virtual = do_mmap( filp, 0, map->size, 1507 virtual = do_mmap( filp, 0, map->size,
1471 PROT_READ | PROT_WRITE, 1508 PROT_READ | PROT_WRITE,
1472 MAP_SHARED, 1509 MAP_SHARED,
1473 (unsigned long)map->offset ); 1510 token );
1474#if LINUX_VERSION_CODE <= 0x020402 1511#if LINUX_VERSION_CODE <= 0x020402
1475 up( &current->mm->mmap_sem ); 1512 up( &current->mm->mmap_sem );
1476#else 1513#else