summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas@tungstengraphics.com>2006-05-26 19:33:02 +0000
committerThomas Hellstrom <thomas@tungstengraphics.com>2006-05-26 19:33:02 +0000
commite25835e9eec31d7f96602292a1ca8b94237551a9 (patch)
tree20f669c5ac6aa995d071a669e5e097cbe54ff551
parent04797f75c5413abac35f3cbb297d75d27b48e866 (diff)
Replace the fast but very unflexible closed hash table implementation with
a generic open hash table ditto. It uses the kernel list_entry() macro to obtain the actual object from a "drm_hash_item_t *". This is done in exactly the same way as a list object is obtained from a "struct list_head *"
-rw-r--r--linux-core/drmP.h27
-rw-r--r--linux-core/drm_bufs.c10
-rw-r--r--linux-core/drm_drv.c4
-rw-r--r--linux-core/drm_fops.c9
-rw-r--r--linux-core/drm_hashtab.c250
-rw-r--r--linux-core/drm_hashtab.h64
-rw-r--r--linux-core/drm_stub.c8
-rw-r--r--linux-core/drm_ttm.c49
-rw-r--r--linux-core/drm_ttm.h1
-rw-r--r--linux-core/drm_vm.c32
10 files changed, 303 insertions, 151 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 18859623..2d85dcae 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -81,6 +81,7 @@
#include <linux/poll.h>
#include <asm/pgalloc.h>
#include "drm.h"
+#include "drm_hashtab.h"
#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
@@ -506,6 +507,7 @@ typedef struct drm_dma_handle {
*/
typedef struct drm_map_list {
struct list_head head; /**< list head */
+ drm_hash_item_t hash;
drm_map_t *map; /**< mapping */
unsigned int user_token;
void *private;
@@ -681,13 +683,6 @@ typedef struct drm_head {
struct class_device *dev_class;
} drm_head_t;
-typedef struct drm_closedhash {
- unsigned int size;
- unsigned int order;
- unsigned int fill;
- void **table;
-} drm_closedhash_t;
-
/**
* DRM device structure. This structure represent a complete card that
* may contain multiple heads.
@@ -734,8 +729,8 @@ typedef struct drm_device {
/*@{ */
drm_map_list_t *maplist; /**< Linked list of regions */
int map_count; /**< Number of mappable regions */
- drm_closedhash_t maphash; /**< Hashed list of maps */
- drm_closedhash_t ttmreghash; /**< Hashed list of ttm regions */
+ drm_open_hash_t maphash; /**< Hashed list of maps */
+ drm_open_hash_t ttmreghash; /**< Hashed list of ttm regions */
/** \name Context handle management */
/*@{ */
@@ -1015,20 +1010,6 @@ extern unsigned long drm_get_resource_len(drm_device_t *dev,
extern int drm_addmap_core(drm_device_t * dev, unsigned int offset,
unsigned int size, drm_map_type_t type,
drm_map_flags_t flags, drm_map_list_t ** maplist);
-
-
-/*
- * Closed hash table support drm_hashtab.c
- */
-extern void drm_remove_hashtab(drm_closedhash_t *ht);
-extern int drm_remove_ht_val(drm_closedhash_t *ht, unsigned int hash);
-extern int drm_get_ht_val(drm_closedhash_t *ht, unsigned int hash, void **item);
-extern int drm_insert_ht_val(drm_closedhash_t *ht, void *item, unsigned int *hash);
-extern int drm_create_hashtab(drm_closedhash_t *ht, unsigned int order);
-extern int drm_find_ht_item(drm_closedhash_t *ht, void *item, unsigned int *hash);
-
-
-
/* DMA support (drm_dma.h) */
extern int drm_dma_setup(drm_device_t * dev);
extern void drm_dma_takedown(drm_device_t * dev);
diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c
index d04233a1..217f331e 100644
--- a/linux-core/drm_bufs.c
+++ b/linux-core/drm_bufs.c
@@ -300,16 +300,20 @@ 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_insert_ht_val(&dev->maphash, (void *)list, &list->user_token)) {
+ if (drm_ht_just_insert_please(&dev->maphash, &list->hash,
+ (unsigned long) map->handle
+ , 32 - PAGE_SHIFT)) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
drm_free(list, sizeof(*list), DRM_MEM_MAPS);
up(&dev->struct_sem);
return -ENOMEM;
}
- list->user_token = (list->user_token << PAGE_SHIFT) + DRM_MAP_HASH_OFFSET;
+
+ list->user_token = (list->hash.key << PAGE_SHIFT) + DRM_MAP_HASH_OFFSET;
up(&dev->struct_sem);
@@ -393,7 +397,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
if (r_list->map == map) {
list_del(list);
- drm_remove_ht_val(&dev->maphash,
+ drm_ht_remove_key(&dev->maphash,
(r_list->user_token - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT);
drm_free(list, sizeof(*list), DRM_MEM_MAPS);
break;
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 6cd99a09..7a990790 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -369,8 +369,8 @@ static void __exit drm_cleanup(drm_device_t * dev)
dev->maplist = NULL;
}
- drm_remove_hashtab(&dev->maphash);
- drm_remove_hashtab(&dev->ttmreghash);
+ drm_ht_remove(&dev->maphash);
+ drm_ht_remove(&dev->ttmreghash);
if (!drm_fb_loaded)
pci_disable_device(dev->pdev);
diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c
index 9e9ba994..13b8bed7 100644
--- a/linux-core/drm_fops.c
+++ b/linux-core/drm_fops.c
@@ -353,7 +353,6 @@ int drm_release(struct inode *inode, struct file *filp)
drm_device_t *dev;
int retcode = 0;
struct list_head *list = NULL, *next = NULL;
- unsigned hash;
lock_kernel();
dev = priv->head->dev;
@@ -488,9 +487,7 @@ int drm_release(struct inode *inode, struct file *filp)
list_for_each_safe(list, next, &priv->ttms) {
drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
list_del(list);
- if (!drm_find_ht_item(&dev->maphash, entry, &hash)) {
- drm_remove_ht_val(&dev->maphash, hash);
- }
+ drm_ht_remove_item(&dev->maphash, &entry->hash);
if (-EBUSY != drm_destroy_ttm((drm_ttm_t *) entry->map->offset))
drm_free(entry->map, sizeof(*entry->map),
DRM_MEM_MAPS);
@@ -502,9 +499,7 @@ int drm_release(struct inode *inode, struct file *filp)
drm_ttm_backend_list_t *entry =
list_entry(list, drm_ttm_backend_list_t, head);
list_del(list);
- if (!drm_find_ht_item(&dev->ttmreghash, entry, &hash)) {
- drm_remove_ht_val(&dev->ttmreghash, hash);
- }
+ drm_ht_remove_item(&dev->ttmreghash, &entry->hash);
drm_user_destroy_region(entry);
}
diff --git a/linux-core/drm_hashtab.c b/linux-core/drm_hashtab.c
index 9e6e60c8..4d2fa9ae 100644
--- a/linux-core/drm_hashtab.c
+++ b/linux-core/drm_hashtab.c
@@ -1,99 +1,191 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO. USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple open hash tab implementation.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
#include "drmP.h"
+#include "drm_hashtab.h"
#include <linux/hash.h>
-int drm_create_hashtab(drm_closedhash_t * ht, unsigned int order)
+int
+drm_ht_create(drm_open_hash_t *ht, unsigned int order)
{
- ht->size = 1 << order;
- ht->order = order;
- ht->fill = 0;
- ht->table = drm_calloc(ht->size, sizeof(void *), DRM_MEM_MAPPINGS);
- return (NULL == ht->table);
+ unsigned int i;
+
+ ht->size = 1 << order;
+ ht->order = order;
+ ht->fill = 0;
+ ht->table = vmalloc(ht->size*sizeof(*ht->table));
+ if (!ht->table) {
+ DRM_ERROR("Out of memory for hash table\n");
+ return -ENOMEM;
+ }
+ for (i=0; i< ht->size; ++i) {
+ INIT_LIST_HEAD(&ht->table[i]);
+ }
+ return 0;
}
-int drm_insert_ht_val(drm_closedhash_t * ht, void *item, unsigned int *hash)
+void
+drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key)
{
-
- unsigned i, tmp_hash;
-
- if (!item) {
- DRM_ERROR("Trying to hash a NULL pointer.\n");
- return DRM_ERR(EINVAL);
- }
-
- if (ht->fill >= ht->size) {
- DRM_ERROR("Hash table full.\n");
- return DRM_ERR(ENOMEM);
- }
-
- tmp_hash = hash_ptr(item, ht->order);
- for (i = 0; i < ht->size; ++i) {
- if (!ht->table[tmp_hash]) {
- ht->table[tmp_hash] = item;
- ht->fill++;
- break;
- }
- if (++tmp_hash >= ht->size)
- tmp_hash = 0;
- }
- BUG_ON(i == ht->size);
- *hash = tmp_hash;
- return 0;
+ drm_hash_item_t *entry;
+ struct list_head *list, *h_list;
+ unsigned int hashed_key;
+ int count = 0;
+
+ hashed_key = hash_long(key, ht->order);
+ DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
+ h_list = &ht->table[hashed_key];
+ list_for_each(list, h_list) {
+ entry = list_entry(list, drm_hash_item_t, head);
+ DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
+ }
}
-int drm_get_ht_val(drm_closedhash_t * ht, unsigned int hash, void **item)
-{
- if (hash >= ht->size || !ht->table[hash]) {
- return DRM_ERR(EINVAL);
- }
- *item = ht->table[hash];
- return 0;
+static struct list_head
+*drm_ht_find_key(drm_open_hash_t *ht, unsigned long key, int *found)
+{
+ drm_hash_item_t *entry;
+ struct list_head *list, *h_list, *ret;
+ unsigned int hashed_key;
+
+ hashed_key = hash_long(key, ht->order);
+
+ *found = FALSE;
+ h_list = &ht->table[hashed_key];
+ ret = h_list;
+ list_for_each(list, h_list) {
+ entry = list_entry(list, drm_hash_item_t, head);
+ if (entry->key == key) {
+ ret = list;
+ *found = TRUE;
+ break;
+ }
+ if (entry->key > key) {
+ ret = list;
+ break;
+ }
+ }
+ return ret;
}
-int drm_find_ht_item(drm_closedhash_t * ht, void *item, unsigned int *hash)
+int
+drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
{
- unsigned i, tmp_hash;
- void **cur_item;
-
- if (!item) {
- DRM_ERROR("Trying to hash a NULL pointer.\n");
- return DRM_ERR(EINVAL);
- }
-
- cur_item = ht->table + (tmp_hash = hash_ptr(item, ht->order));
-
- for (i = 0; i < ht->size; ++i) {
- if (*cur_item == item) {
- break;
- }
- ++cur_item;
- if (++tmp_hash >= ht->size) {
- cur_item = ht->table;
- tmp_hash = 0;
- }
- }
- if (i == ht->size) {
- return DRM_ERR(EINVAL);
- }
-
- *hash = tmp_hash;
- return 0;
+ int found;
+ struct list_head *list;
+
+ list = drm_ht_find_key(ht, item->key, &found);
+ if (found) {
+ return -EINVAL;
+ } else {
+ list_add_tail(&item->head, list);
+ ht->fill++;
+ }
+ return 0;
}
-int drm_remove_ht_val(drm_closedhash_t * ht, unsigned int hash)
-{
+/*
+ * Just insert an item and return any "bits" bit key that hasn't been used before.
+ */
- if (hash >= ht->size) {
- return DRM_ERR(EINVAL);
- }
- ht->table[hash] = NULL;
- ht->fill--;
- return 0;
+int
+drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+ unsigned long seed, int bits)
+{
+ int ret;
+ unsigned long mask = (1 << bits) - 1;
+ unsigned long first;
+
+ item->key = hash_long(seed, bits);
+ first = item->key;
+ do{
+ ret = drm_ht_insert_item(ht, item);
+ if (ret)
+ item->key = item->key++ & mask;
+ } while(ret && (item->key != first));
+
+ if (ret) {
+ DRM_ERROR("Available key bit space exhausted\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int
+drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item)
+{
+ int found;
+ struct list_head *list;
+
+ list = drm_ht_find_key(ht, key, &found);
+ if (!found) {
+ return -1;
+ } else {
+ *item = list_entry(list, drm_hash_item_t, head);
+ return 0;
+ }
+}
+
+int
+drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key)
+{
+ int found;
+ struct list_head *list;
+
+ list = drm_ht_find_key(ht, key, &found);
+ if (found) {
+ list_del_init(list);
+ ht->fill--;
+ return 0;
+ }
+ return -1;
}
-void drm_remove_hashtab(drm_closedhash_t * ht)
+int
+drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item)
{
- if (ht->table)
- drm_free(ht->table, ht->size * sizeof(void *),
- DRM_MEM_MAPPINGS);
+ list_del_init(&item->head);
+ ht->fill--;
+ return 0;
}
+
+void drm_ht_remove(drm_open_hash_t *ht)
+{
+ if (ht->table) {
+ vfree(ht->table);
+ ht->table = NULL;
+ }
+}
+
diff --git a/linux-core/drm_hashtab.h b/linux-core/drm_hashtab.h
new file mode 100644
index 00000000..90716132
--- /dev/null
+++ b/linux-core/drm_hashtab.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO. USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple open hash tab implementation.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef DRM_HASHTAB_H
+#define DRM_HASHTAB_H
+
+typedef struct drm_hash_item{
+ struct list_head head;
+ unsigned long key;
+} drm_hash_item_t;
+
+typedef struct drm_open_hash{
+ unsigned int size;
+ unsigned int order;
+ unsigned int fill;
+ struct list_head *table;
+} drm_open_hash_t;
+
+
+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);
+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);
+extern int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key);
+extern int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item);
+extern void drm_ht_remove(drm_open_hash_t *ht);
+
+
+#endif
+
diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index ed725c93..c6bcba20 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -84,12 +84,12 @@ static int fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
if (dev->maplist == NULL)
return -ENOMEM;
INIT_LIST_HEAD(&dev->maplist->head);
- if (drm_create_hashtab(&dev->ttmreghash, 10)) {
- drm_free(dev->maplist,sizeof(*dev->maplist), DRM_MEM_MAPS);
+ if (drm_ht_create(&dev->ttmreghash, 10)) {
+ drm_free(dev->maplist,sizeof(*dev->maplist), DRM_MEM_MAPS);
return -ENOMEM;
}
- if (drm_create_hashtab(&dev->maphash, 10)) {
- drm_remove_hashtab(&dev->ttmreghash);
+ if (drm_ht_create(&dev->maphash, 10)) {
+ drm_ht_remove(&dev->ttmreghash);
drm_free(dev->maplist,sizeof(*dev->maplist), DRM_MEM_MAPS);
return -ENOMEM;
}
diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c
index a52e2606..2465a62e 100644
--- a/linux-core/drm_ttm.c
+++ b/linux-core/drm_ttm.c
@@ -313,7 +313,6 @@ int drm_destroy_ttm(drm_ttm_t * ttm)
int i;
struct list_head *list, *next;
struct page **cur_page;
- unsigned hash;
if (!ttm)
return 0;
@@ -329,10 +328,8 @@ int drm_destroy_ttm(drm_ttm_t * ttm)
list_for_each_safe(list, next, &ttm->be_list->head) {
drm_ttm_backend_list_t *entry =
list_entry(list, drm_ttm_backend_list_t, head);
- if (!drm_find_ht_item(&ttm->dev->ttmreghash,
- entry, &hash)) {
- drm_remove_ht_val(&ttm->dev->ttmreghash, hash);
- }
+ drm_ht_remove_item(&ttm->dev->ttmreghash,
+ &entry->hash);
drm_destroy_ttm_region(entry);
}
@@ -1076,7 +1073,10 @@ int drm_add_ttm(drm_device_t * dev, unsigned size, drm_map_list_t ** maplist)
}
map->handle = (void *)list;
- if (drm_insert_ht_val(&dev->maphash, map->handle, &list->user_token)) {
+
+ if (drm_ht_just_insert_please(&dev->maphash, &list->hash,
+ (unsigned long) map->handle,
+ 32 - PAGE_SHIFT)) {
drm_destroy_ttm(ttm);
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
drm_free(list, sizeof(*list), DRM_MEM_MAPS);
@@ -1084,7 +1084,7 @@ int drm_add_ttm(drm_device_t * dev, unsigned size, drm_map_list_t ** maplist)
}
list->user_token =
- (list->user_token << PAGE_SHIFT) + DRM_MAP_HASH_OFFSET;
+ (list->hash.key << PAGE_SHIFT) + DRM_MAP_HASH_OFFSET;
list->map = map;
*maplist = list;
@@ -1346,16 +1346,16 @@ static int drm_ttm_from_handle(drm_handle_t handle, drm_file_t * priv,
drm_ttm_t *ttm;
drm_map_list_t *map_list;
drm_map_t *map = NULL;
- void *hash_val;
+ drm_hash_item_t *hash;
- if (drm_get_ht_val(&dev->maphash,
- (handle -
- DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT, &hash_val)) {
+ if (drm_ht_find_item(&dev->maphash,
+ (handle - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
+ &hash)) {
DRM_ERROR("Could not find TTM map.\n");
return -EINVAL;
}
- map_list = (drm_map_list_t *) hash_val;
+ map_list = list_entry(hash, drm_map_list_t, hash);
map = map_list->map;
@@ -1378,7 +1378,6 @@ static int drm_ttm_create_buffer(drm_device_t * dev, drm_ttm_t * ttm,
drm_ttm_buf_arg_t * buf,
drm_ttm_backend_list_t ** created)
{
- unsigned region;
drm_ttm_backend_list_t *entry;
int ret;
int cached;
@@ -1389,11 +1388,14 @@ static int drm_ttm_create_buffer(drm_device_t * dev, drm_ttm_t * ttm,
buf->num_pages, cached, &entry)))
return ret;
- if ((ret = drm_insert_ht_val(&dev->ttmreghash, entry, &region))) {
+ if ((ret = drm_ht_just_insert_please(&dev->ttmreghash,
+ &entry->hash,
+ (unsigned long)entry,
+ 32 - PAGE_SHIFT))) {
drm_destroy_ttm_region(entry);
return ret;
}
- buf->region_handle = (drm_handle_t) region;
+ buf->region_handle = (drm_handle_t) entry->hash.key;
entry->pinned = 0;
*created = entry;
@@ -1405,13 +1407,13 @@ static int drm_ttm_region_from_handle(drm_handle_t handle, drm_file_t * priv,
{
drm_device_t *dev = priv->head->dev;
drm_ttm_backend_list_t *entry;
- void *hash_val;
+ drm_hash_item_t *hash;
- if (drm_get_ht_val(&dev->ttmreghash, handle, &hash_val)) {
+ if (drm_ht_find_item(&dev->ttmreghash, handle, &hash)) {
DRM_ERROR("Could not find TTM region.\n");
return -EINVAL;
}
- entry = (drm_ttm_backend_list_t *) hash_val;
+ entry = list_entry(hash, drm_ttm_backend_list_t, hash);
if (entry->owner && entry->owner->owner != priv) {
DRM_ERROR("Caller is not TTM region owner.\n");
return -EPERM;
@@ -1431,7 +1433,6 @@ static int drm_ttm_create_user_buf(drm_ttm_buf_arg_t * buf_p,
{
unsigned long start, end;
int ret, len;
- unsigned region;
drm_ttm_backend_list_t *entry;
drm_device_t *dev = priv->head->dev;
@@ -1451,13 +1452,15 @@ static int drm_ttm_create_user_buf(drm_ttm_buf_arg_t * buf_p,
return ret;
entry->anon_owner = priv;
- ret = drm_insert_ht_val(&dev->ttmreghash, entry, &region);
+ ret = drm_ht_just_insert_please(&dev->ttmreghash, &entry->hash,
+ (unsigned long) entry,
+ 32 - PAGE_SHIFT);
if (ret) {
drm_user_destroy_region(entry);
return ret;
}
list_add(&entry->head, &priv->anon_ttm_regs);
- buf_p->region_handle = (drm_handle_t) region;
+ buf_p->region_handle = entry->hash.key;
entry->pinned = 0;
*created = entry;
return 0;
@@ -1597,7 +1600,7 @@ static void drm_ttm_handle_buf(drm_file_t * priv, drm_ttm_buf_arg_t * buf_p,
drm_ttm_region_from_handle(buf_p->region_handle, priv,
&entry);
- drm_remove_ht_val(&dev->ttmreghash, buf_p->region_handle);
+ drm_ht_remove_key(&dev->ttmreghash, buf_p->region_handle);
ttm_mm = entry->mm;
if (buf_p->ret)
break;
@@ -1753,7 +1756,7 @@ static int drm_ttm_handle_remove(drm_file_t * priv, drm_handle_t handle)
return ret;
}
list_del(&map_list->head);
- drm_remove_ht_val(&dev->maphash,
+ drm_ht_remove_key(&dev->maphash,
(handle - DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT);
ret = drm_destroy_ttm(ttm);
drm_ttm_destroy_delayed(&dev->mm_driver->ttm_mm, TRUE);
diff --git a/linux-core/drm_ttm.h b/linux-core/drm_ttm.h
index 4bdc0122..41ab5efe 100644
--- a/linux-core/drm_ttm.h
+++ b/linux-core/drm_ttm.h
@@ -30,6 +30,7 @@ typedef struct drm_ttm_backend {
#define DRM_FLUSH_EXE (0x04)
typedef struct drm_ttm_backend_list {
+ drm_hash_item_t hash;
uint32_t flags;
atomic_t refcount;
struct list_head head;
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index cfdcd388..c89282ac 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -42,6 +42,7 @@ static void drm_vm_close(struct vm_area_struct *vma);
static void drm_vm_open(struct vm_area_struct *vma);
static void drm_vm_ttm_close(struct vm_area_struct *vma);
static int drm_vm_ttm_open(struct vm_area_struct *vma);
+static void drm_vm_ttm_open_wrapper(struct vm_area_struct *vma);
/*
* DAVE: The below definition is a duplication of the kernels protection_map, which is bad.
@@ -107,7 +108,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
drm_map_t *map = NULL;
drm_map_list_t *r_list;
struct list_head *list;
- void *hash_val;
+ drm_hash_item_t *hash;
/*
* Find the right map
@@ -118,12 +119,13 @@ 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_get_ht_val(&dev->maphash,
- (VM_OFFSET(vma) -DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
- &hash_val)) {
+ if (drm_ht_find_item(&dev->maphash,
+ (VM_OFFSET(vma) -DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
+ &hash)) {
goto vm_nopage_error;
}
- map = ((drm_map_list_t *) hash_val)->map;
+ r_list = list_entry(hash, drm_map_list_t, hash);
+ map = r_list->map;
#ifdef DRM_LIST
list_for_each(list, &dev->maplist->head) {
@@ -628,7 +630,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
static struct vm_operations_struct drm_vm_ttm_ops = {
.nopage = drm_vm_ttm_nopage,
- .open = drm_vm_ttm_open,
+ .open = drm_vm_ttm_open_wrapper,
.close = drm_vm_ttm_close,
};
@@ -696,6 +698,10 @@ static int drm_vm_ttm_open(struct vm_area_struct *vma) {
return ret;
}
+static void drm_vm_ttm_open_wrapper(struct vm_area_struct *vma)
+{
+ drm_vm_ttm_open(vma);
+}
/**
* \c close method for all virtual memory types.
@@ -849,7 +855,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
drm_map_list_t *r_list;
unsigned long offset = 0;
struct list_head *list;
- void *hash_val;
+ drm_hash_item_t *hash;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
@@ -870,12 +876,18 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
return drm_mmap_dma(filp, vma);
- if (drm_get_ht_val(&dev->maphash,
+ if (drm_ht_find_item(&dev->maphash,
+ (VM_OFFSET(vma) -DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
+ &hash)) {
+ return -EINVAL;
+ }
+
+ if (drm_ht_find_item(&dev->maphash,
(VM_OFFSET(vma) -DRM_MAP_HASH_OFFSET) >> PAGE_SHIFT,
- &hash_val)) {
+ &hash)) {
return -EINVAL;
}
- map = ((drm_map_list_t *) hash_val)->map;
+ map = list_entry(hash,drm_map_list_t, hash)->map;
#ifdef DRM_LIST