Home | History | Annotate | Line # | Download | only in vmwgfx
      1  1.3  riastrad /*	$NetBSD: ttm_object.c,v 1.3 2022/02/17 01:21:02 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /* SPDX-License-Identifier: GPL-2.0 OR MIT */
      4  1.1  riastrad /**************************************************************************
      5  1.1  riastrad  *
      6  1.1  riastrad  * Copyright (c) 2009-2013 VMware, Inc., Palo Alto, CA., USA
      7  1.1  riastrad  * All Rights Reserved.
      8  1.1  riastrad  *
      9  1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
     10  1.1  riastrad  * copy of this software and associated documentation files (the
     11  1.1  riastrad  * "Software"), to deal in the Software without restriction, including
     12  1.1  riastrad  * without limitation the rights to use, copy, modify, merge, publish,
     13  1.1  riastrad  * distribute, sub license, and/or sell copies of the Software, and to
     14  1.1  riastrad  * permit persons to whom the Software is furnished to do so, subject to
     15  1.1  riastrad  * the following conditions:
     16  1.1  riastrad  *
     17  1.1  riastrad  * The above copyright notice and this permission notice (including the
     18  1.1  riastrad  * next paragraph) shall be included in all copies or substantial portions
     19  1.1  riastrad  * of the Software.
     20  1.1  riastrad  *
     21  1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     22  1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     23  1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     24  1.1  riastrad  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     25  1.1  riastrad  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     26  1.1  riastrad  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     27  1.1  riastrad  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     28  1.1  riastrad  *
     29  1.1  riastrad  **************************************************************************/
     30  1.1  riastrad /*
     31  1.1  riastrad  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
     32  1.1  riastrad  *
     33  1.1  riastrad  * While no substantial code is shared, the prime code is inspired by
     34  1.1  riastrad  * drm_prime.c, with
     35  1.1  riastrad  * Authors:
     36  1.1  riastrad  *      Dave Airlie <airlied (at) redhat.com>
     37  1.1  riastrad  *      Rob Clark <rob.clark (at) linaro.org>
     38  1.1  riastrad  */
     39  1.1  riastrad /** @file ttm_ref_object.c
     40  1.1  riastrad  *
     41  1.1  riastrad  * Base- and reference object implementation for the various
     42  1.1  riastrad  * ttm objects. Implements reference counting, minimal security checks
     43  1.1  riastrad  * and release on file close.
     44  1.1  riastrad  */
     45  1.1  riastrad 
     46  1.1  riastrad 
     47  1.1  riastrad /**
     48  1.1  riastrad  * struct ttm_object_file
     49  1.1  riastrad  *
     50  1.1  riastrad  * @tdev: Pointer to the ttm_object_device.
     51  1.1  riastrad  *
     52  1.1  riastrad  * @lock: Lock that protects the ref_list list and the
     53  1.1  riastrad  * ref_hash hash tables.
     54  1.1  riastrad  *
     55  1.1  riastrad  * @ref_list: List of ttm_ref_objects to be destroyed at
     56  1.1  riastrad  * file release.
     57  1.1  riastrad  *
     58  1.1  riastrad  * @ref_hash: Hash tables of ref objects, one per ttm_ref_type,
     59  1.1  riastrad  * for fast lookup of ref objects given a base object.
     60  1.1  riastrad  */
     61  1.1  riastrad 
     62  1.1  riastrad #include <sys/cdefs.h>
     63  1.3  riastrad __KERNEL_RCSID(0, "$NetBSD: ttm_object.c,v 1.3 2022/02/17 01:21:02 riastradh Exp $");
     64  1.1  riastrad 
     65  1.1  riastrad #define pr_fmt(fmt) "[TTM] " fmt
     66  1.1  riastrad 
     67  1.1  riastrad #include <drm/ttm/ttm_module.h>
     68  1.1  riastrad #include <linux/list.h>
     69  1.1  riastrad #include <linux/spinlock.h>
     70  1.1  riastrad #include <linux/slab.h>
     71  1.1  riastrad #include <linux/atomic.h>
     72  1.1  riastrad #include "ttm_object.h"
     73  1.1  riastrad 
     74  1.3  riastrad #include <linux/nbsd-namespace.h>
     75  1.3  riastrad 
     76  1.1  riastrad struct ttm_object_file {
     77  1.1  riastrad 	struct ttm_object_device *tdev;
     78  1.1  riastrad 	spinlock_t lock;
     79  1.1  riastrad 	struct list_head ref_list;
     80  1.1  riastrad 	struct drm_open_hash ref_hash[TTM_REF_NUM];
     81  1.1  riastrad 	struct kref refcount;
     82  1.1  riastrad };
     83  1.1  riastrad 
     84  1.1  riastrad /**
     85  1.1  riastrad  * struct ttm_object_device
     86  1.1  riastrad  *
     87  1.1  riastrad  * @object_lock: lock that protects the object_hash hash table.
     88  1.1  riastrad  *
     89  1.1  riastrad  * @object_hash: hash table for fast lookup of object global names.
     90  1.1  riastrad  *
     91  1.1  riastrad  * @object_count: Per device object count.
     92  1.1  riastrad  *
     93  1.1  riastrad  * This is the per-device data structure needed for ttm object management.
     94  1.1  riastrad  */
     95  1.1  riastrad 
     96  1.1  riastrad struct ttm_object_device {
     97  1.1  riastrad 	spinlock_t object_lock;
     98  1.1  riastrad 	struct drm_open_hash object_hash;
     99  1.1  riastrad 	atomic_t object_count;
    100  1.1  riastrad 	struct ttm_mem_global *mem_glob;
    101  1.1  riastrad 	struct dma_buf_ops ops;
    102  1.1  riastrad 	void (*dmabuf_release)(struct dma_buf *dma_buf);
    103  1.1  riastrad 	size_t dma_buf_size;
    104  1.1  riastrad 	struct idr idr;
    105  1.1  riastrad };
    106  1.1  riastrad 
    107  1.1  riastrad /**
    108  1.1  riastrad  * struct ttm_ref_object
    109  1.1  riastrad  *
    110  1.1  riastrad  * @hash: Hash entry for the per-file object reference hash.
    111  1.1  riastrad  *
    112  1.1  riastrad  * @head: List entry for the per-file list of ref-objects.
    113  1.1  riastrad  *
    114  1.1  riastrad  * @kref: Ref count.
    115  1.1  riastrad  *
    116  1.1  riastrad  * @obj: Base object this ref object is referencing.
    117  1.1  riastrad  *
    118  1.1  riastrad  * @ref_type: Type of ref object.
    119  1.1  riastrad  *
    120  1.1  riastrad  * This is similar to an idr object, but it also has a hash table entry
    121  1.1  riastrad  * that allows lookup with a pointer to the referenced object as a key. In
    122  1.1  riastrad  * that way, one can easily detect whether a base object is referenced by
    123  1.1  riastrad  * a particular ttm_object_file. It also carries a ref count to avoid creating
    124  1.1  riastrad  * multiple ref objects if a ttm_object_file references the same base
    125  1.1  riastrad  * object more than once.
    126  1.1  riastrad  */
    127  1.1  riastrad 
    128  1.1  riastrad struct ttm_ref_object {
    129  1.1  riastrad 	struct rcu_head rcu_head;
    130  1.1  riastrad 	struct drm_hash_item hash;
    131  1.1  riastrad 	struct list_head head;
    132  1.1  riastrad 	struct kref kref;
    133  1.1  riastrad 	enum ttm_ref_type ref_type;
    134  1.1  riastrad 	struct ttm_base_object *obj;
    135  1.1  riastrad 	struct ttm_object_file *tfile;
    136  1.1  riastrad };
    137  1.1  riastrad 
    138  1.1  riastrad static void ttm_prime_dmabuf_release(struct dma_buf *dma_buf);
    139  1.1  riastrad 
    140  1.1  riastrad static inline struct ttm_object_file *
    141  1.1  riastrad ttm_object_file_ref(struct ttm_object_file *tfile)
    142  1.1  riastrad {
    143  1.1  riastrad 	kref_get(&tfile->refcount);
    144  1.1  riastrad 	return tfile;
    145  1.1  riastrad }
    146  1.1  riastrad 
    147  1.1  riastrad static void ttm_object_file_destroy(struct kref *kref)
    148  1.1  riastrad {
    149  1.1  riastrad 	struct ttm_object_file *tfile =
    150  1.1  riastrad 		container_of(kref, struct ttm_object_file, refcount);
    151  1.1  riastrad 
    152  1.1  riastrad 	kfree(tfile);
    153  1.1  riastrad }
    154  1.1  riastrad 
    155  1.1  riastrad 
    156  1.1  riastrad static inline void ttm_object_file_unref(struct ttm_object_file **p_tfile)
    157  1.1  riastrad {
    158  1.1  riastrad 	struct ttm_object_file *tfile = *p_tfile;
    159  1.1  riastrad 
    160  1.1  riastrad 	*p_tfile = NULL;
    161  1.1  riastrad 	kref_put(&tfile->refcount, ttm_object_file_destroy);
    162  1.1  riastrad }
    163  1.1  riastrad 
    164  1.1  riastrad 
    165  1.1  riastrad int ttm_base_object_init(struct ttm_object_file *tfile,
    166  1.1  riastrad 			 struct ttm_base_object *base,
    167  1.1  riastrad 			 bool shareable,
    168  1.1  riastrad 			 enum ttm_object_type object_type,
    169  1.1  riastrad 			 void (*refcount_release) (struct ttm_base_object **),
    170  1.1  riastrad 			 void (*ref_obj_release) (struct ttm_base_object *,
    171  1.1  riastrad 						  enum ttm_ref_type ref_type))
    172  1.1  riastrad {
    173  1.1  riastrad 	struct ttm_object_device *tdev = tfile->tdev;
    174  1.1  riastrad 	int ret;
    175  1.1  riastrad 
    176  1.1  riastrad 	base->shareable = shareable;
    177  1.1  riastrad 	base->tfile = ttm_object_file_ref(tfile);
    178  1.1  riastrad 	base->refcount_release = refcount_release;
    179  1.1  riastrad 	base->ref_obj_release = ref_obj_release;
    180  1.1  riastrad 	base->object_type = object_type;
    181  1.1  riastrad 	kref_init(&base->refcount);
    182  1.1  riastrad 	idr_preload(GFP_KERNEL);
    183  1.1  riastrad 	spin_lock(&tdev->object_lock);
    184  1.1  riastrad 	ret = idr_alloc(&tdev->idr, base, 1, 0, GFP_NOWAIT);
    185  1.1  riastrad 	spin_unlock(&tdev->object_lock);
    186  1.1  riastrad 	idr_preload_end();
    187  1.1  riastrad 	if (ret < 0)
    188  1.1  riastrad 		return ret;
    189  1.1  riastrad 
    190  1.1  riastrad 	base->handle = ret;
    191  1.1  riastrad 	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
    192  1.1  riastrad 	if (unlikely(ret != 0))
    193  1.1  riastrad 		goto out_err1;
    194  1.1  riastrad 
    195  1.1  riastrad 	ttm_base_object_unref(&base);
    196  1.1  riastrad 
    197  1.1  riastrad 	return 0;
    198  1.1  riastrad out_err1:
    199  1.1  riastrad 	spin_lock(&tdev->object_lock);
    200  1.1  riastrad 	idr_remove(&tdev->idr, base->handle);
    201  1.1  riastrad 	spin_unlock(&tdev->object_lock);
    202  1.1  riastrad 	return ret;
    203  1.1  riastrad }
    204  1.1  riastrad 
    205  1.1  riastrad static void ttm_release_base(struct kref *kref)
    206  1.1  riastrad {
    207  1.1  riastrad 	struct ttm_base_object *base =
    208  1.1  riastrad 	    container_of(kref, struct ttm_base_object, refcount);
    209  1.1  riastrad 	struct ttm_object_device *tdev = base->tfile->tdev;
    210  1.1  riastrad 
    211  1.1  riastrad 	spin_lock(&tdev->object_lock);
    212  1.1  riastrad 	idr_remove(&tdev->idr, base->handle);
    213  1.1  riastrad 	spin_unlock(&tdev->object_lock);
    214  1.1  riastrad 
    215  1.1  riastrad 	/*
    216  1.1  riastrad 	 * Note: We don't use synchronize_rcu() here because it's far
    217  1.1  riastrad 	 * too slow. It's up to the user to free the object using
    218  1.1  riastrad 	 * call_rcu() or ttm_base_object_kfree().
    219  1.1  riastrad 	 */
    220  1.1  riastrad 
    221  1.1  riastrad 	ttm_object_file_unref(&base->tfile);
    222  1.1  riastrad 	if (base->refcount_release)
    223  1.1  riastrad 		base->refcount_release(&base);
    224  1.1  riastrad }
    225  1.1  riastrad 
    226  1.1  riastrad void ttm_base_object_unref(struct ttm_base_object **p_base)
    227  1.1  riastrad {
    228  1.1  riastrad 	struct ttm_base_object *base = *p_base;
    229  1.1  riastrad 
    230  1.1  riastrad 	*p_base = NULL;
    231  1.1  riastrad 
    232  1.1  riastrad 	kref_put(&base->refcount, ttm_release_base);
    233  1.1  riastrad }
    234  1.1  riastrad 
    235  1.1  riastrad /**
    236  1.1  riastrad  * ttm_base_object_noref_lookup - look up a base object without reference
    237  1.1  riastrad  * @tfile: The struct ttm_object_file the object is registered with.
    238  1.1  riastrad  * @key: The object handle.
    239  1.1  riastrad  *
    240  1.1  riastrad  * This function looks up a ttm base object and returns a pointer to it
    241  1.1  riastrad  * without refcounting the pointer. The returned pointer is only valid
    242  1.1  riastrad  * until ttm_base_object_noref_release() is called, and the object
    243  1.1  riastrad  * pointed to by the returned pointer may be doomed. Any persistent usage
    244  1.1  riastrad  * of the object requires a refcount to be taken using kref_get_unless_zero().
    245  1.1  riastrad  * Iff this function returns successfully it needs to be paired with
    246  1.1  riastrad  * ttm_base_object_noref_release() and no sleeping- or scheduling functions
    247  1.1  riastrad  * may be called inbetween these function callse.
    248  1.1  riastrad  *
    249  1.1  riastrad  * Return: A pointer to the object if successful or NULL otherwise.
    250  1.1  riastrad  */
    251  1.1  riastrad struct ttm_base_object *
    252  1.1  riastrad ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
    253  1.1  riastrad {
    254  1.1  riastrad 	struct drm_hash_item *hash;
    255  1.1  riastrad 	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
    256  1.1  riastrad 	int ret;
    257  1.1  riastrad 
    258  1.1  riastrad 	rcu_read_lock();
    259  1.1  riastrad 	ret = drm_ht_find_item_rcu(ht, key, &hash);
    260  1.1  riastrad 	if (ret) {
    261  1.1  riastrad 		rcu_read_unlock();
    262  1.1  riastrad 		return NULL;
    263  1.1  riastrad 	}
    264  1.1  riastrad 
    265  1.1  riastrad 	__release(RCU);
    266  1.1  riastrad 	return drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
    267  1.1  riastrad }
    268  1.1  riastrad EXPORT_SYMBOL(ttm_base_object_noref_lookup);
    269  1.1  riastrad 
    270  1.1  riastrad struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
    271  1.1  riastrad 					       uint32_t key)
    272  1.1  riastrad {
    273  1.1  riastrad 	struct ttm_base_object *base = NULL;
    274  1.1  riastrad 	struct drm_hash_item *hash;
    275  1.1  riastrad 	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
    276  1.1  riastrad 	int ret;
    277  1.1  riastrad 
    278  1.1  riastrad 	rcu_read_lock();
    279  1.1  riastrad 	ret = drm_ht_find_item_rcu(ht, key, &hash);
    280  1.1  riastrad 
    281  1.1  riastrad 	if (likely(ret == 0)) {
    282  1.1  riastrad 		base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
    283  1.1  riastrad 		if (!kref_get_unless_zero(&base->refcount))
    284  1.1  riastrad 			base = NULL;
    285  1.1  riastrad 	}
    286  1.1  riastrad 	rcu_read_unlock();
    287  1.1  riastrad 
    288  1.1  riastrad 	return base;
    289  1.1  riastrad }
    290  1.1  riastrad 
    291  1.1  riastrad struct ttm_base_object *
    292  1.1  riastrad ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
    293  1.1  riastrad {
    294  1.1  riastrad 	struct ttm_base_object *base;
    295  1.1  riastrad 
    296  1.1  riastrad 	rcu_read_lock();
    297  1.1  riastrad 	base = idr_find(&tdev->idr, key);
    298  1.1  riastrad 
    299  1.1  riastrad 	if (base && !kref_get_unless_zero(&base->refcount))
    300  1.1  riastrad 		base = NULL;
    301  1.1  riastrad 	rcu_read_unlock();
    302  1.1  riastrad 
    303  1.1  riastrad 	return base;
    304  1.1  riastrad }
    305  1.1  riastrad 
    306  1.1  riastrad /**
    307  1.1  riastrad  * ttm_ref_object_exists - Check whether a caller has a valid ref object
    308  1.1  riastrad  * (has opened) a base object.
    309  1.1  riastrad  *
    310  1.1  riastrad  * @tfile: Pointer to a struct ttm_object_file identifying the caller.
    311  1.1  riastrad  * @base: Pointer to a struct base object.
    312  1.1  riastrad  *
    313  1.1  riastrad  * Checks wether the caller identified by @tfile has put a valid USAGE
    314  1.1  riastrad  * reference object on the base object identified by @base.
    315  1.1  riastrad  */
    316  1.1  riastrad bool ttm_ref_object_exists(struct ttm_object_file *tfile,
    317  1.1  riastrad 			   struct ttm_base_object *base)
    318  1.1  riastrad {
    319  1.1  riastrad 	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
    320  1.1  riastrad 	struct drm_hash_item *hash;
    321  1.1  riastrad 	struct ttm_ref_object *ref;
    322  1.1  riastrad 
    323  1.1  riastrad 	rcu_read_lock();
    324  1.1  riastrad 	if (unlikely(drm_ht_find_item_rcu(ht, base->handle, &hash) != 0))
    325  1.1  riastrad 		goto out_false;
    326  1.1  riastrad 
    327  1.1  riastrad 	/*
    328  1.1  riastrad 	 * Verify that the ref object is really pointing to our base object.
    329  1.1  riastrad 	 * Our base object could actually be dead, and the ref object pointing
    330  1.1  riastrad 	 * to another base object with the same handle.
    331  1.1  riastrad 	 */
    332  1.1  riastrad 	ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
    333  1.1  riastrad 	if (unlikely(base != ref->obj))
    334  1.1  riastrad 		goto out_false;
    335  1.1  riastrad 
    336  1.1  riastrad 	/*
    337  1.1  riastrad 	 * Verify that the ref->obj pointer was actually valid!
    338  1.1  riastrad 	 */
    339  1.1  riastrad 	rmb();
    340  1.1  riastrad 	if (unlikely(kref_read(&ref->kref) == 0))
    341  1.1  riastrad 		goto out_false;
    342  1.1  riastrad 
    343  1.1  riastrad 	rcu_read_unlock();
    344  1.1  riastrad 	return true;
    345  1.1  riastrad 
    346  1.1  riastrad  out_false:
    347  1.1  riastrad 	rcu_read_unlock();
    348  1.1  riastrad 	return false;
    349  1.1  riastrad }
    350  1.1  riastrad 
    351  1.1  riastrad int ttm_ref_object_add(struct ttm_object_file *tfile,
    352  1.1  riastrad 		       struct ttm_base_object *base,
    353  1.1  riastrad 		       enum ttm_ref_type ref_type, bool *existed,
    354  1.1  riastrad 		       bool require_existed)
    355  1.1  riastrad {
    356  1.1  riastrad 	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
    357  1.1  riastrad 	struct ttm_ref_object *ref;
    358  1.1  riastrad 	struct drm_hash_item *hash;
    359  1.1  riastrad 	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
    360  1.1  riastrad 	struct ttm_operation_ctx ctx = {
    361  1.1  riastrad 		.interruptible = false,
    362  1.1  riastrad 		.no_wait_gpu = false
    363  1.1  riastrad 	};
    364  1.1  riastrad 	int ret = -EINVAL;
    365  1.1  riastrad 
    366  1.1  riastrad 	if (base->tfile != tfile && !base->shareable)
    367  1.1  riastrad 		return -EPERM;
    368  1.1  riastrad 
    369  1.1  riastrad 	if (existed != NULL)
    370  1.1  riastrad 		*existed = true;
    371  1.1  riastrad 
    372  1.1  riastrad 	while (ret == -EINVAL) {
    373  1.1  riastrad 		rcu_read_lock();
    374  1.1  riastrad 		ret = drm_ht_find_item_rcu(ht, base->handle, &hash);
    375  1.1  riastrad 
    376  1.1  riastrad 		if (ret == 0) {
    377  1.1  riastrad 			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
    378  1.1  riastrad 			if (kref_get_unless_zero(&ref->kref)) {
    379  1.1  riastrad 				rcu_read_unlock();
    380  1.1  riastrad 				break;
    381  1.1  riastrad 			}
    382  1.1  riastrad 		}
    383  1.1  riastrad 
    384  1.1  riastrad 		rcu_read_unlock();
    385  1.1  riastrad 		if (require_existed)
    386  1.1  riastrad 			return -EPERM;
    387  1.1  riastrad 
    388  1.1  riastrad 		ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
    389  1.1  riastrad 					   &ctx);
    390  1.1  riastrad 		if (unlikely(ret != 0))
    391  1.1  riastrad 			return ret;
    392  1.1  riastrad 		ref = kmalloc(sizeof(*ref), GFP_KERNEL);
    393  1.1  riastrad 		if (unlikely(ref == NULL)) {
    394  1.1  riastrad 			ttm_mem_global_free(mem_glob, sizeof(*ref));
    395  1.1  riastrad 			return -ENOMEM;
    396  1.1  riastrad 		}
    397  1.1  riastrad 
    398  1.1  riastrad 		ref->hash.key = base->handle;
    399  1.1  riastrad 		ref->obj = base;
    400  1.1  riastrad 		ref->tfile = tfile;
    401  1.1  riastrad 		ref->ref_type = ref_type;
    402  1.1  riastrad 		kref_init(&ref->kref);
    403  1.1  riastrad 
    404  1.1  riastrad 		spin_lock(&tfile->lock);
    405  1.1  riastrad 		ret = drm_ht_insert_item_rcu(ht, &ref->hash);
    406  1.1  riastrad 
    407  1.1  riastrad 		if (likely(ret == 0)) {
    408  1.1  riastrad 			list_add_tail(&ref->head, &tfile->ref_list);
    409  1.1  riastrad 			kref_get(&base->refcount);
    410  1.1  riastrad 			spin_unlock(&tfile->lock);
    411  1.1  riastrad 			if (existed != NULL)
    412  1.1  riastrad 				*existed = false;
    413  1.1  riastrad 			break;
    414  1.1  riastrad 		}
    415  1.1  riastrad 
    416  1.1  riastrad 		spin_unlock(&tfile->lock);
    417  1.1  riastrad 		BUG_ON(ret != -EINVAL);
    418  1.1  riastrad 
    419  1.1  riastrad 		ttm_mem_global_free(mem_glob, sizeof(*ref));
    420  1.1  riastrad 		kfree(ref);
    421  1.1  riastrad 	}
    422  1.1  riastrad 
    423  1.1  riastrad 	return ret;
    424  1.1  riastrad }
    425  1.1  riastrad 
    426  1.1  riastrad static void __releases(tfile->lock) __acquires(tfile->lock)
    427  1.1  riastrad ttm_ref_object_release(struct kref *kref)
    428  1.1  riastrad {
    429  1.1  riastrad 	struct ttm_ref_object *ref =
    430  1.1  riastrad 	    container_of(kref, struct ttm_ref_object, kref);
    431  1.1  riastrad 	struct ttm_base_object *base = ref->obj;
    432  1.1  riastrad 	struct ttm_object_file *tfile = ref->tfile;
    433  1.1  riastrad 	struct drm_open_hash *ht;
    434  1.1  riastrad 	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
    435  1.1  riastrad 
    436  1.1  riastrad 	ht = &tfile->ref_hash[ref->ref_type];
    437  1.1  riastrad 	(void)drm_ht_remove_item_rcu(ht, &ref->hash);
    438  1.1  riastrad 	list_del(&ref->head);
    439  1.1  riastrad 	spin_unlock(&tfile->lock);
    440  1.1  riastrad 
    441  1.1  riastrad 	if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release)
    442  1.1  riastrad 		base->ref_obj_release(base, ref->ref_type);
    443  1.1  riastrad 
    444  1.1  riastrad 	ttm_base_object_unref(&ref->obj);
    445  1.1  riastrad 	ttm_mem_global_free(mem_glob, sizeof(*ref));
    446  1.1  riastrad 	kfree_rcu(ref, rcu_head);
    447  1.1  riastrad 	spin_lock(&tfile->lock);
    448  1.1  riastrad }
    449  1.1  riastrad 
    450  1.1  riastrad int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
    451  1.1  riastrad 			      unsigned long key, enum ttm_ref_type ref_type)
    452  1.1  riastrad {
    453  1.1  riastrad 	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
    454  1.1  riastrad 	struct ttm_ref_object *ref;
    455  1.1  riastrad 	struct drm_hash_item *hash;
    456  1.1  riastrad 	int ret;
    457  1.1  riastrad 
    458  1.1  riastrad 	spin_lock(&tfile->lock);
    459  1.1  riastrad 	ret = drm_ht_find_item(ht, key, &hash);
    460  1.1  riastrad 	if (unlikely(ret != 0)) {
    461  1.1  riastrad 		spin_unlock(&tfile->lock);
    462  1.1  riastrad 		return -EINVAL;
    463  1.1  riastrad 	}
    464  1.1  riastrad 	ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
    465  1.1  riastrad 	kref_put(&ref->kref, ttm_ref_object_release);
    466  1.1  riastrad 	spin_unlock(&tfile->lock);
    467  1.1  riastrad 	return 0;
    468  1.1  riastrad }
    469  1.1  riastrad 
    470  1.1  riastrad void ttm_object_file_release(struct ttm_object_file **p_tfile)
    471  1.1  riastrad {
    472  1.1  riastrad 	struct ttm_ref_object *ref;
    473  1.1  riastrad 	struct list_head *list;
    474  1.1  riastrad 	unsigned int i;
    475  1.1  riastrad 	struct ttm_object_file *tfile = *p_tfile;
    476  1.1  riastrad 
    477  1.1  riastrad 	*p_tfile = NULL;
    478  1.1  riastrad 	spin_lock(&tfile->lock);
    479  1.1  riastrad 
    480  1.1  riastrad 	/*
    481  1.1  riastrad 	 * Since we release the lock within the loop, we have to
    482  1.1  riastrad 	 * restart it from the beginning each time.
    483  1.1  riastrad 	 */
    484  1.1  riastrad 
    485  1.1  riastrad 	while (!list_empty(&tfile->ref_list)) {
    486  1.1  riastrad 		list = tfile->ref_list.next;
    487  1.1  riastrad 		ref = list_entry(list, struct ttm_ref_object, head);
    488  1.1  riastrad 		ttm_ref_object_release(&ref->kref);
    489  1.1  riastrad 	}
    490  1.1  riastrad 
    491  1.1  riastrad 	spin_unlock(&tfile->lock);
    492  1.1  riastrad 	for (i = 0; i < TTM_REF_NUM; ++i)
    493  1.1  riastrad 		drm_ht_remove(&tfile->ref_hash[i]);
    494  1.1  riastrad 
    495  1.1  riastrad 	ttm_object_file_unref(&tfile);
    496  1.1  riastrad }
    497  1.1  riastrad 
    498  1.1  riastrad struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
    499  1.1  riastrad 					     unsigned int hash_order)
    500  1.1  riastrad {
    501  1.1  riastrad 	struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
    502  1.1  riastrad 	unsigned int i;
    503  1.1  riastrad 	unsigned int j = 0;
    504  1.1  riastrad 	int ret;
    505  1.1  riastrad 
    506  1.1  riastrad 	if (unlikely(tfile == NULL))
    507  1.1  riastrad 		return NULL;
    508  1.1  riastrad 
    509  1.1  riastrad 	spin_lock_init(&tfile->lock);
    510  1.1  riastrad 	tfile->tdev = tdev;
    511  1.1  riastrad 	kref_init(&tfile->refcount);
    512  1.1  riastrad 	INIT_LIST_HEAD(&tfile->ref_list);
    513  1.1  riastrad 
    514  1.1  riastrad 	for (i = 0; i < TTM_REF_NUM; ++i) {
    515  1.1  riastrad 		ret = drm_ht_create(&tfile->ref_hash[i], hash_order);
    516  1.1  riastrad 		if (ret) {
    517  1.1  riastrad 			j = i;
    518  1.1  riastrad 			goto out_err;
    519  1.1  riastrad 		}
    520  1.1  riastrad 	}
    521  1.1  riastrad 
    522  1.1  riastrad 	return tfile;
    523  1.1  riastrad out_err:
    524  1.1  riastrad 	for (i = 0; i < j; ++i)
    525  1.1  riastrad 		drm_ht_remove(&tfile->ref_hash[i]);
    526  1.1  riastrad 
    527  1.1  riastrad 	kfree(tfile);
    528  1.1  riastrad 
    529  1.1  riastrad 	return NULL;
    530  1.1  riastrad }
    531  1.1  riastrad 
    532  1.1  riastrad struct ttm_object_device *
    533  1.1  riastrad ttm_object_device_init(struct ttm_mem_global *mem_glob,
    534  1.1  riastrad 		       unsigned int hash_order,
    535  1.1  riastrad 		       const struct dma_buf_ops *ops)
    536  1.1  riastrad {
    537  1.1  riastrad 	struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL);
    538  1.1  riastrad 	int ret;
    539  1.1  riastrad 
    540  1.1  riastrad 	if (unlikely(tdev == NULL))
    541  1.1  riastrad 		return NULL;
    542  1.1  riastrad 
    543  1.1  riastrad 	tdev->mem_glob = mem_glob;
    544  1.1  riastrad 	spin_lock_init(&tdev->object_lock);
    545  1.1  riastrad 	atomic_set(&tdev->object_count, 0);
    546  1.1  riastrad 	ret = drm_ht_create(&tdev->object_hash, hash_order);
    547  1.1  riastrad 	if (ret != 0)
    548  1.1  riastrad 		goto out_no_object_hash;
    549  1.1  riastrad 
    550  1.1  riastrad 	idr_init(&tdev->idr);
    551  1.1  riastrad 	tdev->ops = *ops;
    552  1.1  riastrad 	tdev->dmabuf_release = tdev->ops.release;
    553  1.1  riastrad 	tdev->ops.release = ttm_prime_dmabuf_release;
    554  1.1  riastrad 	tdev->dma_buf_size = ttm_round_pot(sizeof(struct dma_buf)) +
    555  1.1  riastrad 		ttm_round_pot(sizeof(struct file));
    556  1.1  riastrad 	return tdev;
    557  1.1  riastrad 
    558  1.1  riastrad out_no_object_hash:
    559  1.1  riastrad 	kfree(tdev);
    560  1.1  riastrad 	return NULL;
    561  1.1  riastrad }
    562  1.1  riastrad 
    563  1.1  riastrad void ttm_object_device_release(struct ttm_object_device **p_tdev)
    564  1.1  riastrad {
    565  1.1  riastrad 	struct ttm_object_device *tdev = *p_tdev;
    566  1.1  riastrad 
    567  1.1  riastrad 	*p_tdev = NULL;
    568  1.1  riastrad 
    569  1.1  riastrad 	WARN_ON_ONCE(!idr_is_empty(&tdev->idr));
    570  1.1  riastrad 	idr_destroy(&tdev->idr);
    571  1.1  riastrad 	drm_ht_remove(&tdev->object_hash);
    572  1.1  riastrad 
    573  1.1  riastrad 	kfree(tdev);
    574  1.1  riastrad }
    575  1.1  riastrad 
    576  1.1  riastrad /**
    577  1.1  riastrad  * get_dma_buf_unless_doomed - get a dma_buf reference if possible.
    578  1.1  riastrad  *
    579  1.1  riastrad  * @dma_buf: Non-refcounted pointer to a struct dma-buf.
    580  1.1  riastrad  *
    581  1.1  riastrad  * Obtain a file reference from a lookup structure that doesn't refcount
    582  1.1  riastrad  * the file, but synchronizes with its release method to make sure it has
    583  1.1  riastrad  * not been freed yet. See for example kref_get_unless_zero documentation.
    584  1.1  riastrad  * Returns true if refcounting succeeds, false otherwise.
    585  1.1  riastrad  *
    586  1.1  riastrad  * Nobody really wants this as a public API yet, so let it mature here
    587  1.1  riastrad  * for some time...
    588  1.1  riastrad  */
    589  1.1  riastrad static bool __must_check get_dma_buf_unless_doomed(struct dma_buf *dmabuf)
    590  1.1  riastrad {
    591  1.3  riastrad #ifdef __NetBSD__
    592  1.3  riastrad 	/* XXX move this to linux_dma_buf.c */
    593  1.3  riastrad 	unsigned cnt;
    594  1.3  riastrad 
    595  1.3  riastrad 	do {
    596  1.3  riastrad 		cnt = atomic_load_relaxed(&dmabuf->db_refcnt);
    597  1.3  riastrad 		if (cnt == 0)
    598  1.3  riastrad 			return false;
    599  1.3  riastrad 	} while (atomic_cas_uint(&dmabuf->db_refcnt, cnt, cnt + 1) != cnt);
    600  1.3  riastrad 	return true;
    601  1.3  riastrad #else
    602  1.1  riastrad 	return atomic_long_inc_not_zero(&dmabuf->file->f_count) != 0L;
    603  1.3  riastrad #endif
    604  1.1  riastrad }
    605  1.1  riastrad 
    606  1.1  riastrad /**
    607  1.1  riastrad  * ttm_prime_refcount_release - refcount release method for a prime object.
    608  1.1  riastrad  *
    609  1.1  riastrad  * @p_base: Pointer to ttm_base_object pointer.
    610  1.1  riastrad  *
    611  1.1  riastrad  * This is a wrapper that calls the refcount_release founction of the
    612  1.1  riastrad  * underlying object. At the same time it cleans up the prime object.
    613  1.1  riastrad  * This function is called when all references to the base object we
    614  1.1  riastrad  * derive from are gone.
    615  1.1  riastrad  */
    616  1.1  riastrad static void ttm_prime_refcount_release(struct ttm_base_object **p_base)
    617  1.1  riastrad {
    618  1.1  riastrad 	struct ttm_base_object *base = *p_base;
    619  1.1  riastrad 	struct ttm_prime_object *prime;
    620  1.1  riastrad 
    621  1.1  riastrad 	*p_base = NULL;
    622  1.1  riastrad 	prime = container_of(base, struct ttm_prime_object, base);
    623  1.1  riastrad 	BUG_ON(prime->dma_buf != NULL);
    624  1.1  riastrad 	mutex_destroy(&prime->mutex);
    625  1.1  riastrad 	if (prime->refcount_release)
    626  1.1  riastrad 		prime->refcount_release(&base);
    627  1.1  riastrad }
    628  1.1  riastrad 
    629  1.1  riastrad /**
    630  1.1  riastrad  * ttm_prime_dmabuf_release - Release method for the dma-bufs we export
    631  1.1  riastrad  *
    632  1.1  riastrad  * @dma_buf:
    633  1.1  riastrad  *
    634  1.1  riastrad  * This function first calls the dma_buf release method the driver
    635  1.1  riastrad  * provides. Then it cleans up our dma_buf pointer used for lookup,
    636  1.1  riastrad  * and finally releases the reference the dma_buf has on our base
    637  1.1  riastrad  * object.
    638  1.1  riastrad  */
    639  1.1  riastrad static void ttm_prime_dmabuf_release(struct dma_buf *dma_buf)
    640  1.1  riastrad {
    641  1.1  riastrad 	struct ttm_prime_object *prime =
    642  1.1  riastrad 		(struct ttm_prime_object *) dma_buf->priv;
    643  1.1  riastrad 	struct ttm_base_object *base = &prime->base;
    644  1.1  riastrad 	struct ttm_object_device *tdev = base->tfile->tdev;
    645  1.1  riastrad 
    646  1.1  riastrad 	if (tdev->dmabuf_release)
    647  1.1  riastrad 		tdev->dmabuf_release(dma_buf);
    648  1.1  riastrad 	mutex_lock(&prime->mutex);
    649  1.1  riastrad 	if (prime->dma_buf == dma_buf)
    650  1.1  riastrad 		prime->dma_buf = NULL;
    651  1.1  riastrad 	mutex_unlock(&prime->mutex);
    652  1.1  riastrad 	ttm_mem_global_free(tdev->mem_glob, tdev->dma_buf_size);
    653  1.1  riastrad 	ttm_base_object_unref(&base);
    654  1.1  riastrad }
    655  1.1  riastrad 
    656  1.1  riastrad /**
    657  1.1  riastrad  * ttm_prime_fd_to_handle - Get a base object handle from a prime fd
    658  1.1  riastrad  *
    659  1.1  riastrad  * @tfile: A struct ttm_object_file identifying the caller.
    660  1.1  riastrad  * @fd: The prime / dmabuf fd.
    661  1.1  riastrad  * @handle: The returned handle.
    662  1.1  riastrad  *
    663  1.1  riastrad  * This function returns a handle to an object that previously exported
    664  1.1  riastrad  * a dma-buf. Note that we don't handle imports yet, because we simply
    665  1.1  riastrad  * have no consumers of that implementation.
    666  1.1  riastrad  */
    667  1.1  riastrad int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,
    668  1.1  riastrad 			   int fd, u32 *handle)
    669  1.1  riastrad {
    670  1.1  riastrad 	struct ttm_object_device *tdev = tfile->tdev;
    671  1.1  riastrad 	struct dma_buf *dma_buf;
    672  1.1  riastrad 	struct ttm_prime_object *prime;
    673  1.1  riastrad 	struct ttm_base_object *base;
    674  1.1  riastrad 	int ret;
    675  1.1  riastrad 
    676  1.1  riastrad 	dma_buf = dma_buf_get(fd);
    677  1.1  riastrad 	if (IS_ERR(dma_buf))
    678  1.1  riastrad 		return PTR_ERR(dma_buf);
    679  1.1  riastrad 
    680  1.1  riastrad 	if (dma_buf->ops != &tdev->ops)
    681  1.1  riastrad 		return -ENOSYS;
    682  1.1  riastrad 
    683  1.1  riastrad 	prime = (struct ttm_prime_object *) dma_buf->priv;
    684  1.1  riastrad 	base = &prime->base;
    685  1.1  riastrad 	*handle = base->handle;
    686  1.1  riastrad 	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
    687  1.1  riastrad 
    688  1.1  riastrad 	dma_buf_put(dma_buf);
    689  1.1  riastrad 
    690  1.1  riastrad 	return ret;
    691  1.1  riastrad }
    692  1.1  riastrad 
    693  1.1  riastrad /**
    694  1.1  riastrad  * ttm_prime_handle_to_fd - Return a dma_buf fd from a ttm prime object
    695  1.1  riastrad  *
    696  1.1  riastrad  * @tfile: Struct ttm_object_file identifying the caller.
    697  1.1  riastrad  * @handle: Handle to the object we're exporting from.
    698  1.1  riastrad  * @flags: flags for dma-buf creation. We just pass them on.
    699  1.1  riastrad  * @prime_fd: The returned file descriptor.
    700  1.1  riastrad  *
    701  1.1  riastrad  */
    702  1.1  riastrad int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
    703  1.1  riastrad 			   uint32_t handle, uint32_t flags,
    704  1.1  riastrad 			   int *prime_fd)
    705  1.1  riastrad {
    706  1.1  riastrad 	struct ttm_object_device *tdev = tfile->tdev;
    707  1.1  riastrad 	struct ttm_base_object *base;
    708  1.1  riastrad 	struct dma_buf *dma_buf;
    709  1.1  riastrad 	struct ttm_prime_object *prime;
    710  1.1  riastrad 	int ret;
    711  1.1  riastrad 
    712  1.1  riastrad 	base = ttm_base_object_lookup(tfile, handle);
    713  1.1  riastrad 	if (unlikely(base == NULL ||
    714  1.1  riastrad 		     base->object_type != ttm_prime_type)) {
    715  1.1  riastrad 		ret = -ENOENT;
    716  1.1  riastrad 		goto out_unref;
    717  1.1  riastrad 	}
    718  1.1  riastrad 
    719  1.1  riastrad 	prime = container_of(base, struct ttm_prime_object, base);
    720  1.1  riastrad 	if (unlikely(!base->shareable)) {
    721  1.1  riastrad 		ret = -EPERM;
    722  1.1  riastrad 		goto out_unref;
    723  1.1  riastrad 	}
    724  1.1  riastrad 
    725  1.1  riastrad 	ret = mutex_lock_interruptible(&prime->mutex);
    726  1.1  riastrad 	if (unlikely(ret != 0)) {
    727  1.1  riastrad 		ret = -ERESTARTSYS;
    728  1.1  riastrad 		goto out_unref;
    729  1.1  riastrad 	}
    730  1.1  riastrad 
    731  1.1  riastrad 	dma_buf = prime->dma_buf;
    732  1.1  riastrad 	if (!dma_buf || !get_dma_buf_unless_doomed(dma_buf)) {
    733  1.1  riastrad 		DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
    734  1.1  riastrad 		struct ttm_operation_ctx ctx = {
    735  1.1  riastrad 			.interruptible = true,
    736  1.1  riastrad 			.no_wait_gpu = false
    737  1.1  riastrad 		};
    738  1.1  riastrad 		exp_info.ops = &tdev->ops;
    739  1.1  riastrad 		exp_info.size = prime->size;
    740  1.1  riastrad 		exp_info.flags = flags;
    741  1.1  riastrad 		exp_info.priv = prime;
    742  1.1  riastrad 
    743  1.1  riastrad 		/*
    744  1.1  riastrad 		 * Need to create a new dma_buf, with memory accounting.
    745  1.1  riastrad 		 */
    746  1.1  riastrad 		ret = ttm_mem_global_alloc(tdev->mem_glob, tdev->dma_buf_size,
    747  1.1  riastrad 					   &ctx);
    748  1.1  riastrad 		if (unlikely(ret != 0)) {
    749  1.1  riastrad 			mutex_unlock(&prime->mutex);
    750  1.1  riastrad 			goto out_unref;
    751  1.1  riastrad 		}
    752  1.1  riastrad 
    753  1.1  riastrad 		dma_buf = dma_buf_export(&exp_info);
    754  1.1  riastrad 		if (IS_ERR(dma_buf)) {
    755  1.1  riastrad 			ret = PTR_ERR(dma_buf);
    756  1.1  riastrad 			ttm_mem_global_free(tdev->mem_glob,
    757  1.1  riastrad 					    tdev->dma_buf_size);
    758  1.1  riastrad 			mutex_unlock(&prime->mutex);
    759  1.1  riastrad 			goto out_unref;
    760  1.1  riastrad 		}
    761  1.1  riastrad 
    762  1.1  riastrad 		/*
    763  1.1  riastrad 		 * dma_buf has taken the base object reference
    764  1.1  riastrad 		 */
    765  1.1  riastrad 		base = NULL;
    766  1.1  riastrad 		prime->dma_buf = dma_buf;
    767  1.1  riastrad 	}
    768  1.1  riastrad 	mutex_unlock(&prime->mutex);
    769  1.1  riastrad 
    770  1.1  riastrad 	ret = dma_buf_fd(dma_buf, flags);
    771  1.1  riastrad 	if (ret >= 0) {
    772  1.1  riastrad 		*prime_fd = ret;
    773  1.1  riastrad 		ret = 0;
    774  1.1  riastrad 	} else
    775  1.1  riastrad 		dma_buf_put(dma_buf);
    776  1.1  riastrad 
    777  1.1  riastrad out_unref:
    778  1.1  riastrad 	if (base)
    779  1.1  riastrad 		ttm_base_object_unref(&base);
    780  1.1  riastrad 	return ret;
    781  1.1  riastrad }
    782  1.1  riastrad 
    783  1.1  riastrad /**
    784  1.1  riastrad  * ttm_prime_object_init - Initialize a ttm_prime_object
    785  1.1  riastrad  *
    786  1.1  riastrad  * @tfile: struct ttm_object_file identifying the caller
    787  1.1  riastrad  * @size: The size of the dma_bufs we export.
    788  1.1  riastrad  * @prime: The object to be initialized.
    789  1.1  riastrad  * @shareable: See ttm_base_object_init
    790  1.1  riastrad  * @type: See ttm_base_object_init
    791  1.1  riastrad  * @refcount_release: See ttm_base_object_init
    792  1.1  riastrad  * @ref_obj_release: See ttm_base_object_init
    793  1.1  riastrad  *
    794  1.1  riastrad  * Initializes an object which is compatible with the drm_prime model
    795  1.1  riastrad  * for data sharing between processes and devices.
    796  1.1  riastrad  */
    797  1.1  riastrad int ttm_prime_object_init(struct ttm_object_file *tfile, size_t size,
    798  1.1  riastrad 			  struct ttm_prime_object *prime, bool shareable,
    799  1.1  riastrad 			  enum ttm_object_type type,
    800  1.1  riastrad 			  void (*refcount_release) (struct ttm_base_object **),
    801  1.1  riastrad 			  void (*ref_obj_release) (struct ttm_base_object *,
    802  1.1  riastrad 						   enum ttm_ref_type ref_type))
    803  1.1  riastrad {
    804  1.1  riastrad 	mutex_init(&prime->mutex);
    805  1.1  riastrad 	prime->size = PAGE_ALIGN(size);
    806  1.1  riastrad 	prime->real_type = type;
    807  1.1  riastrad 	prime->dma_buf = NULL;
    808  1.1  riastrad 	prime->refcount_release = refcount_release;
    809  1.1  riastrad 	return ttm_base_object_init(tfile, &prime->base, shareable,
    810  1.1  riastrad 				    ttm_prime_type,
    811  1.1  riastrad 				    ttm_prime_refcount_release,
    812  1.1  riastrad 				    ref_obj_release);
    813  1.1  riastrad }
    814