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@xxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel