Commit c3ae90c0 authored by Luca Barbieri's avatar Luca Barbieri Committed by Dave Airlie

drm: introduce drm_gem_object_[handle_]unreference_unlocked

This patch introduces the drm_gem_object_unreference_unlocked
and drm_gem_object_handle_unreference_unlocked functions that
do not require holding struct_mutex.

drm_gem_object_unreference_unlocked calls the new
->gem_free_object_unlocked entry point if available, and
otherwise just takes struct_mutex and just calls ->gem_free_object
Signed-off-by: default avatarLuca Barbieri <luca@luca-barbieri.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 77c1ff39
...@@ -411,8 +411,19 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private) ...@@ -411,8 +411,19 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
static void
drm_gem_object_free_common(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
fput(obj->filp);
atomic_dec(&dev->object_count);
atomic_sub(obj->size, &dev->object_memory);
kfree(obj);
}
/** /**
* Called after the last reference to the object has been lost. * Called after the last reference to the object has been lost.
* Must be called holding struct_ mutex
* *
* Frees the object * Frees the object
*/ */
...@@ -427,13 +438,39 @@ drm_gem_object_free(struct kref *kref) ...@@ -427,13 +438,39 @@ drm_gem_object_free(struct kref *kref)
if (dev->driver->gem_free_object != NULL) if (dev->driver->gem_free_object != NULL)
dev->driver->gem_free_object(obj); dev->driver->gem_free_object(obj);
fput(obj->filp); drm_gem_object_free_common(obj);
atomic_dec(&dev->object_count);
atomic_sub(obj->size, &dev->object_memory);
kfree(obj);
} }
EXPORT_SYMBOL(drm_gem_object_free); EXPORT_SYMBOL(drm_gem_object_free);
/**
* Called after the last reference to the object has been lost.
* Must be called without holding struct_mutex
*
* Frees the object
*/
void
drm_gem_object_free_unlocked(struct kref *kref)
{
struct drm_gem_object *obj = (struct drm_gem_object *) kref;
struct drm_device *dev = obj->dev;
if (dev->driver->gem_free_object_unlocked != NULL)
dev->driver->gem_free_object_unlocked(obj);
else if (dev->driver->gem_free_object != NULL) {
mutex_lock(&dev->struct_mutex);
dev->driver->gem_free_object(obj);
mutex_unlock(&dev->struct_mutex);
}
drm_gem_object_free_common(obj);
}
EXPORT_SYMBOL(drm_gem_object_free_unlocked);
static void drm_gem_object_ref_bug(struct kref *list_kref)
{
BUG();
}
/** /**
* Called after the last handle to the object has been closed * Called after the last handle to the object has been closed
* *
...@@ -458,8 +495,10 @@ drm_gem_object_handle_free(struct kref *kref) ...@@ -458,8 +495,10 @@ drm_gem_object_handle_free(struct kref *kref)
/* /*
* The object name held a reference to this object, drop * The object name held a reference to this object, drop
* that now. * that now.
*
* This cannot be the last reference, since the handle holds one too.
*/ */
drm_gem_object_unreference(obj); kref_put(&obj->refcount, drm_gem_object_ref_bug);
} else } else
spin_unlock(&dev->object_name_lock); spin_unlock(&dev->object_name_lock);
......
...@@ -801,6 +801,7 @@ struct drm_driver { ...@@ -801,6 +801,7 @@ struct drm_driver {
*/ */
int (*gem_init_object) (struct drm_gem_object *obj); int (*gem_init_object) (struct drm_gem_object *obj);
void (*gem_free_object) (struct drm_gem_object *obj); void (*gem_free_object) (struct drm_gem_object *obj);
void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
/* vga arb irq handler */ /* vga arb irq handler */
void (*vgaarb_irq)(struct drm_device *dev, bool state); void (*vgaarb_irq)(struct drm_device *dev, bool state);
...@@ -1427,6 +1428,7 @@ extern void drm_sysfs_connector_remove(struct drm_connector *connector); ...@@ -1427,6 +1428,7 @@ extern void drm_sysfs_connector_remove(struct drm_connector *connector);
int drm_gem_init(struct drm_device *dev); int drm_gem_init(struct drm_device *dev);
void drm_gem_destroy(struct drm_device *dev); void drm_gem_destroy(struct drm_device *dev);
void drm_gem_object_free(struct kref *kref); void drm_gem_object_free(struct kref *kref);
void drm_gem_object_free_unlocked(struct kref *kref);
struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
size_t size); size_t size);
void drm_gem_object_handle_free(struct kref *kref); void drm_gem_object_handle_free(struct kref *kref);
...@@ -1443,10 +1445,15 @@ drm_gem_object_reference(struct drm_gem_object *obj) ...@@ -1443,10 +1445,15 @@ drm_gem_object_reference(struct drm_gem_object *obj)
static inline void static inline void
drm_gem_object_unreference(struct drm_gem_object *obj) drm_gem_object_unreference(struct drm_gem_object *obj)
{ {
if (obj == NULL) if (obj != NULL)
return; kref_put(&obj->refcount, drm_gem_object_free);
}
kref_put(&obj->refcount, drm_gem_object_free); static inline void
drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
{
if (obj != NULL)
kref_put(&obj->refcount, drm_gem_object_free_unlocked);
} }
int drm_gem_handle_create(struct drm_file *file_priv, 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,6 +1482,21 @@ drm_gem_object_handle_unreference(struct drm_gem_object *obj)
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
} }
static inline void
drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
{
if (obj == NULL)
return;
/*
* Must bump handle count first as this may be the last
* ref, in which case the object would disappear before we
* checked for a name
*/
kref_put(&obj->handlecount, drm_gem_object_handle_free);
drm_gem_object_unreference_unlocked(obj);
}
struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev, struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
struct drm_file *filp, struct drm_file *filp,
u32 handle); u32 handle);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment