aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_bufs.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas@tungstengraphics.com>2006-08-07 08:36:47 -0400
committerDave Airlie <airlied@linux.ie>2006-09-21 15:32:31 -0400
commit8d153f7107ff2c5d6e32053ae377c961187ab6b9 (patch)
treec90cdf1bf8e04237e840b37033fc0f57b74ab292 /drivers/char/drm/drm_bufs.c
parent8669cbc5e651bf4effa20e8c244a5a7d67da6fe9 (diff)
drm: update user token hashing and map handles
Keep hashed user tokens, with the following changes: 32-bit physical device addresses are mapped directly to user-tokens. No duplicate maps are allowed, and the addresses are assumed to be outside of the range 0x10000000 through 0x30000000. The user-token is identical to the 32-bit physical start-address of the map. 64-bit physical device addressed are mapped to user-tokens in the range 0x10000000 to 0x30000000 with page-size increments. The user_token should not be interpreted as an address. Other map types, like upcoming TTM maps are mapped to user-tokens in the range 0x10000000 to 0x30000000 with page-size increments. The user_token should not be interpreted as an address. Implement hashed map lookups. 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.c68
1 files changed, 32 insertions, 36 deletions
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 7775fb5dfb9b..4440257f33e4 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -65,43 +65,27 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
65 return NULL; 65 return NULL;
66} 66}
67 67
68/* 68int 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
75static __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 return drm_ht_just_insert_please(&dev->map_hash, hash,
82 user_token, 32 - PAGE_SHIFT - 3,
83 PAGE_SHIFT, DRM_MAP_HASH_OFFSET);
84 } else {
85 hash->key = user_token;
86 return drm_ht_insert_item(&dev->map_hash, hash);
100 } 87 }
101} 88}
102#else
103# define HandleID(x,dev) (unsigned int)(x)
104#endif
105 89
106/** 90/**
107 * Ioctl to specify a range of memory that is available for mapping by a non-root process. 91 * Ioctl to specify a range of memory that is available for mapping by a non-root process.
@@ -123,6 +107,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
123 drm_map_t *map; 107 drm_map_t *map;
124 drm_map_list_t *list; 108 drm_map_list_t *list;
125 drm_dma_handle_t *dmah; 109 drm_dma_handle_t *dmah;
110 unsigned long user_token;
111 int ret;
126 112
127 map = drm_alloc(sizeof(*map), DRM_MEM_MAPS); 113 map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
128 if (!map) 114 if (!map)
@@ -257,11 +243,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
257 243
258 mutex_lock(&dev->struct_mutex); 244 mutex_lock(&dev->struct_mutex);
259 list_add(&list->head, &dev->maplist->head); 245 list_add(&list->head, &dev->maplist->head);
246
260 /* Assign a 32-bit handle */ 247 /* Assign a 32-bit handle */
261 /* We do it here so that dev->struct_mutex protects the increment */ 248 /* We do it here so that dev->struct_mutex protects the increment */
262 list->user_token = HandleID(map->type == _DRM_SHM 249 user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle :
263 ? (unsigned long)map->handle 250 map->offset;
264 : map->offset, dev); 251 ret = drm_map_handle(dev, &list->hash, user_token, FALSE);
252 if (ret) {
253 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
254 drm_free(list, sizeof(*list), DRM_MEM_MAPS);
255 mutex_unlock(&dev->struct_mutex);
256 return ret;
257 }
258
259 list->user_token = list->hash.key;
265 mutex_unlock(&dev->struct_mutex); 260 mutex_unlock(&dev->struct_mutex);
266 261
267 *maplist = list; 262 *maplist = list;
@@ -346,6 +341,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
346 341
347 if (r_list->map == map) { 342 if (r_list->map == map) {
348 list_del(list); 343 list_del(list);
344 drm_ht_remove_key(&dev->map_hash, r_list->user_token);
349 drm_free(list, sizeof(*list), DRM_MEM_MAPS); 345 drm_free(list, sizeof(*list), DRM_MEM_MAPS);
350 break; 346 break;
351 } 347 }