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

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
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -646,6 +646,17 @@ See drivers/gpu/drm/amd/display/TODO for tasks.

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
==========

+1 −1
Original line number Diff line number Diff line
# 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_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
	    vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \
+26 −26
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ struct ttm_object_file {
	struct ttm_object_device *tdev;
	spinlock_t lock;
	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;
};

@@ -91,7 +91,7 @@ struct ttm_object_file {

struct ttm_object_device {
	spinlock_t object_lock;
	struct drm_open_hash object_hash;
	struct vmwgfx_open_hash object_hash;
	atomic_t object_count;
	struct ttm_mem_global *mem_glob;
	struct dma_buf_ops ops;
@@ -123,7 +123,7 @@ struct ttm_object_device {

struct ttm_ref_object {
	struct rcu_head rcu_head;
	struct drm_hash_item hash;
	struct vmwgfx_hash_item hash;
	struct list_head head;
	struct kref kref;
	enum ttm_ref_type ref_type;
@@ -247,12 +247,12 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
struct ttm_base_object *
ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
{
	struct drm_hash_item *hash;
	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
	struct vmwgfx_hash_item *hash;
	struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
	int ret;

	rcu_read_lock();
	ret = drm_ht_find_item_rcu(ht, key, &hash);
	ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
	if (ret) {
		rcu_read_unlock();
		return NULL;
@@ -267,12 +267,12 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
					       uint32_t key)
{
	struct ttm_base_object *base = NULL;
	struct drm_hash_item *hash;
	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
	struct vmwgfx_hash_item *hash;
	struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
	int ret;

	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)) {
		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)
bool ttm_ref_object_exists(struct ttm_object_file *tfile,
			   struct ttm_base_object *base)
{
	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
	struct drm_hash_item *hash;
	struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
	struct vmwgfx_hash_item *hash;
	struct ttm_ref_object *ref;

	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;

	/*
@@ -349,9 +349,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
		       enum ttm_ref_type ref_type, bool *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 drm_hash_item *hash;
	struct vmwgfx_hash_item *hash;
	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
	struct ttm_operation_ctx ctx = {
		.interruptible = false,
@@ -367,7 +367,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,

	while (ret == -EINVAL) {
		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) {
			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
@@ -398,7 +398,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
		kref_init(&ref->kref);

		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)) {
			list_add_tail(&ref->head, &tfile->ref_list);
@@ -426,11 +426,11 @@ ttm_ref_object_release(struct kref *kref)
	    container_of(kref, struct ttm_ref_object, kref);
	struct ttm_base_object *base = ref->obj;
	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;

	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);
	spin_unlock(&tfile->lock);

@@ -446,13 +446,13 @@ ttm_ref_object_release(struct kref *kref)
int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
			      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 drm_hash_item *hash;
	struct vmwgfx_hash_item *hash;
	int ret;

	spin_lock(&tfile->lock);
	ret = drm_ht_find_item(ht, key, &hash);
	ret = vmwgfx_ht_find_item(ht, key, &hash);
	if (unlikely(ret != 0)) {
		spin_unlock(&tfile->lock);
		return -EINVAL;
@@ -486,7 +486,7 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)

	spin_unlock(&tfile->lock);
	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);
}
@@ -508,7 +508,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
	INIT_LIST_HEAD(&tfile->ref_list);

	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) {
			j = i;
			goto out_err;
@@ -518,7 +518,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
	return tfile;
out_err:
	for (i = 0; i < j; ++i)
		drm_ht_remove(&tfile->ref_hash[i]);
		vmwgfx_ht_remove(&tfile->ref_hash[i]);

	kfree(tfile);

@@ -539,7 +539,7 @@ ttm_object_device_init(struct ttm_mem_global *mem_glob,
	tdev->mem_glob = mem_glob;
	spin_lock_init(&tdev->object_lock);
	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)
		goto out_no_object_hash;

@@ -564,7 +564,7 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev)

	WARN_ON_ONCE(!idr_is_empty(&tdev->idr));
	idr_destroy(&tdev->idr);
	drm_ht_remove(&tdev->object_hash);
	vmwgfx_ht_remove(&tdev->object_hash);

	kfree(tdev);
}
+1 −2
Original line number Diff line number Diff line
@@ -42,9 +42,8 @@
#include <linux/list.h>
#include <linux/rcupdate.h>

#include <drm/drm_hashtab.h>

#include "ttm_memory.h"
#include "vmwgfx_hashtab.h"

/**
 * enum ttm_ref_type
+12 −12
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@
 */
struct vmw_cmdbuf_res {
	struct vmw_resource *res;
	struct drm_hash_item hash;
	struct vmwgfx_hash_item hash;
	struct list_head head;
	enum vmw_cmdbuf_res_state state;
	struct vmw_cmdbuf_res_manager *man;
@@ -59,7 +59,7 @@ struct vmw_cmdbuf_res {
 * @resources and @list are protected by the cmdbuf mutex for now.
 */
struct vmw_cmdbuf_res_manager {
	struct drm_open_hash resources;
	struct vmwgfx_open_hash resources;
	struct list_head list;
	struct vmw_private *dev_priv;
};
@@ -81,11 +81,11 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
		      enum vmw_cmdbuf_res_type res_type,
		      u32 user_key)
{
	struct drm_hash_item *hash;
	struct vmwgfx_hash_item *hash;
	int ret;
	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))
		return ERR_PTR(ret);

@@ -105,7 +105,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man,
				struct vmw_cmdbuf_res *entry)
{
	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);
	kfree(entry);
}
@@ -167,7 +167,7 @@ void vmw_cmdbuf_res_revert(struct list_head *list)
			vmw_cmdbuf_res_free(entry->man, entry);
			break;
		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);
			list_move_tail(&entry->head, &entry->man->list);
			entry->state = VMW_CMDBUF_RES_COMMITTED;
@@ -206,7 +206,7 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
		return -ENOMEM;

	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)) {
		kfree(cres);
		goto out_invalid_key;
@@ -244,10 +244,10 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
			  struct vmw_resource **res_p)
{
	struct vmw_cmdbuf_res *entry;
	struct drm_hash_item *hash;
	struct vmwgfx_hash_item *hash;
	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);
	if (likely(ret != 0))
		return -EINVAL;
@@ -260,7 +260,7 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
		*res_p = NULL;
		break;
	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);
		entry->state = VMW_CMDBUF_RES_DEL;
		list_add_tail(&entry->head, list);
@@ -295,7 +295,7 @@ vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv)

	man->dev_priv = dev_priv;
	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)
		return 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)
		vmw_cmdbuf_res_free(man, entry);

	drm_ht_remove(&man->resources);
	vmwgfx_ht_remove(&man->resources);
	kfree(man);
}

Loading