diff options
author | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-08-07 08:36:47 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-09-21 15:32:31 -0400 |
commit | 8d153f7107ff2c5d6e32053ae377c961187ab6b9 (patch) | |
tree | c90cdf1bf8e04237e840b37033fc0f57b74ab292 /drivers/char/drm/drm_bufs.c | |
parent | 8669cbc5e651bf4effa20e8c244a5a7d67da6fe9 (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.c | 68 |
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 | /* | 68 | 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 | 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 | } |