aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_bufs.c
diff options
context:
space:
mode:
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