From 126673d62afad6da84e833daa644a352d88a5e37 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 11 Jul 2006 14:37:37 +0000 Subject: 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. This keeps compatibility with buggy drivers, while still implementing a hashed map lookup. The SiS and via device driver major bumps are reverted. --- linux-core/drm_bufs.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'linux-core/drm_bufs.c') diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index 44705259..7dd46b69 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -65,6 +65,29 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev, return NULL; } +int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash, + unsigned long user_token, int hashed_handle) +{ + int use_hashed_handle; + +#if (BITS_PER_LONG == 64) + use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle); +#elif (BITS_PER_LONG == 32) + use_hashed_handle = hashed_handle; +#else +#error Unsupported long size. Neither 64 nor 32 bits. +#endif + + if (use_hashed_handle) { + return drm_ht_just_insert_please(&dev->map_hash, hash, + user_token, 32 - PAGE_SHIFT - 3, + PAGE_SHIFT, DRM_MAP_HASH_OFFSET); + } else { + hash->key = user_token; + return drm_ht_insert_item(&dev->map_hash, hash); + } +} + /** * Ioctl to specify a range of memory that is available for mapping by a non-root process. * @@ -85,6 +108,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, drm_map_t *map; drm_map_list_t *list; drm_dma_handle_t *dmah; + unsigned long user_token; + int ret; map = drm_alloc(sizeof(*map), DRM_MEM_MAPS); if (!map) @@ -260,20 +285,21 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, down(&dev->struct_sem); list_add(&list->head, &dev->maplist->head); + /* Assign a 32-bit handle */ - /* We do it here so that dev->struct_sem protects the increment */ - if (drm_ht_just_insert_please(&dev->map_hash, &list->hash, - ((map->type == _DRM_SHM) ? (unsigned long)map->handle : - map->offset) >> PAGE_SHIFT, - 32 - PAGE_SHIFT - 1)) { + user_token = (map->type == _DRM_SHM) ? (unsigned long) map->handle : + map->offset; + ret = drm_map_handle(dev, &list->hash, user_token, FALSE); + + if (ret) { drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(list, sizeof(*list), DRM_MEM_MAPS); up(&dev->struct_sem); - return -ENOMEM; + return ret; } - list->user_token = (list->hash.key << PAGE_SHIFT) + DRM_MAP_HASH_OFFSET; + list->user_token = list->hash.key; up(&dev->struct_sem); *maplist = list; @@ -358,8 +384,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) if (r_list->map == map) { list_del(list); - drm_ht_remove_key(&dev->map_hash, - (r_list->user_token - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT); + drm_ht_remove_key(&dev->map_hash, r_list->user_token); drm_free(list, sizeof(*list), DRM_MEM_MAPS); break; } -- cgit v1.2.3