1*592ffb21SWarner Losh /************************************************************************** 2*592ffb21SWarner Losh * 3*592ffb21SWarner Losh * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA 4*592ffb21SWarner Losh * All Rights Reserved. 5*592ffb21SWarner Losh * 6*592ffb21SWarner Losh * Permission is hereby granted, free of charge, to any person obtaining a 7*592ffb21SWarner Losh * copy of this software and associated documentation files (the 8*592ffb21SWarner Losh * "Software"), to deal in the Software without restriction, including 9*592ffb21SWarner Losh * without limitation the rights to use, copy, modify, merge, publish, 10*592ffb21SWarner Losh * distribute, sub license, and/or sell copies of the Software, and to 11*592ffb21SWarner Losh * permit persons to whom the Software is furnished to do so, subject to 12*592ffb21SWarner Losh * the following conditions: 13*592ffb21SWarner Losh * 14*592ffb21SWarner Losh * The above copyright notice and this permission notice (including the 15*592ffb21SWarner Losh * next paragraph) shall be included in all copies or substantial portions 16*592ffb21SWarner Losh * of the Software. 17*592ffb21SWarner Losh * 18*592ffb21SWarner Losh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19*592ffb21SWarner Losh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20*592ffb21SWarner Losh * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21*592ffb21SWarner Losh * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22*592ffb21SWarner Losh * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23*592ffb21SWarner Losh * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24*592ffb21SWarner Losh * USE OR OTHER DEALINGS IN THE SOFTWARE. 25*592ffb21SWarner Losh * 26*592ffb21SWarner Losh **************************************************************************/ 27*592ffb21SWarner Losh /* 28*592ffb21SWarner Losh * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> 29*592ffb21SWarner Losh */ 30*592ffb21SWarner Losh /** @file ttm_ref_object.c 31*592ffb21SWarner Losh * 32*592ffb21SWarner Losh * Base- and reference object implementation for the various 33*592ffb21SWarner Losh * ttm objects. Implements reference counting, minimal security checks 34*592ffb21SWarner Losh * and release on file close. 35*592ffb21SWarner Losh */ 36*592ffb21SWarner Losh 37*592ffb21SWarner Losh 38*592ffb21SWarner Losh #include <sys/cdefs.h> 39*592ffb21SWarner Losh /** 40*592ffb21SWarner Losh * struct ttm_object_file 41*592ffb21SWarner Losh * 42*592ffb21SWarner Losh * @tdev: Pointer to the ttm_object_device. 43*592ffb21SWarner Losh * 44*592ffb21SWarner Losh * @lock: Lock that protects the ref_list list and the 45*592ffb21SWarner Losh * ref_hash hash tables. 46*592ffb21SWarner Losh * 47*592ffb21SWarner Losh * @ref_list: List of ttm_ref_objects to be destroyed at 48*592ffb21SWarner Losh * file release. 49*592ffb21SWarner Losh * 50*592ffb21SWarner Losh * @ref_hash: Hash tables of ref objects, one per ttm_ref_type, 51*592ffb21SWarner Losh * for fast lookup of ref objects given a base object. 52*592ffb21SWarner Losh */ 53*592ffb21SWarner Losh 54*592ffb21SWarner Losh #define pr_fmt(fmt) "[TTM] " fmt 55*592ffb21SWarner Losh 56*592ffb21SWarner Losh #include <dev/drm2/drmP.h> 57*592ffb21SWarner Losh #include <dev/drm2/drm.h> 58*592ffb21SWarner Losh #include <sys/rwlock.h> 59*592ffb21SWarner Losh #include <dev/drm2/ttm/ttm_object.h> 60*592ffb21SWarner Losh #include <dev/drm2/ttm/ttm_module.h> 61*592ffb21SWarner Losh 62*592ffb21SWarner Losh struct ttm_object_file { 63*592ffb21SWarner Losh struct ttm_object_device *tdev; 64*592ffb21SWarner Losh struct rwlock lock; 65*592ffb21SWarner Losh struct list_head ref_list; 66*592ffb21SWarner Losh struct drm_open_hash ref_hash[TTM_REF_NUM]; 67*592ffb21SWarner Losh u_int refcount; 68*592ffb21SWarner Losh }; 69*592ffb21SWarner Losh 70*592ffb21SWarner Losh /** 71*592ffb21SWarner Losh * struct ttm_object_device 72*592ffb21SWarner Losh * 73*592ffb21SWarner Losh * @object_lock: lock that protects the object_hash hash table. 74*592ffb21SWarner Losh * 75*592ffb21SWarner Losh * @object_hash: hash table for fast lookup of object global names. 76*592ffb21SWarner Losh * 77*592ffb21SWarner Losh * @object_count: Per device object count. 78*592ffb21SWarner Losh * 79*592ffb21SWarner Losh * This is the per-device data structure needed for ttm object management. 80*592ffb21SWarner Losh */ 81*592ffb21SWarner Losh 82*592ffb21SWarner Losh struct ttm_object_device { 83*592ffb21SWarner Losh struct rwlock object_lock; 84*592ffb21SWarner Losh struct drm_open_hash object_hash; 85*592ffb21SWarner Losh atomic_t object_count; 86*592ffb21SWarner Losh struct ttm_mem_global *mem_glob; 87*592ffb21SWarner Losh }; 88*592ffb21SWarner Losh 89*592ffb21SWarner Losh /** 90*592ffb21SWarner Losh * struct ttm_ref_object 91*592ffb21SWarner Losh * 92*592ffb21SWarner Losh * @hash: Hash entry for the per-file object reference hash. 93*592ffb21SWarner Losh * 94*592ffb21SWarner Losh * @head: List entry for the per-file list of ref-objects. 95*592ffb21SWarner Losh * 96*592ffb21SWarner Losh * @kref: Ref count. 97*592ffb21SWarner Losh * 98*592ffb21SWarner Losh * @obj: Base object this ref object is referencing. 99*592ffb21SWarner Losh * 100*592ffb21SWarner Losh * @ref_type: Type of ref object. 101*592ffb21SWarner Losh * 102*592ffb21SWarner Losh * This is similar to an idr object, but it also has a hash table entry 103*592ffb21SWarner Losh * that allows lookup with a pointer to the referenced object as a key. In 104*592ffb21SWarner Losh * that way, one can easily detect whether a base object is referenced by 105*592ffb21SWarner Losh * a particular ttm_object_file. It also carries a ref count to avoid creating 106*592ffb21SWarner Losh * multiple ref objects if a ttm_object_file references the same base 107*592ffb21SWarner Losh * object more than once. 108*592ffb21SWarner Losh */ 109*592ffb21SWarner Losh 110*592ffb21SWarner Losh struct ttm_ref_object { 111*592ffb21SWarner Losh struct drm_hash_item hash; 112*592ffb21SWarner Losh struct list_head head; 113*592ffb21SWarner Losh u_int kref; 114*592ffb21SWarner Losh enum ttm_ref_type ref_type; 115*592ffb21SWarner Losh struct ttm_base_object *obj; 116*592ffb21SWarner Losh struct ttm_object_file *tfile; 117*592ffb21SWarner Losh }; 118*592ffb21SWarner Losh 119*592ffb21SWarner Losh MALLOC_DEFINE(M_TTM_OBJ_FILE, "ttm_obj_file", "TTM File Objects"); 120*592ffb21SWarner Losh 121*592ffb21SWarner Losh static inline struct ttm_object_file * 122*592ffb21SWarner Losh ttm_object_file_ref(struct ttm_object_file *tfile) 123*592ffb21SWarner Losh { 124*592ffb21SWarner Losh refcount_acquire(&tfile->refcount); 125*592ffb21SWarner Losh return tfile; 126*592ffb21SWarner Losh } 127*592ffb21SWarner Losh 128*592ffb21SWarner Losh static void ttm_object_file_destroy(struct ttm_object_file *tfile) 129*592ffb21SWarner Losh { 130*592ffb21SWarner Losh 131*592ffb21SWarner Losh free(tfile, M_TTM_OBJ_FILE); 132*592ffb21SWarner Losh } 133*592ffb21SWarner Losh 134*592ffb21SWarner Losh 135*592ffb21SWarner Losh static inline void ttm_object_file_unref(struct ttm_object_file **p_tfile) 136*592ffb21SWarner Losh { 137*592ffb21SWarner Losh struct ttm_object_file *tfile = *p_tfile; 138*592ffb21SWarner Losh 139*592ffb21SWarner Losh *p_tfile = NULL; 140*592ffb21SWarner Losh if (refcount_release(&tfile->refcount)) 141*592ffb21SWarner Losh ttm_object_file_destroy(tfile); 142*592ffb21SWarner Losh } 143*592ffb21SWarner Losh 144*592ffb21SWarner Losh 145*592ffb21SWarner Losh int ttm_base_object_init(struct ttm_object_file *tfile, 146*592ffb21SWarner Losh struct ttm_base_object *base, 147*592ffb21SWarner Losh bool shareable, 148*592ffb21SWarner Losh enum ttm_object_type object_type, 149*592ffb21SWarner Losh void (*rcount_release) (struct ttm_base_object **), 150*592ffb21SWarner Losh void (*ref_obj_release) (struct ttm_base_object *, 151*592ffb21SWarner Losh enum ttm_ref_type ref_type)) 152*592ffb21SWarner Losh { 153*592ffb21SWarner Losh struct ttm_object_device *tdev = tfile->tdev; 154*592ffb21SWarner Losh int ret; 155*592ffb21SWarner Losh 156*592ffb21SWarner Losh base->shareable = shareable; 157*592ffb21SWarner Losh base->tfile = ttm_object_file_ref(tfile); 158*592ffb21SWarner Losh base->refcount_release = rcount_release; 159*592ffb21SWarner Losh base->ref_obj_release = ref_obj_release; 160*592ffb21SWarner Losh base->object_type = object_type; 161*592ffb21SWarner Losh refcount_init(&base->refcount, 1); 162*592ffb21SWarner Losh rw_init(&tdev->object_lock, "ttmbao"); 163*592ffb21SWarner Losh rw_wlock(&tdev->object_lock); 164*592ffb21SWarner Losh ret = drm_ht_just_insert_please(&tdev->object_hash, 165*592ffb21SWarner Losh &base->hash, 166*592ffb21SWarner Losh (unsigned long)base, 31, 0, 0); 167*592ffb21SWarner Losh rw_wunlock(&tdev->object_lock); 168*592ffb21SWarner Losh if (unlikely(ret != 0)) 169*592ffb21SWarner Losh goto out_err0; 170*592ffb21SWarner Losh 171*592ffb21SWarner Losh ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); 172*592ffb21SWarner Losh if (unlikely(ret != 0)) 173*592ffb21SWarner Losh goto out_err1; 174*592ffb21SWarner Losh 175*592ffb21SWarner Losh ttm_base_object_unref(&base); 176*592ffb21SWarner Losh 177*592ffb21SWarner Losh return 0; 178*592ffb21SWarner Losh out_err1: 179*592ffb21SWarner Losh rw_wlock(&tdev->object_lock); 180*592ffb21SWarner Losh (void)drm_ht_remove_item(&tdev->object_hash, &base->hash); 181*592ffb21SWarner Losh rw_wunlock(&tdev->object_lock); 182*592ffb21SWarner Losh out_err0: 183*592ffb21SWarner Losh return ret; 184*592ffb21SWarner Losh } 185*592ffb21SWarner Losh 186*592ffb21SWarner Losh static void ttm_release_base(struct ttm_base_object *base) 187*592ffb21SWarner Losh { 188*592ffb21SWarner Losh struct ttm_object_device *tdev = base->tfile->tdev; 189*592ffb21SWarner Losh 190*592ffb21SWarner Losh (void)drm_ht_remove_item(&tdev->object_hash, &base->hash); 191*592ffb21SWarner Losh rw_wunlock(&tdev->object_lock); 192*592ffb21SWarner Losh /* 193*592ffb21SWarner Losh * Note: We don't use synchronize_rcu() here because it's far 194*592ffb21SWarner Losh * too slow. It's up to the user to free the object using 195*592ffb21SWarner Losh * call_rcu() or ttm_base_object_kfree(). 196*592ffb21SWarner Losh */ 197*592ffb21SWarner Losh 198*592ffb21SWarner Losh if (base->refcount_release) { 199*592ffb21SWarner Losh ttm_object_file_unref(&base->tfile); 200*592ffb21SWarner Losh base->refcount_release(&base); 201*592ffb21SWarner Losh } 202*592ffb21SWarner Losh rw_wlock(&tdev->object_lock); 203*592ffb21SWarner Losh } 204*592ffb21SWarner Losh 205*592ffb21SWarner Losh void ttm_base_object_unref(struct ttm_base_object **p_base) 206*592ffb21SWarner Losh { 207*592ffb21SWarner Losh struct ttm_base_object *base = *p_base; 208*592ffb21SWarner Losh struct ttm_object_device *tdev = base->tfile->tdev; 209*592ffb21SWarner Losh 210*592ffb21SWarner Losh *p_base = NULL; 211*592ffb21SWarner Losh 212*592ffb21SWarner Losh /* 213*592ffb21SWarner Losh * Need to take the lock here to avoid racing with 214*592ffb21SWarner Losh * users trying to look up the object. 215*592ffb21SWarner Losh */ 216*592ffb21SWarner Losh 217*592ffb21SWarner Losh rw_wlock(&tdev->object_lock); 218*592ffb21SWarner Losh if (refcount_release(&base->refcount)) 219*592ffb21SWarner Losh ttm_release_base(base); 220*592ffb21SWarner Losh rw_wunlock(&tdev->object_lock); 221*592ffb21SWarner Losh } 222*592ffb21SWarner Losh 223*592ffb21SWarner Losh struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, 224*592ffb21SWarner Losh uint32_t key) 225*592ffb21SWarner Losh { 226*592ffb21SWarner Losh struct ttm_object_device *tdev = tfile->tdev; 227*592ffb21SWarner Losh struct ttm_base_object *base; 228*592ffb21SWarner Losh struct drm_hash_item *hash; 229*592ffb21SWarner Losh int ret; 230*592ffb21SWarner Losh 231*592ffb21SWarner Losh rw_rlock(&tdev->object_lock); 232*592ffb21SWarner Losh ret = drm_ht_find_item(&tdev->object_hash, key, &hash); 233*592ffb21SWarner Losh 234*592ffb21SWarner Losh if (ret == 0) { 235*592ffb21SWarner Losh base = drm_hash_entry(hash, struct ttm_base_object, hash); 236*592ffb21SWarner Losh refcount_acquire(&base->refcount); 237*592ffb21SWarner Losh } 238*592ffb21SWarner Losh rw_runlock(&tdev->object_lock); 239*592ffb21SWarner Losh 240*592ffb21SWarner Losh if (unlikely(ret != 0)) 241*592ffb21SWarner Losh return NULL; 242*592ffb21SWarner Losh 243*592ffb21SWarner Losh if (tfile != base->tfile && !base->shareable) { 244*592ffb21SWarner Losh printf("[TTM] Attempted access of non-shareable object %p\n", 245*592ffb21SWarner Losh base); 246*592ffb21SWarner Losh ttm_base_object_unref(&base); 247*592ffb21SWarner Losh return NULL; 248*592ffb21SWarner Losh } 249*592ffb21SWarner Losh 250*592ffb21SWarner Losh return base; 251*592ffb21SWarner Losh } 252*592ffb21SWarner Losh 253*592ffb21SWarner Losh MALLOC_DEFINE(M_TTM_OBJ_REF, "ttm_obj_ref", "TTM Ref Objects"); 254*592ffb21SWarner Losh 255*592ffb21SWarner Losh int ttm_ref_object_add(struct ttm_object_file *tfile, 256*592ffb21SWarner Losh struct ttm_base_object *base, 257*592ffb21SWarner Losh enum ttm_ref_type ref_type, bool *existed) 258*592ffb21SWarner Losh { 259*592ffb21SWarner Losh struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; 260*592ffb21SWarner Losh struct ttm_ref_object *ref; 261*592ffb21SWarner Losh struct drm_hash_item *hash; 262*592ffb21SWarner Losh struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; 263*592ffb21SWarner Losh int ret = -EINVAL; 264*592ffb21SWarner Losh 265*592ffb21SWarner Losh if (existed != NULL) 266*592ffb21SWarner Losh *existed = true; 267*592ffb21SWarner Losh 268*592ffb21SWarner Losh while (ret == -EINVAL) { 269*592ffb21SWarner Losh rw_rlock(&tfile->lock); 270*592ffb21SWarner Losh ret = drm_ht_find_item(ht, base->hash.key, &hash); 271*592ffb21SWarner Losh 272*592ffb21SWarner Losh if (ret == 0) { 273*592ffb21SWarner Losh ref = drm_hash_entry(hash, struct ttm_ref_object, hash); 274*592ffb21SWarner Losh refcount_acquire(&ref->kref); 275*592ffb21SWarner Losh rw_runlock(&tfile->lock); 276*592ffb21SWarner Losh break; 277*592ffb21SWarner Losh } 278*592ffb21SWarner Losh 279*592ffb21SWarner Losh rw_runlock(&tfile->lock); 280*592ffb21SWarner Losh ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref), 281*592ffb21SWarner Losh false, false); 282*592ffb21SWarner Losh if (unlikely(ret != 0)) 283*592ffb21SWarner Losh return ret; 284*592ffb21SWarner Losh ref = malloc(sizeof(*ref), M_TTM_OBJ_REF, M_WAITOK); 285*592ffb21SWarner Losh ref->hash.key = base->hash.key; 286*592ffb21SWarner Losh ref->obj = base; 287*592ffb21SWarner Losh ref->tfile = tfile; 288*592ffb21SWarner Losh ref->ref_type = ref_type; 289*592ffb21SWarner Losh refcount_init(&ref->kref, 1); 290*592ffb21SWarner Losh 291*592ffb21SWarner Losh rw_wlock(&tfile->lock); 292*592ffb21SWarner Losh ret = drm_ht_insert_item(ht, &ref->hash); 293*592ffb21SWarner Losh 294*592ffb21SWarner Losh if (ret == 0) { 295*592ffb21SWarner Losh list_add_tail(&ref->head, &tfile->ref_list); 296*592ffb21SWarner Losh refcount_acquire(&base->refcount); 297*592ffb21SWarner Losh rw_wunlock(&tfile->lock); 298*592ffb21SWarner Losh if (existed != NULL) 299*592ffb21SWarner Losh *existed = false; 300*592ffb21SWarner Losh break; 301*592ffb21SWarner Losh } 302*592ffb21SWarner Losh 303*592ffb21SWarner Losh rw_wunlock(&tfile->lock); 304*592ffb21SWarner Losh MPASS(ret == -EINVAL); 305*592ffb21SWarner Losh 306*592ffb21SWarner Losh ttm_mem_global_free(mem_glob, sizeof(*ref)); 307*592ffb21SWarner Losh free(ref, M_TTM_OBJ_REF); 308*592ffb21SWarner Losh } 309*592ffb21SWarner Losh 310*592ffb21SWarner Losh return ret; 311*592ffb21SWarner Losh } 312*592ffb21SWarner Losh 313*592ffb21SWarner Losh static void ttm_ref_object_release(struct ttm_ref_object *ref) 314*592ffb21SWarner Losh { 315*592ffb21SWarner Losh struct ttm_base_object *base = ref->obj; 316*592ffb21SWarner Losh struct ttm_object_file *tfile = ref->tfile; 317*592ffb21SWarner Losh struct drm_open_hash *ht; 318*592ffb21SWarner Losh struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; 319*592ffb21SWarner Losh 320*592ffb21SWarner Losh ht = &tfile->ref_hash[ref->ref_type]; 321*592ffb21SWarner Losh (void)drm_ht_remove_item(ht, &ref->hash); 322*592ffb21SWarner Losh list_del(&ref->head); 323*592ffb21SWarner Losh rw_wunlock(&tfile->lock); 324*592ffb21SWarner Losh 325*592ffb21SWarner Losh if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release) 326*592ffb21SWarner Losh base->ref_obj_release(base, ref->ref_type); 327*592ffb21SWarner Losh 328*592ffb21SWarner Losh ttm_base_object_unref(&ref->obj); 329*592ffb21SWarner Losh ttm_mem_global_free(mem_glob, sizeof(*ref)); 330*592ffb21SWarner Losh free(ref, M_TTM_OBJ_REF); 331*592ffb21SWarner Losh rw_wlock(&tfile->lock); 332*592ffb21SWarner Losh } 333*592ffb21SWarner Losh 334*592ffb21SWarner Losh int ttm_ref_object_base_unref(struct ttm_object_file *tfile, 335*592ffb21SWarner Losh unsigned long key, enum ttm_ref_type ref_type) 336*592ffb21SWarner Losh { 337*592ffb21SWarner Losh struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; 338*592ffb21SWarner Losh struct ttm_ref_object *ref; 339*592ffb21SWarner Losh struct drm_hash_item *hash; 340*592ffb21SWarner Losh int ret; 341*592ffb21SWarner Losh 342*592ffb21SWarner Losh rw_wlock(&tfile->lock); 343*592ffb21SWarner Losh ret = drm_ht_find_item(ht, key, &hash); 344*592ffb21SWarner Losh if (unlikely(ret != 0)) { 345*592ffb21SWarner Losh rw_wunlock(&tfile->lock); 346*592ffb21SWarner Losh return -EINVAL; 347*592ffb21SWarner Losh } 348*592ffb21SWarner Losh ref = drm_hash_entry(hash, struct ttm_ref_object, hash); 349*592ffb21SWarner Losh if (refcount_release(&ref->kref)) 350*592ffb21SWarner Losh ttm_ref_object_release(ref); 351*592ffb21SWarner Losh rw_wunlock(&tfile->lock); 352*592ffb21SWarner Losh return 0; 353*592ffb21SWarner Losh } 354*592ffb21SWarner Losh 355*592ffb21SWarner Losh void ttm_object_file_release(struct ttm_object_file **p_tfile) 356*592ffb21SWarner Losh { 357*592ffb21SWarner Losh struct ttm_ref_object *ref; 358*592ffb21SWarner Losh struct list_head *list; 359*592ffb21SWarner Losh unsigned int i; 360*592ffb21SWarner Losh struct ttm_object_file *tfile = *p_tfile; 361*592ffb21SWarner Losh 362*592ffb21SWarner Losh *p_tfile = NULL; 363*592ffb21SWarner Losh rw_wlock(&tfile->lock); 364*592ffb21SWarner Losh 365*592ffb21SWarner Losh /* 366*592ffb21SWarner Losh * Since we release the lock within the loop, we have to 367*592ffb21SWarner Losh * restart it from the beginning each time. 368*592ffb21SWarner Losh */ 369*592ffb21SWarner Losh 370*592ffb21SWarner Losh while (!list_empty(&tfile->ref_list)) { 371*592ffb21SWarner Losh list = tfile->ref_list.next; 372*592ffb21SWarner Losh ref = list_entry(list, struct ttm_ref_object, head); 373*592ffb21SWarner Losh ttm_ref_object_release(ref); 374*592ffb21SWarner Losh } 375*592ffb21SWarner Losh 376*592ffb21SWarner Losh for (i = 0; i < TTM_REF_NUM; ++i) 377*592ffb21SWarner Losh drm_ht_remove(&tfile->ref_hash[i]); 378*592ffb21SWarner Losh 379*592ffb21SWarner Losh rw_wunlock(&tfile->lock); 380*592ffb21SWarner Losh ttm_object_file_unref(&tfile); 381*592ffb21SWarner Losh } 382*592ffb21SWarner Losh 383*592ffb21SWarner Losh struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev, 384*592ffb21SWarner Losh unsigned int hash_order) 385*592ffb21SWarner Losh { 386*592ffb21SWarner Losh struct ttm_object_file *tfile; 387*592ffb21SWarner Losh unsigned int i; 388*592ffb21SWarner Losh unsigned int j = 0; 389*592ffb21SWarner Losh int ret; 390*592ffb21SWarner Losh 391*592ffb21SWarner Losh tfile = malloc(sizeof(*tfile), M_TTM_OBJ_FILE, M_WAITOK); 392*592ffb21SWarner Losh rw_init(&tfile->lock, "ttmfo"); 393*592ffb21SWarner Losh tfile->tdev = tdev; 394*592ffb21SWarner Losh refcount_init(&tfile->refcount, 1); 395*592ffb21SWarner Losh INIT_LIST_HEAD(&tfile->ref_list); 396*592ffb21SWarner Losh 397*592ffb21SWarner Losh for (i = 0; i < TTM_REF_NUM; ++i) { 398*592ffb21SWarner Losh ret = drm_ht_create(&tfile->ref_hash[i], hash_order); 399*592ffb21SWarner Losh if (ret) { 400*592ffb21SWarner Losh j = i; 401*592ffb21SWarner Losh goto out_err; 402*592ffb21SWarner Losh } 403*592ffb21SWarner Losh } 404*592ffb21SWarner Losh 405*592ffb21SWarner Losh return tfile; 406*592ffb21SWarner Losh out_err: 407*592ffb21SWarner Losh for (i = 0; i < j; ++i) 408*592ffb21SWarner Losh drm_ht_remove(&tfile->ref_hash[i]); 409*592ffb21SWarner Losh 410*592ffb21SWarner Losh free(tfile, M_TTM_OBJ_FILE); 411*592ffb21SWarner Losh 412*592ffb21SWarner Losh return NULL; 413*592ffb21SWarner Losh } 414*592ffb21SWarner Losh 415*592ffb21SWarner Losh MALLOC_DEFINE(M_TTM_OBJ_DEV, "ttm_obj_dev", "TTM Device Objects"); 416*592ffb21SWarner Losh 417*592ffb21SWarner Losh struct ttm_object_device *ttm_object_device_init(struct ttm_mem_global 418*592ffb21SWarner Losh *mem_glob, 419*592ffb21SWarner Losh unsigned int hash_order) 420*592ffb21SWarner Losh { 421*592ffb21SWarner Losh struct ttm_object_device *tdev; 422*592ffb21SWarner Losh int ret; 423*592ffb21SWarner Losh 424*592ffb21SWarner Losh tdev = malloc(sizeof(*tdev), M_TTM_OBJ_DEV, M_WAITOK); 425*592ffb21SWarner Losh tdev->mem_glob = mem_glob; 426*592ffb21SWarner Losh rw_init(&tdev->object_lock, "ttmdo"); 427*592ffb21SWarner Losh atomic_set(&tdev->object_count, 0); 428*592ffb21SWarner Losh ret = drm_ht_create(&tdev->object_hash, hash_order); 429*592ffb21SWarner Losh 430*592ffb21SWarner Losh if (ret == 0) 431*592ffb21SWarner Losh return tdev; 432*592ffb21SWarner Losh 433*592ffb21SWarner Losh free(tdev, M_TTM_OBJ_DEV); 434*592ffb21SWarner Losh return NULL; 435*592ffb21SWarner Losh } 436*592ffb21SWarner Losh 437*592ffb21SWarner Losh void ttm_object_device_release(struct ttm_object_device **p_tdev) 438*592ffb21SWarner Losh { 439*592ffb21SWarner Losh struct ttm_object_device *tdev = *p_tdev; 440*592ffb21SWarner Losh 441*592ffb21SWarner Losh *p_tdev = NULL; 442*592ffb21SWarner Losh 443*592ffb21SWarner Losh rw_wlock(&tdev->object_lock); 444*592ffb21SWarner Losh drm_ht_remove(&tdev->object_hash); 445*592ffb21SWarner Losh rw_wunlock(&tdev->object_lock); 446*592ffb21SWarner Losh 447*592ffb21SWarner Losh free(tdev, M_TTM_OBJ_DEV); 448*592ffb21SWarner Losh } 449