@@ -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);
@@ -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;
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 <tzimmermann@suse.de> --- drivers/gpu/drm/ttm/ttm_global.c | 98 ++++++++++++++++++++++++++++++++ include/drm/ttm/ttm_global.h | 22 +++++++ 2 files changed, 120 insertions(+)