summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drm_bufs.c43
-rw-r--r--linux-core/drm_hashtab.c14
-rw-r--r--linux-core/drm_hashtab.h3
-rw-r--r--linux-core/drm_sman.c2
-rw-r--r--linux-core/drm_vm.c6
5 files changed, 47 insertions, 21 deletions
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;
}
diff --git a/linux-core/drm_hashtab.c b/linux-core/drm_hashtab.c
index 3be781df..d8c4549e 100644
--- a/linux-core/drm_hashtab.c
+++ b/linux-core/drm_hashtab.c
@@ -128,19 +128,21 @@ drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
int
drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
- unsigned long seed, int bits)
+ unsigned long seed, int bits, int shift,
+ unsigned long add)
{
int ret;
unsigned long mask = (1 << bits) - 1;
- unsigned long first;
+ unsigned long first, unshifted_key;
- item->key = hash_long(seed, bits);
- first = item->key;
+ unshifted_key = hash_long(seed, bits);
+ first = unshifted_key;
do{
+ item->key = (unshifted_key << shift) + add;
ret = drm_ht_insert_item(ht, item);
if (ret)
- item->key = (item->key + 1) & mask;
- } while(ret && (item->key != first));
+ unshifted_key = (unshifted_key + 1) & mask;
+ } while(ret && (unshifted_key != first));
if (ret) {
DRM_ERROR("Available key bit space exhausted\n");
diff --git a/linux-core/drm_hashtab.h b/linux-core/drm_hashtab.h
index d792499e..157353db 100644
--- a/linux-core/drm_hashtab.h
+++ b/linux-core/drm_hashtab.h
@@ -53,7 +53,8 @@ typedef struct drm_open_hash{
extern int drm_ht_create(drm_open_hash_t *ht, unsigned int order);
extern int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item);
extern int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
- unsigned long seed, int bits);
+ unsigned long seed, int bits, int shift,
+ unsigned long add);
extern int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item);
extern void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key);
diff --git a/linux-core/drm_sman.c b/linux-core/drm_sman.c
index a03c9f55..d894e82c 100644
--- a/linux-core/drm_sman.c
+++ b/linux-core/drm_sman.c
@@ -223,7 +223,7 @@ drm_memblock_item_t *drm_sman_alloc(drm_sman_t * sman, unsigned int manager,
if (drm_ht_just_insert_please
(&sman->user_hash_tab, &memblock->user_hash,
- (unsigned long)memblock, 32))
+ (unsigned long)memblock, 32, 0, 0))
goto out1;
owner_item = drm_sman_get_owner_item(sman, owner);
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index 93037bda..19866dca 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -70,8 +70,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
if (!dev->agp || !dev->agp->cant_use_aperture)
goto vm_nopage_error;
- if (drm_ht_find_item(&dev->map_hash, (VM_OFFSET(vma) - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
- &hash))
+ if (drm_ht_find_item(&dev->map_hash, VM_OFFSET(vma), &hash))
goto vm_nopage_error;
r_list = drm_hash_entry(hash, drm_map_list_t, hash);
@@ -575,8 +574,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
)
return drm_mmap_dma(filp, vma);
- if (drm_ht_find_item(&dev->map_hash, (VM_OFFSET(vma) - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
- &hash)) {
+ if (drm_ht_find_item(&dev->map_hash, VM_OFFSET(vma), &hash)) {
DRM_ERROR("Could not find map\n");
return -EINVAL;
}