diff options
author | Dave Jones <davej@redhat.com> | 2006-12-12 18:13:32 -0500 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2006-12-12 18:13:32 -0500 |
commit | f0eef25339f92f7cd4aeea23d9ae97987a5a1e82 (patch) | |
tree | 2472e94d39f43a9580a6d2d5d92de0b749023263 /drivers/char/drm/drm_bufs.c | |
parent | 0cfea5dd98205f2fa318836da664a7d7df1afbc1 (diff) | |
parent | e1036502e5263851259d147771226161e5ccc85a (diff) |
Merge ../linus
Diffstat (limited to 'drivers/char/drm/drm_bufs.c')
-rw-r--r-- | drivers/char/drm/drm_bufs.c | 88 |
1 files changed, 48 insertions, 40 deletions
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 006b06d29727..9f65f5697ba8 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -65,43 +65,29 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev, | |||
65 | return NULL; | 65 | return NULL; |
66 | } | 66 | } |
67 | 67 | ||
68 | /* | 68 | static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash, |
69 | * Used to allocate 32-bit handles for mappings. | 69 | unsigned long user_token, int hashed_handle) |
70 | */ | ||
71 | #define START_RANGE 0x10000000 | ||
72 | #define END_RANGE 0x40000000 | ||
73 | |||
74 | #ifdef _LP64 | ||
75 | static __inline__ unsigned int HandleID(unsigned long lhandle, | ||
76 | drm_device_t *dev) | ||
77 | { | 70 | { |
78 | static unsigned int map32_handle = START_RANGE; | 71 | int use_hashed_handle; |
79 | unsigned int hash; | 72 | #if (BITS_PER_LONG == 64) |
80 | 73 | use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle); | |
81 | if (lhandle & 0xffffffff00000000) { | 74 | #elif (BITS_PER_LONG == 32) |
82 | hash = map32_handle; | 75 | use_hashed_handle = hashed_handle; |
83 | map32_handle += PAGE_SIZE; | 76 | #else |
84 | if (map32_handle > END_RANGE) | 77 | #error Unsupported long size. Neither 64 nor 32 bits. |
85 | map32_handle = START_RANGE; | 78 | #endif |
86 | } else | ||
87 | hash = lhandle; | ||
88 | |||
89 | while (1) { | ||
90 | drm_map_list_t *_entry; | ||
91 | list_for_each_entry(_entry, &dev->maplist->head, head) { | ||
92 | if (_entry->user_token == hash) | ||
93 | break; | ||
94 | } | ||
95 | if (&_entry->head == &dev->maplist->head) | ||
96 | return hash; | ||
97 | 79 | ||
98 | hash += PAGE_SIZE; | 80 | if (!use_hashed_handle) { |
99 | map32_handle += PAGE_SIZE; | 81 | int ret; |
82 | hash->key = user_token; | ||
83 | ret = drm_ht_insert_item(&dev->map_hash, hash); | ||
84 | if (ret != -EINVAL) | ||
85 | return ret; | ||
100 | } | 86 | } |
87 | return drm_ht_just_insert_please(&dev->map_hash, hash, | ||
88 | user_token, 32 - PAGE_SHIFT - 3, | ||
89 | PAGE_SHIFT, DRM_MAP_HASH_OFFSET); | ||
101 | } | 90 | } |
102 | #else | ||
103 | # define HandleID(x,dev) (unsigned int)(x) | ||
104 | #endif | ||
105 | 91 | ||
106 | /** | 92 | /** |
107 | * Ioctl to specify a range of memory that is available for mapping by a non-root process. | 93 | * Ioctl to specify a range of memory that is available for mapping by a non-root process. |
@@ -123,6 +109,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
123 | drm_map_t *map; | 109 | drm_map_t *map; |
124 | drm_map_list_t *list; | 110 | drm_map_list_t *list; |
125 | drm_dma_handle_t *dmah; | 111 | drm_dma_handle_t *dmah; |
112 | unsigned long user_token; | ||
113 | int ret; | ||
126 | 114 | ||
127 | map = drm_alloc(sizeof(*map), DRM_MEM_MAPS); | 115 | map = drm_alloc(sizeof(*map), DRM_MEM_MAPS); |
128 | if (!map) | 116 | if (!map) |
@@ -249,6 +237,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
249 | 237 | ||
250 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); | 238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); |
251 | if (!list) { | 239 | if (!list) { |
240 | if (map->type == _DRM_REGISTERS) | ||
241 | drm_ioremapfree(map->handle, map->size, dev); | ||
252 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 242 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
253 | return -EINVAL; | 243 | return -EINVAL; |
254 | } | 244 | } |
@@ -257,11 +247,22 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
257 | 247 | ||
258 | mutex_lock(&dev->struct_mutex); | 248 | mutex_lock(&dev->struct_mutex); |
259 | list_add(&list->head, &dev->maplist->head); | 249 | list_add(&list->head, &dev->maplist->head); |
250 | |||
260 | /* Assign a 32-bit handle */ | 251 | /* Assign a 32-bit handle */ |
261 | /* We do it here so that dev->struct_mutex protects the increment */ | 252 | /* We do it here so that dev->struct_mutex protects the increment */ |
262 | list->user_token = HandleID(map->type == _DRM_SHM | 253 | user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle : |
263 | ? (unsigned long)map->handle | 254 | map->offset; |
264 | : map->offset, dev); | 255 | ret = drm_map_handle(dev, &list->hash, user_token, 0); |
256 | if (ret) { | ||
257 | if (map->type == _DRM_REGISTERS) | ||
258 | drm_ioremapfree(map->handle, map->size, dev); | ||
259 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
260 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | ||
261 | mutex_unlock(&dev->struct_mutex); | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | list->user_token = list->hash.key; | ||
265 | mutex_unlock(&dev->struct_mutex); | 266 | mutex_unlock(&dev->struct_mutex); |
266 | 267 | ||
267 | *maplist = list; | 268 | *maplist = list; |
@@ -346,6 +347,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
346 | 347 | ||
347 | if (r_list->map == map) { | 348 | if (r_list->map == map) { |
348 | list_del(list); | 349 | list_del(list); |
350 | drm_ht_remove_key(&dev->map_hash, r_list->user_token); | ||
349 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 351 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
350 | break; | 352 | break; |
351 | } | 353 | } |
@@ -441,8 +443,10 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | |||
441 | return -EINVAL; | 443 | return -EINVAL; |
442 | } | 444 | } |
443 | 445 | ||
444 | if (!map) | 446 | if (!map) { |
447 | mutex_unlock(&dev->struct_mutex); | ||
445 | return -EINVAL; | 448 | return -EINVAL; |
449 | } | ||
446 | 450 | ||
447 | /* Register and framebuffer maps are permanent */ | 451 | /* Register and framebuffer maps are permanent */ |
448 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { | 452 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { |
@@ -883,6 +887,9 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
883 | request->count = entry->buf_count; | 887 | request->count = entry->buf_count; |
884 | request->size = size; | 888 | request->size = size; |
885 | 889 | ||
890 | if (request->flags & _DRM_PCI_BUFFER_RO) | ||
891 | dma->flags = _DRM_DMA_USE_PCI_RO; | ||
892 | |||
886 | atomic_dec(&dev->buf_alloc); | 893 | atomic_dec(&dev->buf_alloc); |
887 | return 0; | 894 | return 0; |
888 | 895 | ||
@@ -1467,9 +1474,10 @@ int drm_freebufs(struct inode *inode, struct file *filp, | |||
1467 | * \param arg pointer to a drm_buf_map structure. | 1474 | * \param arg pointer to a drm_buf_map structure. |
1468 | * \return zero on success or a negative number on failure. | 1475 | * \return zero on success or a negative number on failure. |
1469 | * | 1476 | * |
1470 | * Maps the AGP or SG buffer region with do_mmap(), and copies information | 1477 | * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information |
1471 | * about each buffer into user space. The PCI buffers are already mapped on the | 1478 | * about each buffer into user space. For PCI buffers, it calls do_mmap() with |
1472 | * addbufs_pci() call. | 1479 | * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls |
1480 | * drm_mmap_dma(). | ||
1473 | */ | 1481 | */ |
1474 | int drm_mapbufs(struct inode *inode, struct file *filp, | 1482 | int drm_mapbufs(struct inode *inode, struct file *filp, |
1475 | unsigned int cmd, unsigned long arg) | 1483 | unsigned int cmd, unsigned long arg) |