Commit 2985c964 authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/vmwgfx: Copy DRM hash-table code into driver

Besides some legacy code, vmwgfx is the only user of DRM's hash-
table implementation. Copy the code into the driver, so that the
core code can be retired.

No functional changes. However, the real solution for vmwgfx is to
use Linux' generic hash-table functions.

v2:
	* add TODO item for updating vmwgfx (Sam)
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211129094841.22499-3-tzimmermann@suse.de
parent b93199b2
...@@ -646,6 +646,17 @@ See drivers/gpu/drm/amd/display/TODO for tasks. ...@@ -646,6 +646,17 @@ See drivers/gpu/drm/amd/display/TODO for tasks.
Contact: Harry Wentland, Alex Deucher Contact: Harry Wentland, Alex Deucher
vmwgfx: Replace hashtable with Linux' implementation
----------------------------------------------------
The vmwgfx driver uses its own hashtable implementation. Replace the
code with Linux' implementation and update the callers. It's mostly a
refactoring task, but the interfaces are different.
Contact: Zack Rusin, Thomas Zimmermann <tzimmermann@suse.de>
Level: Intermediate
Bootsplash Bootsplash
========== ==========
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_hashtab.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \ vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \
vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \ vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \
......
...@@ -73,7 +73,7 @@ struct ttm_object_file { ...@@ -73,7 +73,7 @@ struct ttm_object_file {
struct ttm_object_device *tdev; struct ttm_object_device *tdev;
spinlock_t lock; spinlock_t lock;
struct list_head ref_list; struct list_head ref_list;
struct drm_open_hash ref_hash[TTM_REF_NUM]; struct vmwgfx_open_hash ref_hash[TTM_REF_NUM];
struct kref refcount; struct kref refcount;
}; };
...@@ -91,7 +91,7 @@ struct ttm_object_file { ...@@ -91,7 +91,7 @@ struct ttm_object_file {
struct ttm_object_device { struct ttm_object_device {
spinlock_t object_lock; spinlock_t object_lock;
struct drm_open_hash object_hash; struct vmwgfx_open_hash object_hash;
atomic_t object_count; atomic_t object_count;
struct ttm_mem_global *mem_glob; struct ttm_mem_global *mem_glob;
struct dma_buf_ops ops; struct dma_buf_ops ops;
...@@ -123,7 +123,7 @@ struct ttm_object_device { ...@@ -123,7 +123,7 @@ struct ttm_object_device {
struct ttm_ref_object { struct ttm_ref_object {
struct rcu_head rcu_head; struct rcu_head rcu_head;
struct drm_hash_item hash; struct vmwgfx_hash_item hash;
struct list_head head; struct list_head head;
struct kref kref; struct kref kref;
enum ttm_ref_type ref_type; enum ttm_ref_type ref_type;
...@@ -247,12 +247,12 @@ void ttm_base_object_unref(struct ttm_base_object **p_base) ...@@ -247,12 +247,12 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
struct ttm_base_object * 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, uint32_t key)
{ {
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
int ret; int ret;
rcu_read_lock(); rcu_read_lock();
ret = drm_ht_find_item_rcu(ht, key, &hash); ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
if (ret) { if (ret) {
rcu_read_unlock(); rcu_read_unlock();
return NULL; return NULL;
...@@ -267,12 +267,12 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, ...@@ -267,12 +267,12 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
uint32_t key) uint32_t key)
{ {
struct ttm_base_object *base = NULL; struct ttm_base_object *base = NULL;
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
int ret; int ret;
rcu_read_lock(); rcu_read_lock();
ret = drm_ht_find_item_rcu(ht, key, &hash); ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
if (likely(ret == 0)) { if (likely(ret == 0)) {
base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj; base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
...@@ -312,12 +312,12 @@ ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key) ...@@ -312,12 +312,12 @@ ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
bool ttm_ref_object_exists(struct ttm_object_file *tfile, bool ttm_ref_object_exists(struct ttm_object_file *tfile,
struct ttm_base_object *base) struct ttm_base_object *base)
{ {
struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
struct ttm_ref_object *ref; struct ttm_ref_object *ref;
rcu_read_lock(); rcu_read_lock();
if (unlikely(drm_ht_find_item_rcu(ht, base->handle, &hash) != 0)) if (unlikely(vmwgfx_ht_find_item_rcu(ht, base->handle, &hash) != 0))
goto out_false; goto out_false;
/* /*
...@@ -349,9 +349,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile, ...@@ -349,9 +349,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
enum ttm_ref_type ref_type, bool *existed, enum ttm_ref_type ref_type, bool *existed,
bool require_existed) bool require_existed)
{ {
struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; struct vmwgfx_open_hash *ht = &tfile->ref_hash[ref_type];
struct ttm_ref_object *ref; struct ttm_ref_object *ref;
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
struct ttm_operation_ctx ctx = { struct ttm_operation_ctx ctx = {
.interruptible = false, .interruptible = false,
...@@ -367,7 +367,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile, ...@@ -367,7 +367,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
while (ret == -EINVAL) { while (ret == -EINVAL) {
rcu_read_lock(); rcu_read_lock();
ret = drm_ht_find_item_rcu(ht, base->handle, &hash); ret = vmwgfx_ht_find_item_rcu(ht, base->handle, &hash);
if (ret == 0) { if (ret == 0) {
ref = drm_hash_entry(hash, struct ttm_ref_object, hash); ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
...@@ -398,7 +398,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile, ...@@ -398,7 +398,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
kref_init(&ref->kref); kref_init(&ref->kref);
spin_lock(&tfile->lock); spin_lock(&tfile->lock);
ret = drm_ht_insert_item_rcu(ht, &ref->hash); ret = vmwgfx_ht_insert_item_rcu(ht, &ref->hash);
if (likely(ret == 0)) { if (likely(ret == 0)) {
list_add_tail(&ref->head, &tfile->ref_list); list_add_tail(&ref->head, &tfile->ref_list);
...@@ -426,11 +426,11 @@ ttm_ref_object_release(struct kref *kref) ...@@ -426,11 +426,11 @@ ttm_ref_object_release(struct kref *kref)
container_of(kref, struct ttm_ref_object, kref); container_of(kref, struct ttm_ref_object, kref);
struct ttm_base_object *base = ref->obj; struct ttm_base_object *base = ref->obj;
struct ttm_object_file *tfile = ref->tfile; struct ttm_object_file *tfile = ref->tfile;
struct drm_open_hash *ht; struct vmwgfx_open_hash *ht;
struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
ht = &tfile->ref_hash[ref->ref_type]; ht = &tfile->ref_hash[ref->ref_type];
(void)drm_ht_remove_item_rcu(ht, &ref->hash); (void)vmwgfx_ht_remove_item_rcu(ht, &ref->hash);
list_del(&ref->head); list_del(&ref->head);
spin_unlock(&tfile->lock); spin_unlock(&tfile->lock);
...@@ -446,13 +446,13 @@ ttm_ref_object_release(struct kref *kref) ...@@ -446,13 +446,13 @@ ttm_ref_object_release(struct kref *kref)
int ttm_ref_object_base_unref(struct ttm_object_file *tfile, int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
unsigned long key, enum ttm_ref_type ref_type) unsigned long key, enum ttm_ref_type ref_type)
{ {
struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; struct vmwgfx_open_hash *ht = &tfile->ref_hash[ref_type];
struct ttm_ref_object *ref; struct ttm_ref_object *ref;
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
int ret; int ret;
spin_lock(&tfile->lock); spin_lock(&tfile->lock);
ret = drm_ht_find_item(ht, key, &hash); ret = vmwgfx_ht_find_item(ht, key, &hash);
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
spin_unlock(&tfile->lock); spin_unlock(&tfile->lock);
return -EINVAL; return -EINVAL;
...@@ -486,7 +486,7 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile) ...@@ -486,7 +486,7 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
spin_unlock(&tfile->lock); spin_unlock(&tfile->lock);
for (i = 0; i < TTM_REF_NUM; ++i) for (i = 0; i < TTM_REF_NUM; ++i)
drm_ht_remove(&tfile->ref_hash[i]); vmwgfx_ht_remove(&tfile->ref_hash[i]);
ttm_object_file_unref(&tfile); ttm_object_file_unref(&tfile);
} }
...@@ -508,7 +508,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev, ...@@ -508,7 +508,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
INIT_LIST_HEAD(&tfile->ref_list); INIT_LIST_HEAD(&tfile->ref_list);
for (i = 0; i < TTM_REF_NUM; ++i) { for (i = 0; i < TTM_REF_NUM; ++i) {
ret = drm_ht_create(&tfile->ref_hash[i], hash_order); ret = vmwgfx_ht_create(&tfile->ref_hash[i], hash_order);
if (ret) { if (ret) {
j = i; j = i;
goto out_err; goto out_err;
...@@ -518,7 +518,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev, ...@@ -518,7 +518,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
return tfile; return tfile;
out_err: out_err:
for (i = 0; i < j; ++i) for (i = 0; i < j; ++i)
drm_ht_remove(&tfile->ref_hash[i]); vmwgfx_ht_remove(&tfile->ref_hash[i]);
kfree(tfile); kfree(tfile);
...@@ -539,7 +539,7 @@ ttm_object_device_init(struct ttm_mem_global *mem_glob, ...@@ -539,7 +539,7 @@ ttm_object_device_init(struct ttm_mem_global *mem_glob,
tdev->mem_glob = mem_glob; tdev->mem_glob = mem_glob;
spin_lock_init(&tdev->object_lock); spin_lock_init(&tdev->object_lock);
atomic_set(&tdev->object_count, 0); atomic_set(&tdev->object_count, 0);
ret = drm_ht_create(&tdev->object_hash, hash_order); ret = vmwgfx_ht_create(&tdev->object_hash, hash_order);
if (ret != 0) if (ret != 0)
goto out_no_object_hash; goto out_no_object_hash;
...@@ -564,7 +564,7 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev) ...@@ -564,7 +564,7 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev)
WARN_ON_ONCE(!idr_is_empty(&tdev->idr)); WARN_ON_ONCE(!idr_is_empty(&tdev->idr));
idr_destroy(&tdev->idr); idr_destroy(&tdev->idr);
drm_ht_remove(&tdev->object_hash); vmwgfx_ht_remove(&tdev->object_hash);
kfree(tdev); kfree(tdev);
} }
......
...@@ -42,9 +42,8 @@ ...@@ -42,9 +42,8 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <drm/drm_hashtab.h>
#include "ttm_memory.h" #include "ttm_memory.h"
#include "vmwgfx_hashtab.h"
/** /**
* enum ttm_ref_type * enum ttm_ref_type
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
*/ */
struct vmw_cmdbuf_res { struct vmw_cmdbuf_res {
struct vmw_resource *res; struct vmw_resource *res;
struct drm_hash_item hash; struct vmwgfx_hash_item hash;
struct list_head head; struct list_head head;
enum vmw_cmdbuf_res_state state; enum vmw_cmdbuf_res_state state;
struct vmw_cmdbuf_res_manager *man; struct vmw_cmdbuf_res_manager *man;
...@@ -59,7 +59,7 @@ struct vmw_cmdbuf_res { ...@@ -59,7 +59,7 @@ struct vmw_cmdbuf_res {
* @resources and @list are protected by the cmdbuf mutex for now. * @resources and @list are protected by the cmdbuf mutex for now.
*/ */
struct vmw_cmdbuf_res_manager { struct vmw_cmdbuf_res_manager {
struct drm_open_hash resources; struct vmwgfx_open_hash resources;
struct list_head list; struct list_head list;
struct vmw_private *dev_priv; struct vmw_private *dev_priv;
}; };
...@@ -81,11 +81,11 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man, ...@@ -81,11 +81,11 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
enum vmw_cmdbuf_res_type res_type, enum vmw_cmdbuf_res_type res_type,
u32 user_key) u32 user_key)
{ {
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
int ret; int ret;
unsigned long key = user_key | (res_type << 24); unsigned long key = user_key | (res_type << 24);
ret = drm_ht_find_item(&man->resources, key, &hash); ret = vmwgfx_ht_find_item(&man->resources, key, &hash);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -105,7 +105,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man, ...@@ -105,7 +105,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man,
struct vmw_cmdbuf_res *entry) struct vmw_cmdbuf_res *entry)
{ {
list_del(&entry->head); list_del(&entry->head);
WARN_ON(drm_ht_remove_item(&man->resources, &entry->hash)); WARN_ON(vmwgfx_ht_remove_item(&man->resources, &entry->hash));
vmw_resource_unreference(&entry->res); vmw_resource_unreference(&entry->res);
kfree(entry); kfree(entry);
} }
...@@ -167,7 +167,7 @@ void vmw_cmdbuf_res_revert(struct list_head *list) ...@@ -167,7 +167,7 @@ void vmw_cmdbuf_res_revert(struct list_head *list)
vmw_cmdbuf_res_free(entry->man, entry); vmw_cmdbuf_res_free(entry->man, entry);
break; break;
case VMW_CMDBUF_RES_DEL: case VMW_CMDBUF_RES_DEL:
ret = drm_ht_insert_item(&entry->man->resources, &entry->hash); ret = vmwgfx_ht_insert_item(&entry->man->resources, &entry->hash);
BUG_ON(ret); BUG_ON(ret);
list_move_tail(&entry->head, &entry->man->list); list_move_tail(&entry->head, &entry->man->list);
entry->state = VMW_CMDBUF_RES_COMMITTED; entry->state = VMW_CMDBUF_RES_COMMITTED;
...@@ -206,7 +206,7 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man, ...@@ -206,7 +206,7 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
return -ENOMEM; return -ENOMEM;
cres->hash.key = user_key | (res_type << 24); cres->hash.key = user_key | (res_type << 24);
ret = drm_ht_insert_item(&man->resources, &cres->hash); ret = vmwgfx_ht_insert_item(&man->resources, &cres->hash);
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
kfree(cres); kfree(cres);
goto out_invalid_key; goto out_invalid_key;
...@@ -244,10 +244,10 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man, ...@@ -244,10 +244,10 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
struct vmw_resource **res_p) struct vmw_resource **res_p)
{ {
struct vmw_cmdbuf_res *entry; struct vmw_cmdbuf_res *entry;
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
int ret; int ret;
ret = drm_ht_find_item(&man->resources, user_key | (res_type << 24), ret = vmwgfx_ht_find_item(&man->resources, user_key | (res_type << 24),
&hash); &hash);
if (likely(ret != 0)) if (likely(ret != 0))
return -EINVAL; return -EINVAL;
...@@ -260,7 +260,7 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man, ...@@ -260,7 +260,7 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
*res_p = NULL; *res_p = NULL;
break; break;
case VMW_CMDBUF_RES_COMMITTED: case VMW_CMDBUF_RES_COMMITTED:
(void) drm_ht_remove_item(&man->resources, &entry->hash); (void) vmwgfx_ht_remove_item(&man->resources, &entry->hash);
list_del(&entry->head); list_del(&entry->head);
entry->state = VMW_CMDBUF_RES_DEL; entry->state = VMW_CMDBUF_RES_DEL;
list_add_tail(&entry->head, list); list_add_tail(&entry->head, list);
...@@ -295,7 +295,7 @@ vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv) ...@@ -295,7 +295,7 @@ vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv)
man->dev_priv = dev_priv; man->dev_priv = dev_priv;
INIT_LIST_HEAD(&man->list); INIT_LIST_HEAD(&man->list);
ret = drm_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER); ret = vmwgfx_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER);
if (ret == 0) if (ret == 0)
return man; return man;
...@@ -320,7 +320,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man) ...@@ -320,7 +320,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)
list_for_each_entry_safe(entry, next, &man->list, head) list_for_each_entry_safe(entry, next, &man->list, head)
vmw_cmdbuf_res_free(man, entry); vmw_cmdbuf_res_free(man, entry);
drm_ht_remove(&man->resources); vmwgfx_ht_remove(&man->resources);
kfree(man); kfree(man);
} }
......
...@@ -1155,7 +1155,7 @@ static void vmw_driver_unload(struct drm_device *dev) ...@@ -1155,7 +1155,7 @@ static void vmw_driver_unload(struct drm_device *dev)
unregister_pm_notifier(&dev_priv->pm_nb); unregister_pm_notifier(&dev_priv->pm_nb);
if (dev_priv->ctx.res_ht_initialized) if (dev_priv->ctx.res_ht_initialized)
drm_ht_remove(&dev_priv->ctx.res_ht); vmwgfx_ht_remove(&dev_priv->ctx.res_ht);
vfree(dev_priv->ctx.cmd_bounce); vfree(dev_priv->ctx.cmd_bounce);
if (dev_priv->enable_fb) { if (dev_priv->enable_fb) {
vmw_fb_off(dev_priv); vmw_fb_off(dev_priv);
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <drm/drm_auth.h> #include <drm/drm_auth.h>
#include <drm/drm_device.h> #include <drm/drm_device.h>
#include <drm/drm_file.h> #include <drm/drm_file.h>
#include <drm/drm_hashtab.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_bo_driver.h>
...@@ -43,6 +42,7 @@ ...@@ -43,6 +42,7 @@
#include "ttm_object.h" #include "ttm_object.h"
#include "vmwgfx_fence.h" #include "vmwgfx_fence.h"
#include "vmwgfx_hashtab.h"
#include "vmwgfx_reg.h" #include "vmwgfx_reg.h"
#include "vmwgfx_validation.h" #include "vmwgfx_validation.h"
...@@ -133,7 +133,7 @@ struct vmw_buffer_object { ...@@ -133,7 +133,7 @@ struct vmw_buffer_object {
*/ */
struct vmw_validate_buffer { struct vmw_validate_buffer {
struct ttm_validate_buffer base; struct ttm_validate_buffer base;
struct drm_hash_item hash; struct vmwgfx_hash_item hash;
bool validate_as_mob; bool validate_as_mob;
}; };
...@@ -406,7 +406,7 @@ struct vmw_ctx_validation_info; ...@@ -406,7 +406,7 @@ struct vmw_ctx_validation_info;
* @ctx: The validation context * @ctx: The validation context
*/ */
struct vmw_sw_context{ struct vmw_sw_context{
struct drm_open_hash res_ht; struct vmwgfx_open_hash res_ht;
bool res_ht_initialized; bool res_ht_initialized;
bool kernel; bool kernel;
struct vmw_fpriv *fp; struct vmw_fpriv *fp;
......
...@@ -4117,7 +4117,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, ...@@ -4117,7 +4117,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
vmw_binding_state_reset(sw_context->staged_bindings); vmw_binding_state_reset(sw_context->staged_bindings);
if (!sw_context->res_ht_initialized) { if (!sw_context->res_ht_initialized) {
ret = drm_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER); ret = vmwgfx_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto out_unlock; goto out_unlock;
......
/*
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. 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 <linux/export.h>
#include <linux/hash.h>
#include <linux/mm.h>
#include <linux/rculist.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <drm/drm_print.h>
#include "vmwgfx_hashtab.h"
int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order)
{
unsigned int size = 1 << order;
ht->order = order;
ht->table = NULL;
if (size <= PAGE_SIZE / sizeof(*ht->table))
ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL);
else
ht->table = vzalloc(array_size(size, sizeof(*ht->table)));
if (!ht->table) {
DRM_ERROR("Out of memory for hash table\n");
return -ENOMEM;
}
return 0;
}
void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key)
{
struct vmwgfx_hash_item *entry;
struct hlist_head *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];
hlist_for_each_entry(entry, h_list, head)
DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
}
static struct hlist_node *vmwgfx_ht_find_key(struct vmwgfx_open_hash *ht, unsigned long key)
{
struct vmwgfx_hash_item *entry;
struct hlist_head *h_list;
unsigned int hashed_key;
hashed_key = hash_long(key, ht->order);
h_list = &ht->table[hashed_key];
hlist_for_each_entry(entry, h_list, head) {
if (entry->key == key)
return &entry->head;
if (entry->key > key)
break;
}
return NULL;
}
static struct hlist_node *vmwgfx_ht_find_key_rcu(struct vmwgfx_open_hash *ht, unsigned long key)
{
struct vmwgfx_hash_item *entry;
struct hlist_head *h_list;
unsigned int hashed_key;
hashed_key = hash_long(key, ht->order);
h_list = &ht->table[hashed_key];
hlist_for_each_entry_rcu(entry, h_list, head) {
if (entry->key == key)
return &entry->head;
if (entry->key > key)
break;
}
return NULL;
}
int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item)
{
struct vmwgfx_hash_item *entry;
struct hlist_head *h_list;
struct hlist_node *parent;
unsigned int hashed_key;
unsigned long key = item->key;
hashed_key = hash_long(key, ht->order);
h_list = &ht->table[hashed_key];
parent = NULL;
hlist_for_each_entry(entry, h_list, head) {
if (entry->key == key)
return -EINVAL;
if (entry->key > key)
break;
parent = &entry->head;
}
if (parent)
hlist_add_behind_rcu(&item->head, parent);
else
hlist_add_head_rcu(&item->head, h_list);
return 0;
}
/*
* Just insert an item and return any "bits" bit key that hasn't been
* used before.
*/
int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item,
unsigned long seed, int bits, int shift,
unsigned long add)
{
int ret;
unsigned long mask = (1UL << bits) - 1;
unsigned long first, unshifted_key;
unshifted_key = hash_long(seed, bits);
first = unshifted_key;
do {
item->key = (unshifted_key << shift) + add;
ret = vmwgfx_ht_insert_item(ht, item);
if (ret)
unshifted_key = (unshifted_key + 1) & mask;
} while (ret && (unshifted_key != first));
if (ret) {
DRM_ERROR("Available key bit space exhausted\n");
return -EINVAL;
}
return 0;
}
int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key,
struct vmwgfx_hash_item **item)
{
struct hlist_node *list;
list = vmwgfx_ht_find_key_rcu(ht, key);
if (!list)
return -EINVAL;
*item = hlist_entry(list, struct vmwgfx_hash_item, head);
return 0;
}
int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key)
{
struct hlist_node *list;
list = vmwgfx_ht_find_key(ht, key);
if (list) {
hlist_del_init_rcu(list);
return 0;
}
return -EINVAL;
}
int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item)
{
hlist_del_init_rcu(&item->head);
return 0;
}
void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht)
{
if (ht->table) {
kvfree(ht->table);
ht->table = NULL;
}
}
/*
* Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. 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>
*/
/*
* TODO: Replace this hashtable with Linux' generic implementation
* from <linux/hashtable.h>.
*/
#ifndef VMWGFX_HASHTAB_H
#define VMWGFX_HASHTAB_H
#include <linux/list.h>
#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
struct vmwgfx_hash_item {
struct hlist_node head;
unsigned long key;
};
struct vmwgfx_open_hash {
struct hlist_head *table;
u8 order;
};
int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order);
int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item);
int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item,
unsigned long seed, int bits, int shift,
unsigned long add);
int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key,
struct vmwgfx_hash_item **item);
void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key);
int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key);
int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item);
void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht);
/*
* RCU-safe interface
*
* The user of this API needs to make sure that two or more instances of the
* hash table manipulation functions are never run simultaneously.
* The lookup function vmwgfx_ht_find_item_rcu may, however, run simultaneously
* with any of the manipulation functions as long as it's called from within
* an RCU read-locked section.
*/
#define vmwgfx_ht_insert_item_rcu vmwgfx_ht_insert_item
#define vmwgfx_ht_just_insert_please_rcu vmwgfx_ht_just_insert_please
#define vmwgfx_ht_remove_key_rcu vmwgfx_ht_remove_key
#define vmwgfx_ht_remove_item_rcu vmwgfx_ht_remove_item
#define vmwgfx_ht_find_item_rcu vmwgfx_ht_find_item
#endif
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
*/ */
struct vmw_validation_bo_node { struct vmw_validation_bo_node {
struct ttm_validate_buffer base; struct ttm_validate_buffer base;
struct drm_hash_item hash; struct vmwgfx_hash_item hash;
unsigned int coherent_count; unsigned int coherent_count;
u32 as_mob : 1; u32 as_mob : 1;
u32 cpu_blit : 1; u32 cpu_blit : 1;
...@@ -72,7 +72,7 @@ struct vmw_validation_bo_node { ...@@ -72,7 +72,7 @@ struct vmw_validation_bo_node {
*/ */
struct vmw_validation_res_node { struct vmw_validation_res_node {
struct list_head head; struct list_head head;
struct drm_hash_item hash; struct vmwgfx_hash_item hash;
struct vmw_resource *res; struct vmw_resource *res;
struct vmw_buffer_object *new_backup; struct vmw_buffer_object *new_backup;
unsigned long new_backup_offset; unsigned long new_backup_offset;
...@@ -184,9 +184,9 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx, ...@@ -184,9 +184,9 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx,
return NULL; return NULL;
if (ctx->ht) { if (ctx->ht) {
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
if (!drm_ht_find_item(ctx->ht, (unsigned long) vbo, &hash)) if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) vbo, &hash))
bo_node = container_of(hash, typeof(*bo_node), hash); bo_node = container_of(hash, typeof(*bo_node), hash);
} else { } else {
struct vmw_validation_bo_node *entry; struct vmw_validation_bo_node *entry;
...@@ -221,9 +221,9 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx, ...@@ -221,9 +221,9 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx,
return NULL; return NULL;
if (ctx->ht) { if (ctx->ht) {
struct drm_hash_item *hash; struct vmwgfx_hash_item *hash;
if (!drm_ht_find_item(ctx->ht, (unsigned long) res, &hash)) if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) res, &hash))
res_node = container_of(hash, typeof(*res_node), hash); res_node = container_of(hash, typeof(*res_node), hash);
} else { } else {
struct vmw_validation_res_node *entry; struct vmw_validation_res_node *entry;
...@@ -280,7 +280,7 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, ...@@ -280,7 +280,7 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx,
if (ctx->ht) { if (ctx->ht) {
bo_node->hash.key = (unsigned long) vbo; bo_node->hash.key = (unsigned long) vbo;
ret = drm_ht_insert_item(ctx->ht, &bo_node->hash); ret = vmwgfx_ht_insert_item(ctx->ht, &bo_node->hash);
if (ret) { if (ret) {
DRM_ERROR("Failed to initialize a buffer " DRM_ERROR("Failed to initialize a buffer "
"validation entry.\n"); "validation entry.\n");
...@@ -335,7 +335,7 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx, ...@@ -335,7 +335,7 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
if (ctx->ht) { if (ctx->ht) {
node->hash.key = (unsigned long) res; node->hash.key = (unsigned long) res;
ret = drm_ht_insert_item(ctx->ht, &node->hash); ret = vmwgfx_ht_insert_item(ctx->ht, &node->hash);
if (ret) { if (ret) {
DRM_ERROR("Failed to initialize a resource validation " DRM_ERROR("Failed to initialize a resource validation "
"entry.\n"); "entry.\n");
...@@ -688,13 +688,13 @@ void vmw_validation_drop_ht(struct vmw_validation_context *ctx) ...@@ -688,13 +688,13 @@ void vmw_validation_drop_ht(struct vmw_validation_context *ctx)
return; return;
list_for_each_entry(entry, &ctx->bo_list, base.head) list_for_each_entry(entry, &ctx->bo_list, base.head)
(void) drm_ht_remove_item(ctx->ht, &entry->hash); (void) vmwgfx_ht_remove_item(ctx->ht, &entry->hash);
list_for_each_entry(val, &ctx->resource_list, head) list_for_each_entry(val, &ctx->resource_list, head)
(void) drm_ht_remove_item(ctx->ht, &val->hash); (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash);
list_for_each_entry(val, &ctx->resource_ctx_list, head) list_for_each_entry(val, &ctx->resource_ctx_list, head)
(void) drm_ht_remove_item(ctx->ht, &val->hash); (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash);
ctx->ht = NULL; ctx->ht = NULL;
} }
......
...@@ -31,9 +31,10 @@ ...@@ -31,9 +31,10 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/ww_mutex.h> #include <linux/ww_mutex.h>
#include <drm/drm_hashtab.h>
#include <drm/ttm/ttm_execbuf_util.h> #include <drm/ttm/ttm_execbuf_util.h>
#include "vmwgfx_hashtab.h"
#define VMW_RES_DIRTY_NONE 0 #define VMW_RES_DIRTY_NONE 0
#define VMW_RES_DIRTY_SET BIT(0) #define VMW_RES_DIRTY_SET BIT(0)
#define VMW_RES_DIRTY_CLEAR BIT(1) #define VMW_RES_DIRTY_CLEAR BIT(1)
...@@ -73,7 +74,7 @@ struct vmw_validation_mem { ...@@ -73,7 +74,7 @@ struct vmw_validation_mem {
* @total_mem: Amount of reserved memory. * @total_mem: Amount of reserved memory.
*/ */
struct vmw_validation_context { struct vmw_validation_context {
struct drm_open_hash *ht; struct vmwgfx_open_hash *ht;
struct list_head resource_list; struct list_head resource_list;
struct list_head resource_ctx_list; struct list_head resource_ctx_list;
struct list_head bo_list; struct list_head bo_list;
...@@ -151,7 +152,7 @@ vmw_validation_set_val_mem(struct vmw_validation_context *ctx, ...@@ -151,7 +152,7 @@ vmw_validation_set_val_mem(struct vmw_validation_context *ctx,
* available at validation context declaration time * available at validation context declaration time
*/ */
static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx, static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx,
struct drm_open_hash *ht) struct vmwgfx_open_hash *ht)
{ {
ctx->ht = ht; ctx->ht = ht;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment