The data structure struct ttm_global_item is a replacement for struct
drm_global_item. While struct drm_global_item depends on global data
instances, struct ttm_global_item allows drivers to use their own privat
instances.

Signed-off-by: Thomas Zimmermann <tzimmerm...@suse.de>
---
 drivers/gpu/drm/ttm/ttm_global.c | 98 ++++++++++++++++++++++++++++++++
 include/drm/ttm/ttm_global.h     | 22 +++++++
 2 files changed, 120 insertions(+)

diff --git a/drivers/gpu/drm/ttm/ttm_global.c b/drivers/gpu/drm/ttm/ttm_global.c
index ca9da0a46147..1e5c2f5eeca0 100644
--- a/drivers/gpu/drm/ttm/ttm_global.c
+++ b/drivers/gpu/drm/ttm/ttm_global.c
@@ -31,6 +31,104 @@
 #include <drm/ttm/ttm_memory.h>
 #include <linux/kernel.h>
 
+/*
+ * struct ttm_global_item
+ */
+
+struct ttm_global_item {
+       struct mutex mutex;
+       void *object;
+       int refcount;
+};
+
+#define TTM_GLOBAL_ITEM_INIT(name_) { \
+       .mutex = __MUTEX_INITIALIZER(name_.mutex), \
+       .object = NULL, \
+       .refcount = 0 }
+
+#define DEFINE_TTM_GLOBAL_ITEM_ARRAY(name_) \
+       struct ttm_global_item name_[TTM_NUM_GLOBAL_TYPES] = { \
+               [0] = TTM_GLOBAL_ITEM_INIT(name_[0]), \
+               [1] = TTM_GLOBAL_ITEM_INIT(name_[0]) \
+       }
+
+/**
+ * ttm_global_item_ref - Initialize and acquire reference to a global TTM item
+ *
+ * @items: Array of global TTM items
+ * @ref: Object for initialization
+ * @return Zero on success, or a negative error code otherwise.
+ *
+ * This initializes a TTM item by allocating memory and calling the
+ * .init() hook. Further calls will increase the reference count for
+ * that item.
+ */
+static int ttm_global_item_ref(
+       struct ttm_global_item items[TTM_NUM_GLOBAL_TYPES],
+       struct ttm_global_ref *ref)
+{
+       struct ttm_global_item *item = &items[ref->global_type];
+       int ret = 0;
+
+       mutex_lock(&item->mutex);
+       if (item->refcount == 0) {
+               ref->object = kzalloc(ref->size, GFP_KERNEL);
+               if (unlikely(ref->object == NULL)) {
+                       ret = -ENOMEM;
+                       goto error_mutex_unlock;
+               }
+               ret = ref->init(ref);
+               if (unlikely(ret != 0))
+                       goto error_kfree;
+
+               item->object = ref->object;
+       } else {
+               ref->object = item->object;
+       }
+
+       ++item->refcount;
+       mutex_unlock(&item->mutex);
+
+       return 0;
+
+error_kfree:
+       kfree(ref->object);
+       ref->object = NULL;
+error_mutex_unlock:
+       mutex_unlock(&item->mutex);
+       return ret;
+}
+
+/**
+ * ttm_global_item_unref - Drop reference to global TTM item
+ *
+ * @items: Array of global TTM items
+ * @ref: Object being removed
+ *
+ * Drops a reference to the global TTM item and eventually call the
+ * release() hook. The allocated object should be dropped in the
+ * release() hook or before calling this function
+ */
+static void ttm_global_item_unref(
+       struct ttm_global_item items[TTM_NUM_GLOBAL_TYPES],
+       struct ttm_global_ref *ref)
+{
+       struct ttm_global_item *item = &items[ref->global_type];
+
+       mutex_lock(&item->mutex);
+       BUG_ON(item->refcount == 0);
+       BUG_ON(ref->object != item->object);
+       if (--item->refcount == 0) {
+               ref->release(ref);
+               item->object = NULL;
+       }
+       mutex_unlock(&item->mutex);
+}
+
+/*
+ * struct ttm_global
+ */
+
 static int ttm_global_init_mem(struct drm_global_reference *ref)
 {
        BUG_ON(!ref->object);
diff --git a/include/drm/ttm/ttm_global.h b/include/drm/ttm/ttm_global.h
index 06e791499f87..9aa0ddbbe2ef 100644
--- a/include/drm/ttm/ttm_global.h
+++ b/include/drm/ttm/ttm_global.h
@@ -29,6 +29,28 @@
 #define _TTM_GLOBAL_H_
 
 #include <drm/drm_global.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+/**
+ * enum ttm_global_types - Enumerates types of global TTM state
+ */
+enum ttm_global_types {
+       TTM_GLOBAL_MEM = 0,
+       TTM_GLOBAL_BO,
+       TTM_NUM_GLOBAL_TYPES
+};
+
+/**
+ * struct ttm_global_ref - References global TTM item
+ */
+struct ttm_global_ref {
+       enum ttm_global_types global_type;
+       size_t size;
+       void *object;
+       int (*init) (struct ttm_global_ref *);
+       void (*release) (struct ttm_global_ref *);
+};
 
 struct ttm_bo_global;
 
-- 
2.19.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to