diff options
author | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-05-26 19:33:02 +0000 |
---|---|---|
committer | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-05-26 19:33:02 +0000 |
commit | e25835e9eec31d7f96602292a1ca8b94237551a9 (patch) | |
tree | 20f669c5ac6aa995d071a669e5e097cbe54ff551 | |
parent | 04797f75c5413abac35f3cbb297d75d27b48e866 (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.h | 27 | ||||
-rw-r--r-- | linux-core/drm_bufs.c | 10 | ||||
-rw-r--r-- | linux-core/drm_drv.c | 4 | ||||
-rw-r--r-- | linux-core/drm_fops.c | 9 | ||||
-rw-r--r-- | linux-core/drm_hashtab.c | 250 | ||||
-rw-r--r-- | linux-core/drm_hashtab.h | 64 | ||||
-rw-r--r-- | linux-core/drm_stub.c | 8 | ||||
-rw-r--r-- | linux-core/drm_ttm.c | 49 | ||||
-rw-r--r-- | linux-core/drm_ttm.h | 1 | ||||
-rw-r--r-- | linux-core/drm_vm.c | 32 |
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, ®ion))) { + 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, ®ion); + 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 |