aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_gem.c49
-rw-r--r--include/drm/drmP.h28
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
414static void
415drm_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}
435EXPORT_SYMBOL(drm_gem_object_free); 443EXPORT_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 */
451void
452drm_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}
467EXPORT_SYMBOL(drm_gem_object_free_unlocked);
468
469static 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);
1427int drm_gem_init(struct drm_device *dev); 1428int drm_gem_init(struct drm_device *dev);
1428void drm_gem_destroy(struct drm_device *dev); 1429void drm_gem_destroy(struct drm_device *dev);
1429void drm_gem_object_free(struct kref *kref); 1430void drm_gem_object_free(struct kref *kref);
1431void drm_gem_object_free_unlocked(struct kref *kref);
1430struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, 1432struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
1431 size_t size); 1433 size_t size);
1432void drm_gem_object_handle_free(struct kref *kref); 1434void drm_gem_object_handle_free(struct kref *kref);
@@ -1443,10 +1445,15 @@ drm_gem_object_reference(struct drm_gem_object *obj)
1443static inline void 1445static inline void
1444drm_gem_object_unreference(struct drm_gem_object *obj) 1446drm_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); 1452static inline void
1453drm_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
1452int drm_gem_handle_create(struct drm_file *file_priv, 1459int 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
1485static inline void
1486drm_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
1478struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev, 1500struct 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);