int radeon_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_create *args = data; struct drm_gem_object *gobj; uint32_t handle; int r; /* create a gem object to contain this object in */ args->size = roundup(args->size, PAGE_SIZE); r = radeon_gem_object_create(rdev, args->size, args->alignment, args->initial_domain, false, false, &gobj); if (r) { return r; } r = drm_gem_handle_create(filp, gobj, &handle); if (r) { drm_gem_object_unreference_unlocked(gobj); return r; } drm_gem_object_handle_unreference_unlocked(gobj); args->handle = handle; return 0; }
/** * 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; }
/** * 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_object *obj = ptr; drm_gem_object_handle_unreference_unlocked(obj); return 0; }
int drm_gem_handle_delete(struct drm_file *file_priv, uint32_t handle) { struct drm_gem_object *obj; obj = drm_gem_names_remove(&file_priv->object_names, handle); if (obj == NULL) return (EINVAL); drm_gem_object_handle_unreference_unlocked(obj); return (0); }
/** * 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_file *file_priv = data; struct drm_gem_object *obj = ptr; struct drm_device *dev = obj->dev; if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); drm_gem_object_handle_unreference_unlocked(obj); return 0; }
int nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_gem_new *req = data; struct nouveau_bo *nvbo = NULL; struct nouveau_channel *chan = NULL; uint32_t flags = 0; int ret = 0; NOUVEAU_CHECK_INITIALISED_WITH_RETURN; if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; if (req->channel_hint) { NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint, file_priv, chan); } if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) flags |= TTM_PL_FLAG_VRAM; if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) flags |= TTM_PL_FLAG_TT; if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) flags |= TTM_PL_FLAG_SYSTEM; if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags)) return -EINVAL; ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, req->info.tile_mode, req->info.tile_flags, false, (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), &nvbo); if (ret) return ret; ret = nouveau_gem_info(nvbo->gem, &req->info); if (ret) goto out; ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); out: drm_gem_object_handle_unreference_unlocked(nvbo->gem); if (ret) drm_gem_object_unreference_unlocked(nvbo->gem); return ret; }
void nouveau_notifier_takedown_channel(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; if (!chan->notifier_bo) return; nouveau_bo_unmap(chan->notifier_bo); mutex_lock(&dev->struct_mutex); nouveau_bo_unpin(chan->notifier_bo); mutex_unlock(&dev->struct_mutex); drm_gem_object_handle_unreference_unlocked(chan->notifier_bo->gem); drm_gem_object_unreference_unlocked(chan->notifier_bo->gem); drm_mm_takedown(&chan->notifier_heap); }
/** * drm_gem_handle_create_tail - internal functions to create a handle * @file_priv: drm file-private structure to register the handle for * @obj: object to register * @handlep: pointer to return the created handle to the caller * * This expects the dev->object_name_lock to be held already and will drop it * before returning. Used to avoid races in establishing new handles when * importing an object from either an flink name or a dma-buf. */ int drm_gem_handle_create_tail(struct drm_file *file_priv, struct drm_gem_object *obj, u32 *handlep) { struct drm_device *dev = obj->dev; int ret; WARN_ON(!mutex_is_locked(&dev->object_name_lock)); /* * Get the user-visible handle using idr. Preload and perform * allocation under our spinlock. */ idr_preload(GFP_KERNEL); spin_lock(&file_priv->table_lock); ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); drm_gem_object_reference(obj); obj->handle_count++; spin_unlock(&file_priv->table_lock); idr_preload_end(); mutex_unlock(&dev->object_name_lock); if (ret < 0) { drm_gem_object_handle_unreference_unlocked(obj); return ret; } *handlep = ret; ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp); if (ret) { drm_gem_handle_delete(file_priv, *handlep); return ret; } if (dev->driver->gem_open_object) { ret = dev->driver->gem_open_object(obj, file_priv); if (ret) { drm_gem_handle_delete(file_priv, *handlep); return ret; } } return 0; }
/* * 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_file *file_priv = data; struct drm_gem_object *obj = ptr; struct drm_device *dev = obj->dev; if (drm_core_check_feature(dev, DRIVER_PRIME)) drm_gem_remove_prime_handles(obj, file_priv); drm_vma_node_revoke(&obj->vma_node, file_priv->filp); if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); drm_gem_object_handle_unreference_unlocked(obj); return 0; }
static int drm_gem_object_release_handle(uint32_t name, void *ptr, void *data) { struct drm_file *file_priv = data; struct drm_gem_object *obj = ptr; struct drm_device *dev = obj->dev; #if defined(FREEBSD_NOTYET) drm_gem_remove_prime_handles(obj, file_priv); #endif if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); drm_gem_object_handle_unreference_unlocked(obj); return 0; }
static int drm_gem_object_release_handle(int id, void *ptr, void *data) { struct drm_file *file_priv = data; struct drm_gem_object *obj = ptr; struct drm_device *dev = obj->dev; if (obj->import_attach) drm_prime_remove_imported_buf_handle(&file_priv->prime, obj->import_attach->dmabuf); if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); drm_gem_object_handle_unreference_unlocked(obj); return 0; }
/** * 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_file *file_priv = data; struct drm_gem_object *obj = ptr; struct drm_device *dev = obj->dev; #ifndef __NetBSD__ /* XXX drm prime */ drm_gem_remove_prime_handles(obj, file_priv); #endif if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); drm_gem_object_handle_unreference_unlocked(obj); return 0; }
/** * 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; obj = drm_gem_names_remove(&filp->object_names, handle); if (obj == NULL) { return -EINVAL; } dev = obj->dev; #if defined(FREEBSD_NOTYET) drm_gem_remove_prime_handles(obj, filp); #endif if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, filp); drm_gem_object_handle_unreference_unlocked(obj); return 0; }
int drm_gem_handle_delete(struct drm_file *filp, u32 handle) { struct drm_device *dev; struct drm_gem_object *obj; /* */ spin_lock(&filp->table_lock); /* */ obj = idr_find(&filp->object_idr, handle); if (obj == NULL) { spin_unlock(&filp->table_lock); return -EINVAL; } dev = obj->dev; /* */ idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); if (obj->import_attach) drm_prime_remove_imported_buf_handle(&filp->prime, obj->import_attach->dmabuf); if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, filp); drm_gem_object_handle_unreference_unlocked(obj); return 0; }