170,6 → 170,15 |
} |
EXPORT_SYMBOL(drm_gem_private_object_init); |
|
static void |
drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp) |
{ |
/* |
* Note: obj->dma_buf can't disappear as long as we still hold a |
* handle reference in obj->handle_count. |
*/ |
} |
|
/** |
* drm_gem_object_handle_free - release resources bound to userspace handles |
* @obj: GEM object to clean up. |
195,6 → 204,9 |
static void |
drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) |
{ |
struct drm_device *dev = obj->dev; |
bool final = false; |
|
if (WARN_ON(obj->handle_count == 0)) |
return; |
|
204,22 → 216,48 |
* checked for a name |
*/ |
|
mutex_lock(&obj->dev->object_name_lock); |
mutex_lock(&dev->object_name_lock); |
if (--obj->handle_count == 0) { |
drm_gem_object_handle_free(obj); |
final = true; |
} |
mutex_unlock(&obj->dev->object_name_lock); |
mutex_unlock(&dev->object_name_lock); |
|
if (final) |
drm_gem_object_unreference_unlocked(obj); |
} |
|
/* |
* Called at device or object 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; |
} |
|
/** |
* drm_gem_handle_delete - deletes the given file-private handle |
* @filp: drm file-private structure to use for the handle look up |
* @handle: userspace handle to delete |
* |
* Removes the GEM handle from the @filp lookup table and if this is the last |
* handle also cleans up linked resources like GEM names. |
* Removes the GEM handle from the @filp lookup table which has been added with |
* drm_gem_handle_create(). If this is the last handle also cleans up linked |
* resources like GEM names. |
*/ |
int |
drm_gem_handle_delete(struct drm_file *filp, u32 handle) |
250,12 → 288,7 |
idr_remove(&filp->object_idr, handle); |
spin_unlock(&filp->table_lock); |
|
// drm_vma_node_revoke(&obj->vma_node, filp->filp); |
|
if (dev->driver->gem_close_object) |
dev->driver->gem_close_object(obj, filp); |
|
drm_gem_object_handle_unreference_unlocked(obj); |
drm_gem_object_release_handle(handle, obj, filp); |
return 0; |
} |
EXPORT_SYMBOL(drm_gem_handle_delete); |
286,6 → 319,10 |
* 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. |
* |
* Handles must be release again through drm_gem_handle_delete(). This is done |
* when userspace closes @file_priv for all attached handles, or through the |
* GEM_CLOSE ioctl for individual handles. |
*/ |
int |
drm_gem_handle_create_tail(struct drm_file *file_priv, |
293,9 → 330,12 |
u32 *handlep) |
{ |
struct drm_device *dev = obj->dev; |
u32 handle; |
int ret; |
|
WARN_ON(!mutex_is_locked(&dev->object_name_lock)); |
if (obj->handle_count++ == 0) |
drm_gem_object_reference(obj); |
|
/* |
* Get the user-visible handle using idr. Preload and perform |
305,15 → 345,15 |
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) |
goto err_unref; |
|
*handlep = ret; |
handle = ret; |
|
// ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp); |
// if (ret) { |
327,6 → 367,7 |
goto err_revoke; |
} |
|
*handlep = handle; |
return 0; |
|
err_revoke: |
333,7 → 374,7 |
// drm_vma_node_revoke(&obj->vma_node, file_priv->filp); |
err_remove: |
spin_lock(&file_priv->table_lock); |
idr_remove(&file_priv->object_idr, *handlep); |
idr_remove(&file_priv->object_idr, handle); |
spin_unlock(&file_priv->table_lock); |
err_unref: |
drm_gem_object_handle_unreference_unlocked(obj); |
521,7 → 562,17 |
EXPORT_SYMBOL(drm_gem_put_pages); |
#endif |
|
/** Returns a reference to the object named by the handle. */ |
/** |
* drm_gem_object_lookup - look up a GEM object from it's handle |
* @dev: DRM device |
* @filp: DRM file private date |
* @handle: userspace handle |
* |
* Returns: |
* |
* A reference to the object named by the handle if such exists on @filp, NULL |
* otherwise. |
*/ |
struct drm_gem_object * |
drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, |
u32 handle) |
595,7 → 646,6 |
return -ENOENT; |
|
mutex_lock(&dev->object_name_lock); |
idr_preload(GFP_KERNEL); |
/* prevent races with concurrent gem_close. */ |
if (obj->handle_count == 0) { |
ret = -ENOENT; |
603,7 → 653,7 |
} |
|
if (!obj->name) { |
ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT); |
ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_KERNEL); |
if (ret < 0) |
goto err; |
|
614,9 → 664,12 |
ret = 0; |
|
err: |
idr_preload_end(); |
mutex_unlock(&dev->object_name_lock); |
drm_gem_object_unreference_unlocked(obj); |
|
// printf("%s object %p name %d refcount %d\n", |
// __FUNCTION__, obj, obj->name, obj->refcount.refcount); |
|
return ret; |
} |
|
661,6 → 714,9 |
args->handle = handle; |
args->size = obj->size; |
|
// printf("%s object %p handle %d refcount %d\n", |
// __FUNCTION__, obj, handle, obj->refcount.refcount); |
|
return 0; |
} |
|
680,27 → 736,6 |
spin_lock_init(&file_private->table_lock); |
} |
|
/* |
* 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; |
|
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; |
} |
|
/** |
* drm_gem_release - release file-private GEM resources |
* @dev: drm_device which is being closed by userspace |