1*673a394bSEric Anholt /* 2*673a394bSEric Anholt * Copyright © 2008 Intel Corporation 3*673a394bSEric Anholt * 4*673a394bSEric Anholt * Permission is hereby granted, free of charge, to any person obtaining a 5*673a394bSEric Anholt * copy of this software and associated documentation files (the "Software"), 6*673a394bSEric Anholt * to deal in the Software without restriction, including without limitation 7*673a394bSEric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*673a394bSEric Anholt * and/or sell copies of the Software, and to permit persons to whom the 9*673a394bSEric Anholt * Software is furnished to do so, subject to the following conditions: 10*673a394bSEric Anholt * 11*673a394bSEric Anholt * The above copyright notice and this permission notice (including the next 12*673a394bSEric Anholt * paragraph) shall be included in all copies or substantial portions of the 13*673a394bSEric Anholt * Software. 14*673a394bSEric Anholt * 15*673a394bSEric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*673a394bSEric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*673a394bSEric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*673a394bSEric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*673a394bSEric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20*673a394bSEric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21*673a394bSEric Anholt * IN THE SOFTWARE. 22*673a394bSEric Anholt * 23*673a394bSEric Anholt * Authors: 24*673a394bSEric Anholt * Eric Anholt <eric@anholt.net> 25*673a394bSEric Anholt * 26*673a394bSEric Anholt */ 27*673a394bSEric Anholt 28*673a394bSEric Anholt #include <linux/types.h> 29*673a394bSEric Anholt #include <linux/slab.h> 30*673a394bSEric Anholt #include <linux/mm.h> 31*673a394bSEric Anholt #include <linux/uaccess.h> 32*673a394bSEric Anholt #include <linux/fs.h> 33*673a394bSEric Anholt #include <linux/file.h> 34*673a394bSEric Anholt #include <linux/module.h> 35*673a394bSEric Anholt #include <linux/mman.h> 36*673a394bSEric Anholt #include <linux/pagemap.h> 37*673a394bSEric Anholt #include "drmP.h" 38*673a394bSEric Anholt 39*673a394bSEric Anholt /** @file drm_gem.c 40*673a394bSEric Anholt * 41*673a394bSEric Anholt * This file provides some of the base ioctls and library routines for 42*673a394bSEric Anholt * the graphics memory manager implemented by each device driver. 43*673a394bSEric Anholt * 44*673a394bSEric Anholt * Because various devices have different requirements in terms of 45*673a394bSEric Anholt * synchronization and migration strategies, implementing that is left up to 46*673a394bSEric Anholt * the driver, and all that the general API provides should be generic -- 47*673a394bSEric Anholt * allocating objects, reading/writing data with the cpu, freeing objects. 48*673a394bSEric Anholt * Even there, platform-dependent optimizations for reading/writing data with 49*673a394bSEric Anholt * the CPU mean we'll likely hook those out to driver-specific calls. However, 50*673a394bSEric Anholt * the DRI2 implementation wants to have at least allocate/mmap be generic. 51*673a394bSEric Anholt * 52*673a394bSEric Anholt * The goal was to have swap-backed object allocation managed through 53*673a394bSEric Anholt * struct file. However, file descriptors as handles to a struct file have 54*673a394bSEric Anholt * two major failings: 55*673a394bSEric Anholt * - Process limits prevent more than 1024 or so being used at a time by 56*673a394bSEric Anholt * default. 57*673a394bSEric Anholt * - Inability to allocate high fds will aggravate the X Server's select() 58*673a394bSEric Anholt * handling, and likely that of many GL client applications as well. 59*673a394bSEric Anholt * 60*673a394bSEric Anholt * This led to a plan of using our own integer IDs (called handles, following 61*673a394bSEric Anholt * DRM terminology) to mimic fds, and implement the fd syscalls we need as 62*673a394bSEric Anholt * ioctls. The objects themselves will still include the struct file so 63*673a394bSEric Anholt * that we can transition to fds if the required kernel infrastructure shows 64*673a394bSEric Anholt * up at a later date, and as our interface with shmfs for memory allocation. 65*673a394bSEric Anholt */ 66*673a394bSEric Anholt 67*673a394bSEric Anholt /** 68*673a394bSEric Anholt * Initialize the GEM device fields 69*673a394bSEric Anholt */ 70*673a394bSEric Anholt 71*673a394bSEric Anholt int 72*673a394bSEric Anholt drm_gem_init(struct drm_device *dev) 73*673a394bSEric Anholt { 74*673a394bSEric Anholt spin_lock_init(&dev->object_name_lock); 75*673a394bSEric Anholt idr_init(&dev->object_name_idr); 76*673a394bSEric Anholt atomic_set(&dev->object_count, 0); 77*673a394bSEric Anholt atomic_set(&dev->object_memory, 0); 78*673a394bSEric Anholt atomic_set(&dev->pin_count, 0); 79*673a394bSEric Anholt atomic_set(&dev->pin_memory, 0); 80*673a394bSEric Anholt atomic_set(&dev->gtt_count, 0); 81*673a394bSEric Anholt atomic_set(&dev->gtt_memory, 0); 82*673a394bSEric Anholt return 0; 83*673a394bSEric Anholt } 84*673a394bSEric Anholt 85*673a394bSEric Anholt /** 86*673a394bSEric Anholt * Allocate a GEM object of the specified size with shmfs backing store 87*673a394bSEric Anholt */ 88*673a394bSEric Anholt struct drm_gem_object * 89*673a394bSEric Anholt drm_gem_object_alloc(struct drm_device *dev, size_t size) 90*673a394bSEric Anholt { 91*673a394bSEric Anholt struct drm_gem_object *obj; 92*673a394bSEric Anholt 93*673a394bSEric Anholt BUG_ON((size & (PAGE_SIZE - 1)) != 0); 94*673a394bSEric Anholt 95*673a394bSEric Anholt obj = kcalloc(1, sizeof(*obj), GFP_KERNEL); 96*673a394bSEric Anholt 97*673a394bSEric Anholt obj->dev = dev; 98*673a394bSEric Anholt obj->filp = shmem_file_setup("drm mm object", size, 0); 99*673a394bSEric Anholt if (IS_ERR(obj->filp)) { 100*673a394bSEric Anholt kfree(obj); 101*673a394bSEric Anholt return NULL; 102*673a394bSEric Anholt } 103*673a394bSEric Anholt 104*673a394bSEric Anholt kref_init(&obj->refcount); 105*673a394bSEric Anholt kref_init(&obj->handlecount); 106*673a394bSEric Anholt obj->size = size; 107*673a394bSEric Anholt if (dev->driver->gem_init_object != NULL && 108*673a394bSEric Anholt dev->driver->gem_init_object(obj) != 0) { 109*673a394bSEric Anholt fput(obj->filp); 110*673a394bSEric Anholt kfree(obj); 111*673a394bSEric Anholt return NULL; 112*673a394bSEric Anholt } 113*673a394bSEric Anholt atomic_inc(&dev->object_count); 114*673a394bSEric Anholt atomic_add(obj->size, &dev->object_memory); 115*673a394bSEric Anholt return obj; 116*673a394bSEric Anholt } 117*673a394bSEric Anholt EXPORT_SYMBOL(drm_gem_object_alloc); 118*673a394bSEric Anholt 119*673a394bSEric Anholt /** 120*673a394bSEric Anholt * Removes the mapping from handle to filp for this object. 121*673a394bSEric Anholt */ 122*673a394bSEric Anholt static int 123*673a394bSEric Anholt drm_gem_handle_delete(struct drm_file *filp, int handle) 124*673a394bSEric Anholt { 125*673a394bSEric Anholt struct drm_device *dev; 126*673a394bSEric Anholt struct drm_gem_object *obj; 127*673a394bSEric Anholt 128*673a394bSEric Anholt /* This is gross. The idr system doesn't let us try a delete and 129*673a394bSEric Anholt * return an error code. It just spews if you fail at deleting. 130*673a394bSEric Anholt * So, we have to grab a lock around finding the object and then 131*673a394bSEric Anholt * doing the delete on it and dropping the refcount, or the user 132*673a394bSEric Anholt * could race us to double-decrement the refcount and cause a 133*673a394bSEric Anholt * use-after-free later. Given the frequency of our handle lookups, 134*673a394bSEric Anholt * we may want to use ida for number allocation and a hash table 135*673a394bSEric Anholt * for the pointers, anyway. 136*673a394bSEric Anholt */ 137*673a394bSEric Anholt spin_lock(&filp->table_lock); 138*673a394bSEric Anholt 139*673a394bSEric Anholt /* Check if we currently have a reference on the object */ 140*673a394bSEric Anholt obj = idr_find(&filp->object_idr, handle); 141*673a394bSEric Anholt if (obj == NULL) { 142*673a394bSEric Anholt spin_unlock(&filp->table_lock); 143*673a394bSEric Anholt return -EINVAL; 144*673a394bSEric Anholt } 145*673a394bSEric Anholt dev = obj->dev; 146*673a394bSEric Anholt 147*673a394bSEric Anholt /* Release reference and decrement refcount. */ 148*673a394bSEric Anholt idr_remove(&filp->object_idr, handle); 149*673a394bSEric Anholt spin_unlock(&filp->table_lock); 150*673a394bSEric Anholt 151*673a394bSEric Anholt mutex_lock(&dev->struct_mutex); 152*673a394bSEric Anholt drm_gem_object_handle_unreference(obj); 153*673a394bSEric Anholt mutex_unlock(&dev->struct_mutex); 154*673a394bSEric Anholt 155*673a394bSEric Anholt return 0; 156*673a394bSEric Anholt } 157*673a394bSEric Anholt 158*673a394bSEric Anholt /** 159*673a394bSEric Anholt * Create a handle for this object. This adds a handle reference 160*673a394bSEric Anholt * to the object, which includes a regular reference count. Callers 161*673a394bSEric Anholt * will likely want to dereference the object afterwards. 162*673a394bSEric Anholt */ 163*673a394bSEric Anholt int 164*673a394bSEric Anholt drm_gem_handle_create(struct drm_file *file_priv, 165*673a394bSEric Anholt struct drm_gem_object *obj, 166*673a394bSEric Anholt int *handlep) 167*673a394bSEric Anholt { 168*673a394bSEric Anholt int ret; 169*673a394bSEric Anholt 170*673a394bSEric Anholt /* 171*673a394bSEric Anholt * Get the user-visible handle using idr. 172*673a394bSEric Anholt */ 173*673a394bSEric Anholt again: 174*673a394bSEric Anholt /* ensure there is space available to allocate a handle */ 175*673a394bSEric Anholt if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0) 176*673a394bSEric Anholt return -ENOMEM; 177*673a394bSEric Anholt 178*673a394bSEric Anholt /* do the allocation under our spinlock */ 179*673a394bSEric Anholt spin_lock(&file_priv->table_lock); 180*673a394bSEric Anholt ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep); 181*673a394bSEric Anholt spin_unlock(&file_priv->table_lock); 182*673a394bSEric Anholt if (ret == -EAGAIN) 183*673a394bSEric Anholt goto again; 184*673a394bSEric Anholt 185*673a394bSEric Anholt if (ret != 0) 186*673a394bSEric Anholt return ret; 187*673a394bSEric Anholt 188*673a394bSEric Anholt drm_gem_object_handle_reference(obj); 189*673a394bSEric Anholt return 0; 190*673a394bSEric Anholt } 191*673a394bSEric Anholt EXPORT_SYMBOL(drm_gem_handle_create); 192*673a394bSEric Anholt 193*673a394bSEric Anholt /** Returns a reference to the object named by the handle. */ 194*673a394bSEric Anholt struct drm_gem_object * 195*673a394bSEric Anholt drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, 196*673a394bSEric Anholt int handle) 197*673a394bSEric Anholt { 198*673a394bSEric Anholt struct drm_gem_object *obj; 199*673a394bSEric Anholt 200*673a394bSEric Anholt spin_lock(&filp->table_lock); 201*673a394bSEric Anholt 202*673a394bSEric Anholt /* Check if we currently have a reference on the object */ 203*673a394bSEric Anholt obj = idr_find(&filp->object_idr, handle); 204*673a394bSEric Anholt if (obj == NULL) { 205*673a394bSEric Anholt spin_unlock(&filp->table_lock); 206*673a394bSEric Anholt return NULL; 207*673a394bSEric Anholt } 208*673a394bSEric Anholt 209*673a394bSEric Anholt drm_gem_object_reference(obj); 210*673a394bSEric Anholt 211*673a394bSEric Anholt spin_unlock(&filp->table_lock); 212*673a394bSEric Anholt 213*673a394bSEric Anholt return obj; 214*673a394bSEric Anholt } 215*673a394bSEric Anholt EXPORT_SYMBOL(drm_gem_object_lookup); 216*673a394bSEric Anholt 217*673a394bSEric Anholt /** 218*673a394bSEric Anholt * Releases the handle to an mm object. 219*673a394bSEric Anholt */ 220*673a394bSEric Anholt int 221*673a394bSEric Anholt drm_gem_close_ioctl(struct drm_device *dev, void *data, 222*673a394bSEric Anholt struct drm_file *file_priv) 223*673a394bSEric Anholt { 224*673a394bSEric Anholt struct drm_gem_close *args = data; 225*673a394bSEric Anholt int ret; 226*673a394bSEric Anholt 227*673a394bSEric Anholt if (!(dev->driver->driver_features & DRIVER_GEM)) 228*673a394bSEric Anholt return -ENODEV; 229*673a394bSEric Anholt 230*673a394bSEric Anholt ret = drm_gem_handle_delete(file_priv, args->handle); 231*673a394bSEric Anholt 232*673a394bSEric Anholt return ret; 233*673a394bSEric Anholt } 234*673a394bSEric Anholt 235*673a394bSEric Anholt /** 236*673a394bSEric Anholt * Create a global name for an object, returning the name. 237*673a394bSEric Anholt * 238*673a394bSEric Anholt * Note that the name does not hold a reference; when the object 239*673a394bSEric Anholt * is freed, the name goes away. 240*673a394bSEric Anholt */ 241*673a394bSEric Anholt int 242*673a394bSEric Anholt drm_gem_flink_ioctl(struct drm_device *dev, void *data, 243*673a394bSEric Anholt struct drm_file *file_priv) 244*673a394bSEric Anholt { 245*673a394bSEric Anholt struct drm_gem_flink *args = data; 246*673a394bSEric Anholt struct drm_gem_object *obj; 247*673a394bSEric Anholt int ret; 248*673a394bSEric Anholt 249*673a394bSEric Anholt if (!(dev->driver->driver_features & DRIVER_GEM)) 250*673a394bSEric Anholt return -ENODEV; 251*673a394bSEric Anholt 252*673a394bSEric Anholt obj = drm_gem_object_lookup(dev, file_priv, args->handle); 253*673a394bSEric Anholt if (obj == NULL) 254*673a394bSEric Anholt return -EINVAL; 255*673a394bSEric Anholt 256*673a394bSEric Anholt again: 257*673a394bSEric Anholt if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) 258*673a394bSEric Anholt return -ENOMEM; 259*673a394bSEric Anholt 260*673a394bSEric Anholt spin_lock(&dev->object_name_lock); 261*673a394bSEric Anholt if (obj->name) { 262*673a394bSEric Anholt spin_unlock(&dev->object_name_lock); 263*673a394bSEric Anholt return -EEXIST; 264*673a394bSEric Anholt } 265*673a394bSEric Anholt ret = idr_get_new_above(&dev->object_name_idr, obj, 1, 266*673a394bSEric Anholt &obj->name); 267*673a394bSEric Anholt spin_unlock(&dev->object_name_lock); 268*673a394bSEric Anholt if (ret == -EAGAIN) 269*673a394bSEric Anholt goto again; 270*673a394bSEric Anholt 271*673a394bSEric Anholt if (ret != 0) { 272*673a394bSEric Anholt mutex_lock(&dev->struct_mutex); 273*673a394bSEric Anholt drm_gem_object_unreference(obj); 274*673a394bSEric Anholt mutex_unlock(&dev->struct_mutex); 275*673a394bSEric Anholt return ret; 276*673a394bSEric Anholt } 277*673a394bSEric Anholt 278*673a394bSEric Anholt /* 279*673a394bSEric Anholt * Leave the reference from the lookup around as the 280*673a394bSEric Anholt * name table now holds one 281*673a394bSEric Anholt */ 282*673a394bSEric Anholt args->name = (uint64_t) obj->name; 283*673a394bSEric Anholt 284*673a394bSEric Anholt return 0; 285*673a394bSEric Anholt } 286*673a394bSEric Anholt 287*673a394bSEric Anholt /** 288*673a394bSEric Anholt * Open an object using the global name, returning a handle and the size. 289*673a394bSEric Anholt * 290*673a394bSEric Anholt * This handle (of course) holds a reference to the object, so the object 291*673a394bSEric Anholt * will not go away until the handle is deleted. 292*673a394bSEric Anholt */ 293*673a394bSEric Anholt int 294*673a394bSEric Anholt drm_gem_open_ioctl(struct drm_device *dev, void *data, 295*673a394bSEric Anholt struct drm_file *file_priv) 296*673a394bSEric Anholt { 297*673a394bSEric Anholt struct drm_gem_open *args = data; 298*673a394bSEric Anholt struct drm_gem_object *obj; 299*673a394bSEric Anholt int ret; 300*673a394bSEric Anholt int handle; 301*673a394bSEric Anholt 302*673a394bSEric Anholt if (!(dev->driver->driver_features & DRIVER_GEM)) 303*673a394bSEric Anholt return -ENODEV; 304*673a394bSEric Anholt 305*673a394bSEric Anholt spin_lock(&dev->object_name_lock); 306*673a394bSEric Anholt obj = idr_find(&dev->object_name_idr, (int) args->name); 307*673a394bSEric Anholt if (obj) 308*673a394bSEric Anholt drm_gem_object_reference(obj); 309*673a394bSEric Anholt spin_unlock(&dev->object_name_lock); 310*673a394bSEric Anholt if (!obj) 311*673a394bSEric Anholt return -ENOENT; 312*673a394bSEric Anholt 313*673a394bSEric Anholt ret = drm_gem_handle_create(file_priv, obj, &handle); 314*673a394bSEric Anholt mutex_lock(&dev->struct_mutex); 315*673a394bSEric Anholt drm_gem_object_unreference(obj); 316*673a394bSEric Anholt mutex_unlock(&dev->struct_mutex); 317*673a394bSEric Anholt if (ret) 318*673a394bSEric Anholt return ret; 319*673a394bSEric Anholt 320*673a394bSEric Anholt args->handle = handle; 321*673a394bSEric Anholt args->size = obj->size; 322*673a394bSEric Anholt 323*673a394bSEric Anholt return 0; 324*673a394bSEric Anholt } 325*673a394bSEric Anholt 326*673a394bSEric Anholt /** 327*673a394bSEric Anholt * Called at device open time, sets up the structure for handling refcounting 328*673a394bSEric Anholt * of mm objects. 329*673a394bSEric Anholt */ 330*673a394bSEric Anholt void 331*673a394bSEric Anholt drm_gem_open(struct drm_device *dev, struct drm_file *file_private) 332*673a394bSEric Anholt { 333*673a394bSEric Anholt idr_init(&file_private->object_idr); 334*673a394bSEric Anholt spin_lock_init(&file_private->table_lock); 335*673a394bSEric Anholt } 336*673a394bSEric Anholt 337*673a394bSEric Anholt /** 338*673a394bSEric Anholt * Called at device close to release the file's 339*673a394bSEric Anholt * handle references on objects. 340*673a394bSEric Anholt */ 341*673a394bSEric Anholt static int 342*673a394bSEric Anholt drm_gem_object_release_handle(int id, void *ptr, void *data) 343*673a394bSEric Anholt { 344*673a394bSEric Anholt struct drm_gem_object *obj = ptr; 345*673a394bSEric Anholt 346*673a394bSEric Anholt drm_gem_object_handle_unreference(obj); 347*673a394bSEric Anholt 348*673a394bSEric Anholt return 0; 349*673a394bSEric Anholt } 350*673a394bSEric Anholt 351*673a394bSEric Anholt /** 352*673a394bSEric Anholt * Called at close time when the filp is going away. 353*673a394bSEric Anholt * 354*673a394bSEric Anholt * Releases any remaining references on objects by this filp. 355*673a394bSEric Anholt */ 356*673a394bSEric Anholt void 357*673a394bSEric Anholt drm_gem_release(struct drm_device *dev, struct drm_file *file_private) 358*673a394bSEric Anholt { 359*673a394bSEric Anholt mutex_lock(&dev->struct_mutex); 360*673a394bSEric Anholt idr_for_each(&file_private->object_idr, 361*673a394bSEric Anholt &drm_gem_object_release_handle, NULL); 362*673a394bSEric Anholt 363*673a394bSEric Anholt idr_destroy(&file_private->object_idr); 364*673a394bSEric Anholt mutex_unlock(&dev->struct_mutex); 365*673a394bSEric Anholt } 366*673a394bSEric Anholt 367*673a394bSEric Anholt /** 368*673a394bSEric Anholt * Called after the last reference to the object has been lost. 369*673a394bSEric Anholt * 370*673a394bSEric Anholt * Frees the object 371*673a394bSEric Anholt */ 372*673a394bSEric Anholt void 373*673a394bSEric Anholt drm_gem_object_free(struct kref *kref) 374*673a394bSEric Anholt { 375*673a394bSEric Anholt struct drm_gem_object *obj = (struct drm_gem_object *) kref; 376*673a394bSEric Anholt struct drm_device *dev = obj->dev; 377*673a394bSEric Anholt 378*673a394bSEric Anholt BUG_ON(!mutex_is_locked(&dev->struct_mutex)); 379*673a394bSEric Anholt 380*673a394bSEric Anholt if (dev->driver->gem_free_object != NULL) 381*673a394bSEric Anholt dev->driver->gem_free_object(obj); 382*673a394bSEric Anholt 383*673a394bSEric Anholt fput(obj->filp); 384*673a394bSEric Anholt atomic_dec(&dev->object_count); 385*673a394bSEric Anholt atomic_sub(obj->size, &dev->object_memory); 386*673a394bSEric Anholt kfree(obj); 387*673a394bSEric Anholt } 388*673a394bSEric Anholt EXPORT_SYMBOL(drm_gem_object_free); 389*673a394bSEric Anholt 390*673a394bSEric Anholt /** 391*673a394bSEric Anholt * Called after the last handle to the object has been closed 392*673a394bSEric Anholt * 393*673a394bSEric Anholt * Removes any name for the object. Note that this must be 394*673a394bSEric Anholt * called before drm_gem_object_free or we'll be touching 395*673a394bSEric Anholt * freed memory 396*673a394bSEric Anholt */ 397*673a394bSEric Anholt void 398*673a394bSEric Anholt drm_gem_object_handle_free(struct kref *kref) 399*673a394bSEric Anholt { 400*673a394bSEric Anholt struct drm_gem_object *obj = container_of(kref, 401*673a394bSEric Anholt struct drm_gem_object, 402*673a394bSEric Anholt handlecount); 403*673a394bSEric Anholt struct drm_device *dev = obj->dev; 404*673a394bSEric Anholt 405*673a394bSEric Anholt /* Remove any name for this object */ 406*673a394bSEric Anholt spin_lock(&dev->object_name_lock); 407*673a394bSEric Anholt if (obj->name) { 408*673a394bSEric Anholt idr_remove(&dev->object_name_idr, obj->name); 409*673a394bSEric Anholt spin_unlock(&dev->object_name_lock); 410*673a394bSEric Anholt /* 411*673a394bSEric Anholt * The object name held a reference to this object, drop 412*673a394bSEric Anholt * that now. 413*673a394bSEric Anholt */ 414*673a394bSEric Anholt drm_gem_object_unreference(obj); 415*673a394bSEric Anholt } else 416*673a394bSEric Anholt spin_unlock(&dev->object_name_lock); 417*673a394bSEric Anholt 418*673a394bSEric Anholt } 419*673a394bSEric Anholt EXPORT_SYMBOL(drm_gem_object_handle_free); 420*673a394bSEric Anholt 421