aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_gem.c')
-rw-r--r--drivers/gpu/drm/drm_gem.c109
1 files changed, 57 insertions, 52 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 2e10bba4468b..2e8c77e71e1f 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -220,6 +220,9 @@ static void drm_gem_object_exported_dma_buf_free(struct drm_gem_object *obj)
220static void 220static void
221drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) 221drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
222{ 222{
223 struct drm_device *dev = obj->dev;
224 bool final = false;
225
223 if (WARN_ON(obj->handle_count == 0)) 226 if (WARN_ON(obj->handle_count == 0))
224 return; 227 return;
225 228
@@ -229,14 +232,39 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
229 * checked for a name 232 * checked for a name
230 */ 233 */
231 234
232 mutex_lock(&obj->dev->object_name_lock); 235 mutex_lock(&dev->object_name_lock);
233 if (--obj->handle_count == 0) { 236 if (--obj->handle_count == 0) {
234 drm_gem_object_handle_free(obj); 237 drm_gem_object_handle_free(obj);
235 drm_gem_object_exported_dma_buf_free(obj); 238 drm_gem_object_exported_dma_buf_free(obj);
239 final = true;
236 } 240 }
237 mutex_unlock(&obj->dev->object_name_lock); 241 mutex_unlock(&dev->object_name_lock);
238 242
239 drm_gem_object_unreference_unlocked(obj); 243 if (final)
244 drm_gem_object_unreference_unlocked(obj);
245}
246
247/*
248 * Called at device or object close to release the file's
249 * handle references on objects.
250 */
251static int
252drm_gem_object_release_handle(int id, void *ptr, void *data)
253{
254 struct drm_file *file_priv = data;
255 struct drm_gem_object *obj = ptr;
256 struct drm_device *dev = obj->dev;
257
258 if (drm_core_check_feature(dev, DRIVER_PRIME))
259 drm_gem_remove_prime_handles(obj, file_priv);
260 drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
261
262 if (dev->driver->gem_close_object)
263 dev->driver->gem_close_object(obj, file_priv);
264
265 drm_gem_object_handle_unreference_unlocked(obj);
266
267 return 0;
240} 268}
241 269
242/** 270/**
@@ -277,14 +305,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
277 idr_remove(&filp->object_idr, handle); 305 idr_remove(&filp->object_idr, handle);
278 spin_unlock(&filp->table_lock); 306 spin_unlock(&filp->table_lock);
279 307
280 if (drm_core_check_feature(dev, DRIVER_PRIME)) 308 drm_gem_object_release_handle(handle, obj, filp);
281 drm_gem_remove_prime_handles(obj, filp);
282 drm_vma_node_revoke(&obj->vma_node, filp->filp);
283
284 if (dev->driver->gem_close_object)
285 dev->driver->gem_close_object(obj, filp);
286 drm_gem_object_handle_unreference_unlocked(obj);
287
288 return 0; 309 return 0;
289} 310}
290EXPORT_SYMBOL(drm_gem_handle_delete); 311EXPORT_SYMBOL(drm_gem_handle_delete);
@@ -326,9 +347,12 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
326 u32 *handlep) 347 u32 *handlep)
327{ 348{
328 struct drm_device *dev = obj->dev; 349 struct drm_device *dev = obj->dev;
350 u32 handle;
329 int ret; 351 int ret;
330 352
331 WARN_ON(!mutex_is_locked(&dev->object_name_lock)); 353 WARN_ON(!mutex_is_locked(&dev->object_name_lock));
354 if (obj->handle_count++ == 0)
355 drm_gem_object_reference(obj);
332 356
333 /* 357 /*
334 * Get the user-visible handle using idr. Preload and perform 358 * Get the user-visible handle using idr. Preload and perform
@@ -338,32 +362,38 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
338 spin_lock(&file_priv->table_lock); 362 spin_lock(&file_priv->table_lock);
339 363
340 ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); 364 ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT);
341 drm_gem_object_reference(obj); 365
342 obj->handle_count++;
343 spin_unlock(&file_priv->table_lock); 366 spin_unlock(&file_priv->table_lock);
344 idr_preload_end(); 367 idr_preload_end();
368
345 mutex_unlock(&dev->object_name_lock); 369 mutex_unlock(&dev->object_name_lock);
346 if (ret < 0) { 370 if (ret < 0)
347 drm_gem_object_handle_unreference_unlocked(obj); 371 goto err_unref;
348 return ret; 372
349 } 373 handle = ret;
350 *handlep = ret;
351 374
352 ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp); 375 ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp);
353 if (ret) { 376 if (ret)
354 drm_gem_handle_delete(file_priv, *handlep); 377 goto err_remove;
355 return ret;
356 }
357 378
358 if (dev->driver->gem_open_object) { 379 if (dev->driver->gem_open_object) {
359 ret = dev->driver->gem_open_object(obj, file_priv); 380 ret = dev->driver->gem_open_object(obj, file_priv);
360 if (ret) { 381 if (ret)
361 drm_gem_handle_delete(file_priv, *handlep); 382 goto err_revoke;
362 return ret;
363 }
364 } 383 }
365 384
385 *handlep = handle;
366 return 0; 386 return 0;
387
388err_revoke:
389 drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
390err_remove:
391 spin_lock(&file_priv->table_lock);
392 idr_remove(&file_priv->object_idr, handle);
393 spin_unlock(&file_priv->table_lock);
394err_unref:
395 drm_gem_object_handle_unreference_unlocked(obj);
396 return ret;
367} 397}
368 398
369/** 399/**
@@ -630,7 +660,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
630 return -ENOENT; 660 return -ENOENT;
631 661
632 mutex_lock(&dev->object_name_lock); 662 mutex_lock(&dev->object_name_lock);
633 idr_preload(GFP_KERNEL);
634 /* prevent races with concurrent gem_close. */ 663 /* prevent races with concurrent gem_close. */
635 if (obj->handle_count == 0) { 664 if (obj->handle_count == 0) {
636 ret = -ENOENT; 665 ret = -ENOENT;
@@ -638,7 +667,7 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
638 } 667 }
639 668
640 if (!obj->name) { 669 if (!obj->name) {
641 ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT); 670 ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_KERNEL);
642 if (ret < 0) 671 if (ret < 0)
643 goto err; 672 goto err;
644 673
@@ -649,7 +678,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
649 ret = 0; 678 ret = 0;
650 679
651err: 680err:
652 idr_preload_end();
653 mutex_unlock(&dev->object_name_lock); 681 mutex_unlock(&dev->object_name_lock);
654 drm_gem_object_unreference_unlocked(obj); 682 drm_gem_object_unreference_unlocked(obj);
655 return ret; 683 return ret;
@@ -714,29 +742,6 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
714 spin_lock_init(&file_private->table_lock); 742 spin_lock_init(&file_private->table_lock);
715} 743}
716 744
717/*
718 * Called at device close to release the file's
719 * handle references on objects.
720 */
721static int
722drm_gem_object_release_handle(int id, void *ptr, void *data)
723{
724 struct drm_file *file_priv = data;
725 struct drm_gem_object *obj = ptr;
726 struct drm_device *dev = obj->dev;
727
728 if (drm_core_check_feature(dev, DRIVER_PRIME))
729 drm_gem_remove_prime_handles(obj, file_priv);
730 drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
731
732 if (dev->driver->gem_close_object)
733 dev->driver->gem_close_object(obj, file_priv);
734
735 drm_gem_object_handle_unreference_unlocked(obj);
736
737 return 0;
738}
739
740/** 745/**
741 * drm_gem_release - release file-private GEM resources 746 * drm_gem_release - release file-private GEM resources
742 * @dev: drm_device which is being closed by userspace 747 * @dev: drm_device which is being closed by userspace