From c7e1c9dd9a6540625baf71a8d2706f10a91728d8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Tigeot?= Date: Sat, 5 Oct 2013 21:59:04 +0200 Subject: [PATCH] drm: Remove the drm_gem_names subsystem And use the original idr code from Linux 3.8 instead --- sys/dev/drm/drm/Makefile | 1 - sys/dev/drm/drm_gem.c | 365 ++++++++++++++++-------- sys/dev/drm/drm_gem_names.c | 211 -------------- sys/dev/drm/include/drm/drmP.h | 19 +- sys/dev/drm/include/drm/drm_crtc.h | 1 - sys/dev/drm/include/drm/drm_gem_names.h | 63 ---- 6 files changed, 261 insertions(+), 399 deletions(-) delete mode 100644 sys/dev/drm/drm_gem_names.c delete mode 100644 sys/dev/drm/include/drm/drm_gem_names.h diff --git a/sys/dev/drm/drm/Makefile b/sys/dev/drm/drm/Makefile index dfcaaac2f4..8e0f024e0d 100644 --- a/sys/dev/drm/drm/Makefile +++ b/sys/dev/drm/drm/Makefile @@ -18,7 +18,6 @@ SRCS = \ drm_fb_helper.c \ drm_fops.c \ drm_gem.c \ - drm_gem_names.c \ drm_global.c \ drm_hashtab.c \ drm_ioctl.c \ diff --git a/sys/dev/drm/drm_gem.c b/sys/dev/drm/drm_gem.c index bcdddcbf78..f038e33aa8 100644 --- a/sys/dev/drm/drm_gem.c +++ b/sys/dev/drm/drm_gem.c @@ -60,33 +60,44 @@ #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16) #endif +/** + * Initialize the GEM device fields + */ + int drm_gem_init(struct drm_device *dev) { struct drm_gem_mm *mm; - drm_gem_names_init(&dev->object_names); + spin_init(&dev->object_name_lock); + idr_init(&dev->object_name_idr); + mm = kmalloc(sizeof(*mm), DRM_MEM_DRIVER, M_WAITOK); + if (!mm) { + DRM_ERROR("out of memory\n"); + return -ENOMEM; + } + dev->mm_private = mm; - if (drm_ht_create(&mm->offset_hash, 19) != 0) { + + if (drm_ht_create(&mm->offset_hash, 12)) { drm_free(mm, DRM_MEM_DRIVER); - return (ENOMEM); + return -ENOMEM; } + mm->idxunr = new_unrhdr(0, DRM_GEM_MAX_IDX, NULL); - return (0); + return 0; } void drm_gem_destroy(struct drm_device *dev) { - struct drm_gem_mm *mm; + struct drm_gem_mm *mm = dev->mm_private; - mm = dev->mm_private; - dev->mm_private = NULL; drm_ht_remove(&mm->offset_hash); delete_unrhdr(mm->idxunr); drm_free(mm, DRM_MEM_DRIVER); - drm_gem_names_fini(&dev->object_names); + dev->mm_private = NULL; } /** @@ -171,183 +182,303 @@ drm_gem_object_free(struct kref *kref) dev->driver->gem_free_object(obj); } -void -drm_gem_object_handle_free(struct drm_gem_object *obj) +static void drm_gem_object_ref_bug(struct kref *list_kref) { - struct drm_device *dev; - struct drm_gem_object *obj1; + panic("BUG"); +} - dev = obj->dev; - if (obj->name != 0) { - obj1 = drm_gem_names_remove(&dev->object_names, obj->name); +/** + * Called after the last handle to the object has been closed + * + * Removes any name for the object. Note that this must be + * called before drm_gem_object_free or we'll be touching + * freed memory + */ +void drm_gem_object_handle_free(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + + /* Remove any name for this object */ + spin_lock(&dev->object_name_lock); + if (obj->name) { + idr_remove(&dev->object_name_idr, obj->name); obj->name = 0; - drm_gem_object_unreference(obj1); + spin_unlock(&dev->object_name_lock); + /* + * The object name held a reference to this object, drop + * that now. + * + * This cannot be the last reference, since the handle holds one too. + */ + kref_put(&obj->refcount, drm_gem_object_ref_bug); + } else + spin_unlock(&dev->object_name_lock); + +} + +/** + * Removes the mapping from handle to filp for this object. + */ +int +drm_gem_handle_delete(struct drm_file *filp, u32 handle) +{ + struct drm_device *dev; + struct drm_gem_object *obj; + + /* This is gross. The idr system doesn't let us try a delete and + * return an error code. It just spews if you fail at deleting. + * So, we have to grab a lock around finding the object and then + * doing the delete on it and dropping the refcount, or the user + * could race us to double-decrement the refcount and cause a + * use-after-free later. Given the frequency of our handle lookups, + * we may want to use ida for number allocation and a hash table + * for the pointers, anyway. + */ + spin_lock(&filp->table_lock); + + /* Check if we currently have a reference on the object */ + obj = idr_find(&filp->object_idr, handle); + if (obj == NULL) { + spin_unlock(&filp->table_lock); + return -EINVAL; } + dev = obj->dev; + + /* Release reference and decrement refcount. */ + idr_remove(&filp->object_idr, handle); + spin_unlock(&filp->table_lock); + + if (dev->driver->gem_close_object) + dev->driver->gem_close_object(obj, filp); + drm_gem_object_handle_unreference_unlocked(obj); + + return 0; } +/** + * Create a handle for this object. This adds a handle reference + * to the object, which includes a regular reference count. Callers + * will likely want to dereference the object afterwards. + */ int -drm_gem_handle_create(struct drm_file *file_priv, struct drm_gem_object *obj, - uint32_t *handle) +drm_gem_handle_create(struct drm_file *file_priv, + struct drm_gem_object *obj, + u32 *handlep) { struct drm_device *dev = obj->dev; int ret; - ret = drm_gem_name_create(&file_priv->object_names, obj, handle); - if (ret != 0) - return (ret); + /* + * Get the user-visible handle using idr. + */ +again: + /* ensure there is space available to allocate a handle */ + if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0) + return -ENOMEM; + + /* do the allocation under our spinlock */ + spin_lock(&file_priv->table_lock); + ret = idr_get_new_above(&file_priv->object_idr, obj, 1, (int *)handlep); + spin_unlock(&file_priv->table_lock); + if (ret == -EAGAIN) + goto again; + else if (ret) + return ret; + drm_gem_object_handle_reference(obj); if (dev->driver->gem_open_object) { ret = dev->driver->gem_open_object(obj, file_priv); if (ret) { - drm_gem_handle_delete(file_priv, *handle); + drm_gem_handle_delete(file_priv, *handlep); return ret; } } - return (0); + return 0; } -int -drm_gem_handle_delete(struct drm_file *file_priv, uint32_t handle) +/** Returns a reference to the object named by the handle. */ +struct drm_gem_object * +drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, + u32 handle) { - struct drm_device *dev; struct drm_gem_object *obj; - obj = drm_gem_names_remove(&file_priv->object_names, handle); - if (obj == NULL) - return (EINVAL); + spin_lock(&filp->table_lock); - dev = obj->dev; - if (dev->driver->gem_close_object) - dev->driver->gem_close_object(obj, file_priv); - drm_gem_object_handle_unreference_unlocked(obj); + /* Check if we currently have a reference on the object */ + obj = idr_find(&filp->object_idr, handle); + if (obj == NULL) { + spin_unlock(&filp->table_lock); + return NULL; + } - return (0); + drm_gem_object_reference(obj); + + spin_unlock(&filp->table_lock); + + return obj; } -void -drm_gem_object_release(struct drm_gem_object *obj) +int +drm_gem_close_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { + struct drm_gem_close *args; - /* - * obj->vm_obj can be NULL for private gem objects. - */ - vm_object_deallocate(obj->vm_obj); + if (!drm_core_check_feature(dev, DRIVER_GEM)) + return (ENODEV); + args = data; + + return (drm_gem_handle_delete(file_priv, args->handle)); } +/** + * Create a global name for an object, returning the name. + * + * Note that the name does not hold a reference; when the object + * is freed, the name goes away. + */ int -drm_gem_open_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +drm_gem_flink_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_gem_open *args; + struct drm_gem_flink *args = data; struct drm_gem_object *obj; int ret; - uint32_t handle; if (!drm_core_check_feature(dev, DRIVER_GEM)) - return (ENODEV); - args = data; + return -ENODEV; - obj = drm_gem_name_ref(&dev->object_names, args->name, - (void (*)(void *))drm_gem_object_reference); + obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (obj == NULL) - return (ENOENT); - handle = 0; - ret = drm_gem_handle_create(file_priv, obj, &handle); - drm_gem_object_unreference_unlocked(obj); - if (ret != 0) - return (ret); - - args->handle = handle; - args->size = obj->size; + return -ENOENT; - return (0); -} +again: + if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) { + ret = -ENOMEM; + goto err; + } -void -drm_gem_open(struct drm_device *dev, struct drm_file *file_priv) -{ + spin_lock(&dev->object_name_lock); + if (!obj->name) { + ret = idr_get_new_above(&dev->object_name_idr, obj, 1, + &obj->name); + args->name = (uint64_t) obj->name; + spin_unlock(&dev->object_name_lock); + + if (ret == -EAGAIN) + goto again; + else if (ret) + goto err; + + /* Allocate a reference for the name table. */ + drm_gem_object_reference(obj); + } else { + args->name = (uint64_t) obj->name; + spin_unlock(&dev->object_name_lock); + ret = 0; + } - drm_gem_names_init(&file_priv->object_names); +err: + drm_gem_object_unreference_unlocked(obj); + return ret; } -static int -drm_gem_object_release_handle(uint32_t name, void *ptr, void *arg) +/** + * Open an object using the global name, returning a handle and the size. + * + * This handle (of course) holds a reference to the object, so the object + * will not go away until the handle is deleted. + */ +int +drm_gem_open_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *file_priv; + struct drm_gem_open *args = data; struct drm_gem_object *obj; - struct drm_device *dev; + int ret; + u32 handle; - file_priv = arg; - obj = ptr; - dev = obj->dev; +#if 0 + if (!drm_core_check_feature(dev, DRIVER_GEM)) +#endif + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; - if (dev->driver->gem_close_object) - dev->driver->gem_close_object(obj, file_priv); + spin_lock(&dev->object_name_lock); + obj = idr_find(&dev->object_name_idr, (int) args->name); + if (obj) + drm_gem_object_reference(obj); + spin_unlock(&dev->object_name_lock); + if (!obj) + return -ENOENT; - drm_gem_object_handle_unreference(obj); - return (0); + ret = drm_gem_handle_create(file_priv, obj, &handle); + drm_gem_object_unreference_unlocked(obj); + if (ret) + return ret; + + args->handle = handle; + args->size = obj->size; + + return 0; } +/** + * Called at device open time, sets up the structure for handling refcounting + * of mm objects. + */ void -drm_gem_release(struct drm_device *dev, struct drm_file *file_priv) +drm_gem_open(struct drm_device *dev, struct drm_file *file_private) { - - drm_gem_names_foreach(&file_priv->object_names, - drm_gem_object_release_handle, file_priv); - drm_gem_names_fini(&file_priv->object_names); + idr_init(&file_private->object_idr); + spin_init(&file_private->table_lock); } -int -drm_gem_close_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +/** + * Called at device close to release the file's + * handle references on objects. + */ +static int +drm_gem_object_release_handle(int id, void *ptr, void *data) { - struct drm_gem_close *args; + struct drm_file *file_priv = data; + struct drm_gem_object *obj = ptr; + struct drm_device *dev = obj->dev; - if (!drm_core_check_feature(dev, DRIVER_GEM)) - return (ENODEV); - args = data; + if (dev->driver->gem_close_object) + dev->driver->gem_close_object(obj, file_priv); - return (drm_gem_handle_delete(file_priv, args->handle)); + drm_gem_object_handle_unreference_unlocked(obj); + + return 0; } -int -drm_gem_flink_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +void +drm_gem_object_release(struct drm_gem_object *obj) { - struct drm_gem_flink *args; - struct drm_gem_object *obj; - int error; - - if (!drm_core_check_feature(dev, DRIVER_GEM)) - return (ENODEV); - args = data; - obj = drm_gem_name_ref(&file_priv->object_names, args->handle, - (void (*)(void *))drm_gem_object_reference); - if (obj == NULL) - return (ENOENT); - error = drm_gem_name_create(&dev->object_names, obj, &obj->name); - if (error != 0) { - if (error == EALREADY) - error = 0; - drm_gem_object_unreference_unlocked(obj); - } - if (error == 0) - args->name = obj->name; - return (error); + /* + * obj->vm_obj can be NULL for private gem objects. + */ + vm_object_deallocate(obj->vm_obj); } -struct drm_gem_object * -drm_gem_object_lookup(struct drm_device *dev, struct drm_file *file_priv, - uint32_t handle) +/** + * Called at close time when the filp is going away. + * + * Releases any remaining references on objects by this filp. + */ +void +drm_gem_release(struct drm_device *dev, struct drm_file *file_private) { - struct drm_gem_object *obj; + idr_for_each(&file_private->object_idr, + &drm_gem_object_release_handle, file_private); - obj = drm_gem_name_ref(&file_priv->object_names, handle, - (void (*)(void *))drm_gem_object_reference); - return (obj); + idr_remove_all(&file_private->object_idr); + idr_destroy(&file_private->object_idr); } static struct drm_gem_object * diff --git a/sys/dev/drm/drm_gem_names.c b/sys/dev/drm/drm_gem_names.c deleted file mode 100644 index bae1e84cf7..0000000000 --- a/sys/dev/drm/drm_gem_names.c +++ /dev/null @@ -1,211 +0,0 @@ -/*- - * Copyright (c) 2011 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Konstantin Belousov under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/drm2/drm_gem_names.c,v 1.1 2012/05/22 11:07:44 kib Exp $ -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include - -MALLOC_DEFINE(M_GEM_NAMES, "gem_name", "Hash headers for the gem names"); - -static void drm_gem_names_delete_name(struct drm_gem_names *names, - struct drm_gem_name *np); - -void -drm_gem_names_init(struct drm_gem_names *names) -{ - - names->unr = new_unrhdr(1, INT_MAX, NULL); /* XXXKIB */ - names->names_hash = hashinit(1000 /* XXXKIB */, M_GEM_NAMES, - &names->hash_mask); - lockinit(&names->lock, "drmnames", 0, LK_CANRECURSE); -} - -void -drm_gem_names_fini(struct drm_gem_names *names) -{ - struct drm_gem_name *np; - int i; - - lockmgr(&names->lock, LK_EXCLUSIVE); - for (i = 0; i <= names->hash_mask; i++) { - while ((np = LIST_FIRST(&names->names_hash[i])) != NULL) { - drm_gem_names_delete_name(names, np); - lockmgr(&names->lock, LK_EXCLUSIVE); - } - } - lockmgr(&names->lock, LK_RELEASE); - lockuninit(&names->lock); - hashdestroy(names->names_hash, M_GEM_NAMES, names->hash_mask); - delete_unrhdr(names->unr); -} - -static struct drm_gem_names_head * -gem_name_hash_index(struct drm_gem_names *names, int name) -{ - - return (&names->names_hash[name & names->hash_mask]); -} - -void * -drm_gem_name_ref(struct drm_gem_names *names, uint32_t name, - void (*ref)(void *)) -{ - struct drm_gem_name *n; - - lockmgr(&names->lock, LK_EXCLUSIVE); - LIST_FOREACH(n, gem_name_hash_index(names, name), link) { - if (n->name == name) { - if (ref != NULL) - ref(n->ptr); - lockmgr(&names->lock, LK_RELEASE); - return (n->ptr); - } - } - lockmgr(&names->lock, LK_RELEASE); - return (NULL); -} - -struct drm_gem_ptr_match_arg { - uint32_t res; - void *ptr; -}; - -static int -drm_gem_ptr_match(uint32_t name, void *ptr, void *arg) -{ - struct drm_gem_ptr_match_arg *a; - - a = arg; - if (ptr == a->ptr) { - a->res = name; - return (1); - } else - return (0); -} - -uint32_t -drm_gem_find_name(struct drm_gem_names *names, void *ptr) -{ - struct drm_gem_ptr_match_arg arg; - - arg.res = 0; - arg.ptr = ptr; - drm_gem_names_foreach(names, drm_gem_ptr_match, &arg); - return (arg.res); -} - -int -drm_gem_name_create(struct drm_gem_names *names, void *p, uint32_t *name) -{ - struct drm_gem_name *np; - - if (*name != 0) { - return (EALREADY); - } - - np = kmalloc(sizeof(struct drm_gem_name), M_GEM_NAMES, M_WAITOK); - lockmgr(&names->lock, LK_EXCLUSIVE); - np->name = alloc_unr(names->unr); - if (np->name == -1) { - lockmgr(&names->lock, LK_RELEASE); - drm_free(np, M_GEM_NAMES); - return (ENOMEM); - } - *name = np->name; - np->ptr = p; - LIST_INSERT_HEAD(gem_name_hash_index(names, np->name), np, link); - lockmgr(&names->lock, LK_RELEASE); - return (0); -} - -static void -drm_gem_names_delete_name(struct drm_gem_names *names, struct drm_gem_name *np) -{ - KKASSERT(lockstatus(&names->lock, curthread) != 0); - LIST_REMOVE(np, link); - lockmgr(&names->lock, LK_RELEASE); - free_unr(names->unr, np->name); - drm_free(np, M_GEM_NAMES); -} - -void * -drm_gem_names_remove(struct drm_gem_names *names, uint32_t name) -{ - struct drm_gem_name *n; - void *res; - - lockmgr(&names->lock, LK_EXCLUSIVE); - LIST_FOREACH(n, gem_name_hash_index(names, name), link) { - if (n->name == name) { - res = n->ptr; - drm_gem_names_delete_name(names, n); - return (res); - } - } - lockmgr(&names->lock, LK_RELEASE); - return (NULL); -} - -void -drm_gem_names_foreach(struct drm_gem_names *names, - int (*f)(uint32_t, void *, void *), void *arg) -{ - struct drm_gem_name *np; - struct drm_gem_name marker; - int i, fres; - - bzero(&marker, sizeof(marker)); - marker.name = -1; - lockmgr(&names->lock, LK_EXCLUSIVE); - for (i = 0; i <= names->hash_mask; i++) { - for (np = LIST_FIRST(&names->names_hash[i]); np != NULL; ) { - if (np->name == -1) { - np = LIST_NEXT(np, link); - continue; - } - LIST_INSERT_AFTER(np, &marker, link); - lockmgr(&names->lock, LK_RELEASE); - fres = f(np->name, np->ptr, arg); - lockmgr(&names->lock, LK_EXCLUSIVE); - np = LIST_NEXT(&marker, link); - LIST_REMOVE(&marker, link); - if (fres) - break; - } - } - lockmgr(&names->lock, LK_RELEASE); -} diff --git a/sys/dev/drm/include/drm/drmP.h b/sys/dev/drm/include/drm/drmP.h index dce5491984..8979daf016 100644 --- a/sys/dev/drm/include/drm/drmP.h +++ b/sys/dev/drm/include/drm/drmP.h @@ -95,8 +95,8 @@ #include #include "drm_linux_list.h" -#include "drm_gem_names.h" +#include #include struct drm_file; @@ -499,8 +499,12 @@ struct drm_file { drm_magic_t magic; unsigned long ioctl_count; + /** Mapping of mm object handles to object pointers. */ + struct idr object_idr; + /** Lock for synchronization of access to object_idr. */ + struct spinlock table_lock; + void *driver_priv; - struct drm_gem_names object_names; int is_master; struct drm_master *masterp; @@ -1009,10 +1013,13 @@ struct drm_device { struct drm_mode_config mode_config; /**< Current mode config */ - /* GEM part */ - struct lock object_name_lock; - struct drm_gem_names object_names; - void *mm_private; + + /** \name GEM information */ + /*@{ */ + struct spinlock object_name_lock; + struct idr object_name_idr; + /*@} */ + void *mm_private; void *sysctl_private; char busid_str[128]; diff --git a/sys/dev/drm/include/drm/drm_crtc.h b/sys/dev/drm/include/drm/drm_crtc.h index e3a957a7d4..8145cf861a 100644 --- a/sys/dev/drm/include/drm/drm_crtc.h +++ b/sys/dev/drm/include/drm/drm_crtc.h @@ -29,7 +29,6 @@ #include -#include "drm_gem_names.h" #include struct drm_device; diff --git a/sys/dev/drm/include/drm/drm_gem_names.h b/sys/dev/drm/include/drm/drm_gem_names.h deleted file mode 100644 index 0c5ba3735f..0000000000 --- a/sys/dev/drm/include/drm/drm_gem_names.h +++ /dev/null @@ -1,63 +0,0 @@ -/*- - * Copyright (c) 2011 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Konstantin Belousov under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/drm2/drm_gem_names.h,v 1.1 2012/05/22 11:07:44 kib Exp $ - * - */ - -#ifndef DRM_GEM_NAMES_H -#define DRM_GEM_NAMES_H - -#include -#include -#include - -struct drm_gem_name { - uint32_t name; - void *ptr; - LIST_ENTRY(drm_gem_name) link; -}; - -struct drm_gem_names { - struct lock lock; - LIST_HEAD(drm_gem_names_head, drm_gem_name) *names_hash; - u_long hash_mask; - struct unrhdr *unr; -}; - -void drm_gem_names_init(struct drm_gem_names *names); -void drm_gem_names_fini(struct drm_gem_names *names); -uint32_t drm_gem_find_name(struct drm_gem_names *names, void *ptr); -void *drm_gem_name_ref(struct drm_gem_names *names, uint32_t name, - void (*ref)(void *)); -int drm_gem_name_create(struct drm_gem_names *names, void *obj, uint32_t *name); -void drm_gem_names_foreach(struct drm_gem_names *names, - int (*f)(uint32_t, void *, void *), void *arg); -void *drm_gem_names_remove(struct drm_gem_names *names, uint32_t name); - -#endif -- 2.41.0