diff options
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 49 | ||||
-rw-r--r-- | include/drm/drmP.h | 28 |
2 files changed, 69 insertions, 8 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 8bf3770f294e..4018b3bfc72e 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -411,8 +411,19 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private) | |||
411 | mutex_unlock(&dev->struct_mutex); | 411 | mutex_unlock(&dev->struct_mutex); |
412 | } | 412 | } |
413 | 413 | ||
414 | static void | ||
415 | drm_gem_object_free_common(struct drm_gem_object *obj) | ||
416 | { | ||
417 | struct drm_device *dev = obj->dev; | ||
418 | fput(obj->filp); | ||
419 | atomic_dec(&dev->object_count); | ||
420 | atomic_sub(obj->size, &dev->object_memory); | ||
421 | kfree(obj); | ||
422 | } | ||
423 | |||
414 | /** | 424 | /** |
415 | * Called after the last reference to the object has been lost. | 425 | * Called after the last reference to the object has been lost. |
426 | * Must be called holding struct_ mutex | ||
416 | * | 427 | * |
417 | * Frees the object | 428 | * Frees the object |
418 | */ | 429 | */ |
@@ -427,14 +438,40 @@ drm_gem_object_free(struct kref *kref) | |||
427 | if (dev->driver->gem_free_object != NULL) | 438 | if (dev->driver->gem_free_object != NULL) |
428 | dev->driver->gem_free_object(obj); | 439 | dev->driver->gem_free_object(obj); |
429 | 440 | ||
430 | fput(obj->filp); | 441 | drm_gem_object_free_common(obj); |
431 | atomic_dec(&dev->object_count); | ||
432 | atomic_sub(obj->size, &dev->object_memory); | ||
433 | kfree(obj); | ||
434 | } | 442 | } |
435 | EXPORT_SYMBOL(drm_gem_object_free); | 443 | EXPORT_SYMBOL(drm_gem_object_free); |
436 | 444 | ||
437 | /** | 445 | /** |
446 | * Called after the last reference to the object has been lost. | ||
447 | * Must be called without holding struct_mutex | ||
448 | * | ||
449 | * Frees the object | ||
450 | */ | ||
451 | void | ||
452 | drm_gem_object_free_unlocked(struct kref *kref) | ||
453 | { | ||
454 | struct drm_gem_object *obj = (struct drm_gem_object *) kref; | ||
455 | struct drm_device *dev = obj->dev; | ||
456 | |||
457 | if (dev->driver->gem_free_object_unlocked != NULL) | ||
458 | dev->driver->gem_free_object_unlocked(obj); | ||
459 | else if (dev->driver->gem_free_object != NULL) { | ||
460 | mutex_lock(&dev->struct_mutex); | ||
461 | dev->driver->gem_free_object(obj); | ||
462 | mutex_unlock(&dev->struct_mutex); | ||
463 | } | ||
464 | |||
465 | drm_gem_object_free_common(obj); | ||
466 | } | ||
467 | EXPORT_SYMBOL(drm_gem_object_free_unlocked); | ||
468 | |||
469 | static void drm_gem_object_ref_bug(struct kref *list_kref) | ||
470 | { | ||
471 | BUG(); | ||
472 | } | ||
473 | |||
474 | /** | ||
438 | * Called after the last handle to the object has been closed | 475 | * Called after the last handle to the object has been closed |
439 | * | 476 | * |
440 | * Removes any name for the object. Note that this must be | 477 | * Removes any name for the object. Note that this must be |
@@ -458,8 +495,10 @@ drm_gem_object_handle_free(struct kref *kref) | |||
458 | /* | 495 | /* |
459 | * The object name held a reference to this object, drop | 496 | * The object name held a reference to this object, drop |
460 | * that now. | 497 | * that now. |
498 | * | ||
499 | * This cannot be the last reference, since the handle holds one too. | ||
461 | */ | 500 | */ |
462 | drm_gem_object_unreference(obj); | 501 | kref_put(&obj->refcount, drm_gem_object_ref_bug); |
463 | } else | 502 | } else |
464 | spin_unlock(&dev->object_name_lock); | 503 | spin_unlock(&dev->object_name_lock); |
465 | 504 | ||
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index ffac157fb5b2..4a3c4e441027 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -801,6 +801,7 @@ struct drm_driver { | |||
801 | */ | 801 | */ |
802 | int (*gem_init_object) (struct drm_gem_object *obj); | 802 | int (*gem_init_object) (struct drm_gem_object *obj); |
803 | void (*gem_free_object) (struct drm_gem_object *obj); | 803 | void (*gem_free_object) (struct drm_gem_object *obj); |
804 | void (*gem_free_object_unlocked) (struct drm_gem_object *obj); | ||
804 | 805 | ||
805 | /* vga arb irq handler */ | 806 | /* vga arb irq handler */ |
806 | void (*vgaarb_irq)(struct drm_device *dev, bool state); | 807 | void (*vgaarb_irq)(struct drm_device *dev, bool state); |
@@ -1427,6 +1428,7 @@ extern void drm_sysfs_connector_remove(struct drm_connector *connector); | |||
1427 | int drm_gem_init(struct drm_device *dev); | 1428 | int drm_gem_init(struct drm_device *dev); |
1428 | void drm_gem_destroy(struct drm_device *dev); | 1429 | void drm_gem_destroy(struct drm_device *dev); |
1429 | void drm_gem_object_free(struct kref *kref); | 1430 | void drm_gem_object_free(struct kref *kref); |
1431 | void drm_gem_object_free_unlocked(struct kref *kref); | ||
1430 | struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, | 1432 | struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, |
1431 | size_t size); | 1433 | size_t size); |
1432 | void drm_gem_object_handle_free(struct kref *kref); | 1434 | void drm_gem_object_handle_free(struct kref *kref); |
@@ -1443,10 +1445,15 @@ drm_gem_object_reference(struct drm_gem_object *obj) | |||
1443 | static inline void | 1445 | static inline void |
1444 | drm_gem_object_unreference(struct drm_gem_object *obj) | 1446 | drm_gem_object_unreference(struct drm_gem_object *obj) |
1445 | { | 1447 | { |
1446 | if (obj == NULL) | 1448 | if (obj != NULL) |
1447 | return; | 1449 | kref_put(&obj->refcount, drm_gem_object_free); |
1450 | } | ||
1448 | 1451 | ||
1449 | kref_put(&obj->refcount, drm_gem_object_free); | 1452 | static inline void |
1453 | drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) | ||
1454 | { | ||
1455 | if (obj != NULL) | ||
1456 | kref_put(&obj->refcount, drm_gem_object_free_unlocked); | ||
1450 | } | 1457 | } |
1451 | 1458 | ||
1452 | int drm_gem_handle_create(struct drm_file *file_priv, | 1459 | int drm_gem_handle_create(struct drm_file *file_priv, |
@@ -1475,6 +1482,21 @@ drm_gem_object_handle_unreference(struct drm_gem_object *obj) | |||
1475 | drm_gem_object_unreference(obj); | 1482 | drm_gem_object_unreference(obj); |
1476 | } | 1483 | } |
1477 | 1484 | ||
1485 | static inline void | ||
1486 | drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) | ||
1487 | { | ||
1488 | if (obj == NULL) | ||
1489 | return; | ||
1490 | |||
1491 | /* | ||
1492 | * Must bump handle count first as this may be the last | ||
1493 | * ref, in which case the object would disappear before we | ||
1494 | * checked for a name | ||
1495 | */ | ||
1496 | kref_put(&obj->handlecount, drm_gem_object_handle_free); | ||
1497 | drm_gem_object_unreference_unlocked(obj); | ||
1498 | } | ||
1499 | |||
1478 | struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev, | 1500 | struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev, |
1479 | struct drm_file *filp, | 1501 | struct drm_file *filp, |
1480 | u32 handle); | 1502 | u32 handle); |