#include <linux/slab.h>
 #include <linux/atomic.h>
 #include <linux/module.h>
+#include <linux/hashtable.h>
 
 MODULE_IMPORT_NS(DMA_BUF);
 
+#define VMW_TTM_OBJECT_REF_HT_ORDER 10
+
 /**
  * struct ttm_object_file
  *
        struct ttm_object_device *tdev;
        spinlock_t lock;
        struct list_head ref_list;
-       struct vmwgfx_open_hash ref_hash;
+       DECLARE_HASHTABLE(ref_hash, VMW_TTM_OBJECT_REF_HT_ORDER);
        struct kref refcount;
 };
 
        return tfile;
 }
 
+static int ttm_tfile_find_ref_rcu(struct ttm_object_file *tfile,
+                                 uint64_t key,
+                                 struct vmwgfx_hash_item **p_hash)
+{
+       struct vmwgfx_hash_item *hash;
+
+       hash_for_each_possible_rcu(tfile->ref_hash, hash, head, key) {
+               if (hash->key == key) {
+                       *p_hash = hash;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static int ttm_tfile_find_ref(struct ttm_object_file *tfile,
+                             uint64_t key,
+                             struct vmwgfx_hash_item **p_hash)
+{
+       struct vmwgfx_hash_item *hash;
+
+       hash_for_each_possible(tfile->ref_hash, hash, head, key) {
+               if (hash->key == key) {
+                       *p_hash = hash;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
 static void ttm_object_file_destroy(struct kref *kref)
 {
        struct ttm_object_file *tfile =
  * Return: A pointer to the object if successful or NULL otherwise.
  */
 struct ttm_base_object *
-ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
+ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key)
 {
        struct vmwgfx_hash_item *hash;
-       struct vmwgfx_open_hash *ht = &tfile->ref_hash;
        int ret;
 
        rcu_read_lock();
-       ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
+       ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
        if (ret) {
                rcu_read_unlock();
                return NULL;
 EXPORT_SYMBOL(ttm_base_object_noref_lookup);
 
 struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
-                                              uint32_t key)
+                                              uint64_t key)
 {
        struct ttm_base_object *base = NULL;
        struct vmwgfx_hash_item *hash;
-       struct vmwgfx_open_hash *ht = &tfile->ref_hash;
        int ret;
 
        rcu_read_lock();
-       ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
+       ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
 
        if (likely(ret == 0)) {
                base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
 }
 
 struct ttm_base_object *
-ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key)
 {
        struct ttm_base_object *base;
 
                       bool *existed,
                       bool require_existed)
 {
-       struct vmwgfx_open_hash *ht = &tfile->ref_hash;
        struct ttm_ref_object *ref;
        struct vmwgfx_hash_item *hash;
        int ret = -EINVAL;
 
        while (ret == -EINVAL) {
                rcu_read_lock();
-               ret = vmwgfx_ht_find_item_rcu(ht, base->handle, &hash);
+               ret = ttm_tfile_find_ref_rcu(tfile, base->handle, &hash);
 
                if (ret == 0) {
                        ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
                kref_init(&ref->kref);
 
                spin_lock(&tfile->lock);
-               ret = vmwgfx_ht_insert_item_rcu(ht, &ref->hash);
-
-               if (likely(ret == 0)) {
-                       list_add_tail(&ref->head, &tfile->ref_list);
-                       kref_get(&base->refcount);
-                       spin_unlock(&tfile->lock);
-                       if (existed != NULL)
-                               *existed = false;
-                       break;
-               }
+               hash_add_rcu(tfile->ref_hash, &ref->hash.head, ref->hash.key);
+               ret = 0;
 
+               list_add_tail(&ref->head, &tfile->ref_list);
+               kref_get(&base->refcount);
                spin_unlock(&tfile->lock);
-               BUG_ON(ret != -EINVAL);
-
-               kfree(ref);
+               if (existed != NULL)
+                       *existed = false;
        }
 
        return ret;
        struct ttm_ref_object *ref =
            container_of(kref, struct ttm_ref_object, kref);
        struct ttm_object_file *tfile = ref->tfile;
-       struct vmwgfx_open_hash *ht;
 
-       ht = &tfile->ref_hash;
-       (void)vmwgfx_ht_remove_item_rcu(ht, &ref->hash);
+       hash_del_rcu(&ref->hash.head);
        list_del(&ref->head);
        spin_unlock(&tfile->lock);
 
 int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
                              unsigned long key)
 {
-       struct vmwgfx_open_hash *ht = &tfile->ref_hash;
        struct ttm_ref_object *ref;
        struct vmwgfx_hash_item *hash;
        int ret;
 
        spin_lock(&tfile->lock);
-       ret = vmwgfx_ht_find_item(ht, key, &hash);
+       ret = ttm_tfile_find_ref(tfile, key, &hash);
        if (unlikely(ret != 0)) {
                spin_unlock(&tfile->lock);
                return -EINVAL;
        }
 
        spin_unlock(&tfile->lock);
-       vmwgfx_ht_remove(&tfile->ref_hash);
 
        ttm_object_file_unref(&tfile);
 }
 
-struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
-                                            unsigned int hash_order)
+struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev)
 {
        struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
-       int ret;
 
        if (unlikely(tfile == NULL))
                return NULL;
        kref_init(&tfile->refcount);
        INIT_LIST_HEAD(&tfile->ref_list);
 
-       ret = vmwgfx_ht_create(&tfile->ref_hash, hash_order);
-       if (ret)
-               goto out_err;
+       hash_init(tfile->ref_hash);
 
        return tfile;
-out_err:
-       vmwgfx_ht_remove(&tfile->ref_hash);
-
-       kfree(tfile);
-
-       return NULL;
 }
 
 struct ttm_object_device *
 
        struct ttm_object_file *tfile;
        struct kref refcount;
        void (*refcount_release) (struct ttm_base_object **base);
-       u32 handle;
+       u64 handle;
        enum ttm_object_type object_type;
        u32 shareable;
 };
  */
 
 extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
-                                                     *tfile, uint32_t key);
+                                                     *tfile, uint64_t key);
 
 /**
  * ttm_base_object_lookup_for_ref
  */
 
 extern struct ttm_base_object *
-ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key);
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key);
 
 /**
  * ttm_base_object_unref
  * ttm_object_file_init - initialize a struct ttm_object file
  *
  * @tdev: A struct ttm_object device this file is initialized on.
- * @hash_order: Order of the hash table used to hold the reference objects.
  *
  * This is typically called by the file_ops::open function.
  */
 
 extern struct ttm_object_file *ttm_object_file_init(struct ttm_object_device
-                                                   *tdev,
-                                                   unsigned int hash_order);
+                                                   *tdev);
 
 /**
  * ttm_object_file_release - release data held by a ttm_object_file
        kfree_rcu(__obj, __prime.base.rhead)
 
 struct ttm_base_object *
-ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key);
+ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key);
 
 /**
  * ttm_base_object_noref_release - release a base object pointer looked up