diff options
Diffstat (limited to 'drivers/gpu/drm/drm_gem.c')
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 8bf3770f294e..aa89d4b0b4c4 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -192,9 +192,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle) | |||
192 | idr_remove(&filp->object_idr, handle); | 192 | idr_remove(&filp->object_idr, handle); |
193 | spin_unlock(&filp->table_lock); | 193 | spin_unlock(&filp->table_lock); |
194 | 194 | ||
195 | mutex_lock(&dev->struct_mutex); | 195 | drm_gem_object_handle_unreference_unlocked(obj); |
196 | drm_gem_object_handle_unreference(obj); | ||
197 | mutex_unlock(&dev->struct_mutex); | ||
198 | 196 | ||
199 | return 0; | 197 | return 0; |
200 | } | 198 | } |
@@ -325,9 +323,7 @@ again: | |||
325 | } | 323 | } |
326 | 324 | ||
327 | err: | 325 | err: |
328 | mutex_lock(&dev->struct_mutex); | 326 | drm_gem_object_unreference_unlocked(obj); |
329 | drm_gem_object_unreference(obj); | ||
330 | mutex_unlock(&dev->struct_mutex); | ||
331 | return ret; | 327 | return ret; |
332 | } | 328 | } |
333 | 329 | ||
@@ -358,9 +354,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, | |||
358 | return -ENOENT; | 354 | return -ENOENT; |
359 | 355 | ||
360 | ret = drm_gem_handle_create(file_priv, obj, &handle); | 356 | ret = drm_gem_handle_create(file_priv, obj, &handle); |
361 | mutex_lock(&dev->struct_mutex); | 357 | drm_gem_object_unreference_unlocked(obj); |
362 | drm_gem_object_unreference(obj); | ||
363 | mutex_unlock(&dev->struct_mutex); | ||
364 | if (ret) | 358 | if (ret) |
365 | return ret; | 359 | return ret; |
366 | 360 | ||
@@ -390,7 +384,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) | |||
390 | { | 384 | { |
391 | struct drm_gem_object *obj = ptr; | 385 | struct drm_gem_object *obj = ptr; |
392 | 386 | ||
393 | drm_gem_object_handle_unreference(obj); | 387 | drm_gem_object_handle_unreference_unlocked(obj); |
394 | 388 | ||
395 | return 0; | 389 | return 0; |
396 | } | 390 | } |
@@ -403,16 +397,25 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) | |||
403 | void | 397 | void |
404 | drm_gem_release(struct drm_device *dev, struct drm_file *file_private) | 398 | drm_gem_release(struct drm_device *dev, struct drm_file *file_private) |
405 | { | 399 | { |
406 | mutex_lock(&dev->struct_mutex); | ||
407 | idr_for_each(&file_private->object_idr, | 400 | idr_for_each(&file_private->object_idr, |
408 | &drm_gem_object_release_handle, NULL); | 401 | &drm_gem_object_release_handle, NULL); |
409 | 402 | ||
410 | idr_destroy(&file_private->object_idr); | 403 | idr_destroy(&file_private->object_idr); |
411 | mutex_unlock(&dev->struct_mutex); | 404 | } |
405 | |||
406 | static void | ||
407 | drm_gem_object_free_common(struct drm_gem_object *obj) | ||
408 | { | ||
409 | struct drm_device *dev = obj->dev; | ||
410 | fput(obj->filp); | ||
411 | atomic_dec(&dev->object_count); | ||
412 | atomic_sub(obj->size, &dev->object_memory); | ||
413 | kfree(obj); | ||
412 | } | 414 | } |
413 | 415 | ||
414 | /** | 416 | /** |
415 | * Called after the last reference to the object has been lost. | 417 | * Called after the last reference to the object has been lost. |
418 | * Must be called holding struct_ mutex | ||
416 | * | 419 | * |
417 | * Frees the object | 420 | * Frees the object |
418 | */ | 421 | */ |
@@ -427,14 +430,40 @@ drm_gem_object_free(struct kref *kref) | |||
427 | if (dev->driver->gem_free_object != NULL) | 430 | if (dev->driver->gem_free_object != NULL) |
428 | dev->driver->gem_free_object(obj); | 431 | dev->driver->gem_free_object(obj); |
429 | 432 | ||
430 | fput(obj->filp); | 433 | drm_gem_object_free_common(obj); |
431 | atomic_dec(&dev->object_count); | ||
432 | atomic_sub(obj->size, &dev->object_memory); | ||
433 | kfree(obj); | ||
434 | } | 434 | } |
435 | EXPORT_SYMBOL(drm_gem_object_free); | 435 | EXPORT_SYMBOL(drm_gem_object_free); |
436 | 436 | ||
437 | /** | 437 | /** |
438 | * Called after the last reference to the object has been lost. | ||
439 | * Must be called without holding struct_mutex | ||
440 | * | ||
441 | * Frees the object | ||
442 | */ | ||
443 | void | ||
444 | drm_gem_object_free_unlocked(struct kref *kref) | ||
445 | { | ||
446 | struct drm_gem_object *obj = (struct drm_gem_object *) kref; | ||
447 | struct drm_device *dev = obj->dev; | ||
448 | |||
449 | if (dev->driver->gem_free_object_unlocked != NULL) | ||
450 | dev->driver->gem_free_object_unlocked(obj); | ||
451 | else if (dev->driver->gem_free_object != NULL) { | ||
452 | mutex_lock(&dev->struct_mutex); | ||
453 | dev->driver->gem_free_object(obj); | ||
454 | mutex_unlock(&dev->struct_mutex); | ||
455 | } | ||
456 | |||
457 | drm_gem_object_free_common(obj); | ||
458 | } | ||
459 | EXPORT_SYMBOL(drm_gem_object_free_unlocked); | ||
460 | |||
461 | static void drm_gem_object_ref_bug(struct kref *list_kref) | ||
462 | { | ||
463 | BUG(); | ||
464 | } | ||
465 | |||
466 | /** | ||
438 | * Called after the last handle to the object has been closed | 467 | * Called after the last handle to the object has been closed |
439 | * | 468 | * |
440 | * Removes any name for the object. Note that this must be | 469 | * Removes any name for the object. Note that this must be |
@@ -458,8 +487,10 @@ drm_gem_object_handle_free(struct kref *kref) | |||
458 | /* | 487 | /* |
459 | * The object name held a reference to this object, drop | 488 | * The object name held a reference to this object, drop |
460 | * that now. | 489 | * that now. |
490 | * | ||
491 | * This cannot be the last reference, since the handle holds one too. | ||
461 | */ | 492 | */ |
462 | drm_gem_object_unreference(obj); | 493 | kref_put(&obj->refcount, drm_gem_object_ref_bug); |
463 | } else | 494 | } else |
464 | spin_unlock(&dev->object_name_lock); | 495 | spin_unlock(&dev->object_name_lock); |
465 | 496 | ||
@@ -477,11 +508,8 @@ EXPORT_SYMBOL(drm_gem_vm_open); | |||
477 | void drm_gem_vm_close(struct vm_area_struct *vma) | 508 | void drm_gem_vm_close(struct vm_area_struct *vma) |
478 | { | 509 | { |
479 | struct drm_gem_object *obj = vma->vm_private_data; | 510 | struct drm_gem_object *obj = vma->vm_private_data; |
480 | struct drm_device *dev = obj->dev; | ||
481 | 511 | ||
482 | mutex_lock(&dev->struct_mutex); | 512 | drm_gem_object_unreference_unlocked(obj); |
483 | drm_gem_object_unreference(obj); | ||
484 | mutex_unlock(&dev->struct_mutex); | ||
485 | } | 513 | } |
486 | EXPORT_SYMBOL(drm_gem_vm_close); | 514 | EXPORT_SYMBOL(drm_gem_vm_close); |
487 | 515 | ||