Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+44 −5
Original line number Diff line number Diff line
@@ -411,8 +411,19 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
	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.
 * Must be called holding struct_ mutex
 *
 * Frees the object
 */
@@ -427,13 +438,39 @@ drm_gem_object_free(struct kref *kref)
	if (dev->driver->gem_free_object != NULL)
		dev->driver->gem_free_object(obj);

	fput(obj->filp);
	atomic_dec(&dev->object_count);
	atomic_sub(obj->size, &dev->object_memory);
	kfree(obj);
	drm_gem_object_free_common(obj);
}
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
 *
@@ -458,8 +495,10 @@ drm_gem_object_handle_free(struct kref *kref)
		/*
		 * The object name held a reference to this object, drop
		 * 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
		spin_unlock(&dev->object_name_lock);

+25 −3
Original line number Diff line number Diff line
@@ -801,6 +801,7 @@ struct drm_driver {
	 */
	int (*gem_init_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 */
	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);
void drm_gem_destroy(struct drm_device *dev);
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,
					    size_t size);
void drm_gem_object_handle_free(struct kref *kref);
@@ -1443,12 +1445,17 @@ drm_gem_object_reference(struct drm_gem_object *obj)
static inline void
drm_gem_object_unreference(struct drm_gem_object *obj)
{
	if (obj == NULL)
		return;

	if (obj != NULL)
		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,
			  struct drm_gem_object *obj,
			  u32 *handlep);
@@ -1475,6 +1482,21 @@ drm_gem_object_handle_unreference(struct drm_gem_object *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_file *filp,
					     u32 handle);