diff options
author | Dave Airlie <airlied@starflyer.(none)> | 2005-08-05 08:11:22 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2005-08-05 08:11:22 -0400 |
commit | d1f2b55ad2c11f46e30547a9f7754e99b478348e (patch) | |
tree | cabf9060c4f6cb419c7ed7fdcbcc6b6a91a83ac1 /drivers/char/drm/drm_bufs.c | |
parent | c73681e77b40697d16ada777adf2c6dc4db05917 (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.c | 81 |
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 | */ |
73 | static unsigned int map32_handle = 0x10000000; | 70 | #define START_RANGE 0x10000000 |
71 | #define END_RANGE 0x40000000 | ||
72 | |||
73 | #ifdef _LP64 | ||
74 | static __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( ¤t->mm->mmap_sem ); | 1512 | up( ¤t->mm->mmap_sem ); |
1476 | #else | 1513 | #else |