mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-04 09:34:12 +08:00
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: Luca Barbieri <luca@luca-barbieri.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
77c1ff3982
commit
c3ae90c099
@ -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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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 {
|
|||||||
*/
|
*/
|
||||||
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);
|
|||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user