OSDN Git Service

drm/vmwgfx: Refactor resource validation hashtable to use linux/hashtable implementation.
authorMaaz Mombasawala <mombasawalam@vmware.com>
Sat, 22 Oct 2022 04:02:24 +0000 (00:02 -0400)
committerZack Rusin <zackr@vmware.com>
Tue, 25 Oct 2022 16:42:20 +0000 (12:42 -0400)
Vmwgfx's hashtab implementation needs to be replaced with linux/hashtable
to reduce maintenence burden.
As part of this effort, refactor the res_ht hashtable used for resource
validation during execbuf execution to use linux/hashtable implementation.
This also refactors vmw_validation_context to use vmw_sw_context as the
container for the hashtable, whereas before it used a vmwgfx_open_hash
directly. This makes vmw_validation_context less generic, but there is
no functional change since res_ht is the only instance where validation
context used a hashtable in vmwgfx driver.

Signed-off-by: Maaz Mombasawala <mombasawalam@vmware.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Zack Rusin <zackr@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-6-zack@kde.org
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
drivers/gpu/drm/vmwgfx/vmwgfx_validation.h

index 13b9027..8d77e79 100644 (file)
@@ -830,6 +830,22 @@ static void vmw_write_driver_id(struct vmw_private *dev)
        }
 }
 
+static void vmw_sw_context_init(struct vmw_private *dev_priv)
+{
+       struct vmw_sw_context *sw_context = &dev_priv->ctx;
+
+       hash_init(sw_context->res_ht);
+}
+
+static void vmw_sw_context_fini(struct vmw_private *dev_priv)
+{
+       struct vmw_sw_context *sw_context = &dev_priv->ctx;
+
+       vfree(sw_context->cmd_bounce);
+       if (sw_context->staged_bindings)
+               vmw_binding_state_free(sw_context->staged_bindings);
+}
+
 static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
 {
        int ret;
@@ -839,6 +855,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
 
        dev_priv->drm.dev_private = dev_priv;
 
+       vmw_sw_context_init(dev_priv);
+
        mutex_init(&dev_priv->cmdbuf_mutex);
        mutex_init(&dev_priv->binding_mutex);
        spin_lock_init(&dev_priv->resource_lock);
@@ -1168,9 +1186,7 @@ static void vmw_driver_unload(struct drm_device *dev)
 
        unregister_pm_notifier(&dev_priv->pm_nb);
 
-       if (dev_priv->ctx.res_ht_initialized)
-               vmwgfx_ht_remove(&dev_priv->ctx.res_ht);
-       vfree(dev_priv->ctx.cmd_bounce);
+       vmw_sw_context_fini(dev_priv);
        if (dev_priv->enable_fb) {
                vmw_fb_off(dev_priv);
                vmw_fb_close(dev_priv);
@@ -1198,8 +1214,6 @@ static void vmw_driver_unload(struct drm_device *dev)
                vmw_irq_uninstall(&dev_priv->drm);
 
        ttm_object_device_release(&dev_priv->tdev);
-       if (dev_priv->ctx.staged_bindings)
-               vmw_binding_state_free(dev_priv->ctx.staged_bindings);
 
        for (i = vmw_res_context; i < vmw_res_max; ++i)
                idr_destroy(&dev_priv->res_idr[i]);
index 09e2d73..d87aeed 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <linux/suspend.h>
 #include <linux/sync_file.h>
+#include <linux/hashtable.h>
 
 #include <drm/drm_auth.h>
 #include <drm/drm_device.h>
@@ -93,6 +94,7 @@
 #define VMW_RES_STREAM ttm_driver_type2
 #define VMW_RES_FENCE ttm_driver_type3
 #define VMW_RES_SHADER ttm_driver_type4
+#define VMW_RES_HT_ORDER 12
 
 #define MKSSTAT_CAPACITY_LOG2 5U
 #define MKSSTAT_CAPACITY (1U << MKSSTAT_CAPACITY_LOG2)
@@ -425,8 +427,7 @@ struct vmw_ctx_validation_info;
  * @ctx: The validation context
  */
 struct vmw_sw_context{
-       struct vmwgfx_open_hash res_ht;
-       bool res_ht_initialized;
+       DECLARE_HASHTABLE(res_ht, VMW_RES_HT_ORDER);
        bool kernel;
        struct vmw_fpriv *fp;
        struct drm_file *filp;
index f085dbd..c943ab8 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
  *
- * Copyright 2009 - 2015 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2009 - 2022 VMware, Inc., Palo Alto, CA., USA
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
@@ -25,6 +25,7 @@
  *
  **************************************************************************/
 #include <linux/sync_file.h>
+#include <linux/hashtable.h>
 
 #include "vmwgfx_drv.h"
 #include "vmwgfx_reg.h"
@@ -34,7 +35,6 @@
 #include "vmwgfx_binding.h"
 #include "vmwgfx_mksstat.h"
 
-#define VMW_RES_HT_ORDER 12
 
 /*
  * Helper macro to get dx_ctx_node if available otherwise print an error
@@ -4101,7 +4101,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
        int ret;
        int32_t out_fence_fd = -1;
        struct sync_file *sync_file = NULL;
-       DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1);
+       DECLARE_VAL_CONTEXT(val_ctx, sw_context, 1);
 
        if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) {
                out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
@@ -4164,14 +4164,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
        if (sw_context->staged_bindings)
                vmw_binding_state_reset(sw_context->staged_bindings);
 
-       if (!sw_context->res_ht_initialized) {
-               ret = vmwgfx_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER);
-               if (unlikely(ret != 0))
-                       goto out_unlock;
-
-               sw_context->res_ht_initialized = true;
-       }
-
        INIT_LIST_HEAD(&sw_context->staged_cmd_res);
        sw_context->ctx = &val_ctx;
        ret = vmw_execbuf_tie_context(dev_priv, sw_context, dx_context_handle);
index f468910..f5c4a40 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /**************************************************************************
  *
- * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
+ * Copyright © 2018 - 2022 VMware, Inc., Palo Alto, CA., USA
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -180,11 +180,16 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx,
        if (!ctx->merge_dups)
                return NULL;
 
-       if (ctx->ht) {
+       if (ctx->sw_context) {
                struct vmwgfx_hash_item *hash;
+               unsigned long key = (unsigned long) vbo;
 
-               if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) vbo, &hash))
-                       bo_node = container_of(hash, typeof(*bo_node), hash);
+               hash_for_each_possible_rcu(ctx->sw_context->res_ht, hash, head, key) {
+                       if (hash->key == key) {
+                               bo_node = container_of(hash, typeof(*bo_node), hash);
+                               break;
+                       }
+               }
        } else {
                struct  vmw_validation_bo_node *entry;
 
@@ -217,11 +222,16 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx,
        if (!ctx->merge_dups)
                return NULL;
 
-       if (ctx->ht) {
+       if (ctx->sw_context) {
                struct vmwgfx_hash_item *hash;
+               unsigned long key = (unsigned long) res;
 
-               if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) res, &hash))
-                       res_node = container_of(hash, typeof(*res_node), hash);
+               hash_for_each_possible_rcu(ctx->sw_context->res_ht, hash, head, key) {
+                       if (hash->key == key) {
+                               res_node = container_of(hash, typeof(*res_node), hash);
+                               break;
+                       }
+               }
        } else {
                struct  vmw_validation_res_node *entry;
 
@@ -269,20 +279,15 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx,
                }
        } else {
                struct ttm_validate_buffer *val_buf;
-               int ret;
 
                bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node));
                if (!bo_node)
                        return -ENOMEM;
 
-               if (ctx->ht) {
+               if (ctx->sw_context) {
                        bo_node->hash.key = (unsigned long) vbo;
-                       ret = vmwgfx_ht_insert_item(ctx->ht, &bo_node->hash);
-                       if (ret) {
-                               DRM_ERROR("Failed to initialize a buffer "
-                                         "validation entry.\n");
-                               return ret;
-                       }
+                       hash_add_rcu(ctx->sw_context->res_ht, &bo_node->hash.head,
+                               bo_node->hash.key);
                }
                val_buf = &bo_node->base;
                val_buf->bo = ttm_bo_get_unless_zero(&vbo->base);
@@ -316,7 +321,6 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
                                bool *first_usage)
 {
        struct vmw_validation_res_node *node;
-       int ret;
 
        node = vmw_validation_find_res_dup(ctx, res);
        if (node) {
@@ -330,14 +334,9 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
                return -ENOMEM;
        }
 
-       if (ctx->ht) {
+       if (ctx->sw_context) {
                node->hash.key = (unsigned long) res;
-               ret = vmwgfx_ht_insert_item(ctx->ht, &node->hash);
-               if (ret) {
-                       DRM_ERROR("Failed to initialize a resource validation "
-                                 "entry.\n");
-                       return ret;
-               }
+               hash_add_rcu(ctx->sw_context->res_ht, &node->hash.head, node->hash.key);
        }
        node->res = vmw_resource_reference_unless_doomed(res);
        if (!node->res)
@@ -681,19 +680,19 @@ void vmw_validation_drop_ht(struct vmw_validation_context *ctx)
        struct vmw_validation_bo_node *entry;
        struct vmw_validation_res_node *val;
 
-       if (!ctx->ht)
+       if (!ctx->sw_context)
                return;
 
        list_for_each_entry(entry, &ctx->bo_list, base.head)
-               (void) vmwgfx_ht_remove_item(ctx->ht, &entry->hash);
+               hash_del_rcu(&entry->hash.head);
 
        list_for_each_entry(val, &ctx->resource_list, head)
-               (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash);
+               hash_del_rcu(&val->hash.head);
 
        list_for_each_entry(val, &ctx->resource_ctx_list, head)
-               (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash);
+               hash_del_rcu(&entry->hash.head);
 
-       ctx->ht = NULL;
+       ctx->sw_context = NULL;
 }
 
 /**
index f21df05..ab9ec22 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 OR MIT */
 /**************************************************************************
  *
- * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
+ * Copyright © 2018 - 2022 VMware, Inc., Palo Alto, CA., USA
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
 #define _VMWGFX_VALIDATION_H_
 
 #include <linux/list.h>
+#include <linux/hashtable.h>
 #include <linux/ww_mutex.h>
 
 #include <drm/ttm/ttm_execbuf_util.h>
 
-#include "vmwgfx_hashtab.h"
-
 #define VMW_RES_DIRTY_NONE 0
 #define VMW_RES_DIRTY_SET BIT(0)
 #define VMW_RES_DIRTY_CLEAR BIT(1)
@@ -59,7 +58,7 @@
  * @total_mem: Amount of reserved memory.
  */
 struct vmw_validation_context {
-       struct vmwgfx_open_hash *ht;
+       struct vmw_sw_context *sw_context;
        struct list_head resource_list;
        struct list_head resource_ctx_list;
        struct list_head bo_list;
@@ -82,16 +81,16 @@ struct vmw_fence_obj;
 /**
  * DECLARE_VAL_CONTEXT - Declare a validation context with initialization
  * @_name: The name of the variable
- * @_ht: The hash table used to find dups or NULL if none
+ * @_sw_context: Contains the hash table used to find dups or NULL if none
  * @_merge_dups: Whether to merge duplicate buffer object- or resource
  * entries. If set to true, ideally a hash table pointer should be supplied
  * as well unless the number of resources and buffer objects per validation
  * is known to be very small
  */
 #endif
-#define DECLARE_VAL_CONTEXT(_name, _ht, _merge_dups)                   \
+#define DECLARE_VAL_CONTEXT(_name, _sw_context, _merge_dups)           \
        struct vmw_validation_context _name =                           \
-       { .ht = _ht,                                                    \
+       { .sw_context = _sw_context,                                    \
          .resource_list = LIST_HEAD_INIT((_name).resource_list),       \
          .resource_ctx_list = LIST_HEAD_INIT((_name).resource_ctx_list), \
          .bo_list = LIST_HEAD_INIT((_name).bo_list),                   \
@@ -115,19 +114,6 @@ vmw_validation_has_bos(struct vmw_validation_context *ctx)
 }
 
 /**
- * vmw_validation_set_ht - Register a hash table for duplicate finding
- * @ctx: The validation context
- * @ht: Pointer to a hash table to use for duplicate finding
- * This function is intended to be used if the hash table wasn't
- * available at validation context declaration time
- */
-static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx,
-                                        struct vmwgfx_open_hash *ht)
-{
-       ctx->ht = ht;
-}
-
-/**
  * vmw_validation_bo_reserve - Reserve buffer objects registered with a
  * validation context
  * @ctx: The validation context