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

Commit 29d08b3e authored by Dave Airlie's avatar Dave Airlie
Browse files

drm/gem: handlecount isn't really a kref so don't make it one.



There were lots of places being inconsistent since handle count
looked like a kref but it really wasn't.

Fix this my just making handle count an atomic on the object,
and have it increase the normal object kref.

Now i915/radeon/nouveau drivers can drop the normal reference on
userspace object creation, and have the handle hold it.

This patch fixes a memory leak or corruption on unload, because
the driver had no way of knowing if a handle had been actually
added for this object, and the fbcon object needed to know this
to clean itself up properly.

Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 130b9851
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -148,7 +148,7 @@ int drm_gem_object_init(struct drm_device *dev,
		return -ENOMEM;

	kref_init(&obj->refcount);
	kref_init(&obj->handlecount);
	atomic_set(&obj->handle_count, 0);
	obj->size = size;

	atomic_inc(&dev->object_count);
@@ -496,12 +496,8 @@ static void drm_gem_object_ref_bug(struct kref *list_kref)
 * called before drm_gem_object_free or we'll be touching
 * freed memory
 */
void
drm_gem_object_handle_free(struct kref *kref)
void drm_gem_object_handle_free(struct drm_gem_object *obj)
{
	struct drm_gem_object *obj = container_of(kref,
						  struct drm_gem_object,
						  handlecount);
	struct drm_device *dev = obj->dev;

	/* Remove any name for this object */
+1 −1
Original line number Diff line number Diff line
@@ -255,7 +255,7 @@ int drm_gem_one_name_info(int id, void *ptr, void *data)

	seq_printf(m, "%6d %8zd %7d %8d\n",
		   obj->name, obj->size,
		   atomic_read(&obj->handlecount.refcount),
		   atomic_read(&obj->handle_count),
		   atomic_read(&obj->refcount.refcount));
	return 0;
}
+2 −4
Original line number Diff line number Diff line
@@ -136,14 +136,12 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
		return -ENOMEM;

	ret = drm_gem_handle_create(file_priv, obj, &handle);
	if (ret) {
	/* drop reference from allocate - handle holds it now */
	drm_gem_object_unreference_unlocked(obj);
	if (ret) {
		return ret;
	}

	/* Sink the floating reference from kref_init(handlecount) */
	drm_gem_object_handle_unreference_unlocked(obj);

	args->handle = handle;
	return 0;
}
+3 −1
Original line number Diff line number Diff line
@@ -237,8 +237,10 @@ int intel_fbdev_destroy(struct drm_device *dev,
	drm_fb_helper_fini(&ifbdev->helper);

	drm_framebuffer_cleanup(&ifb->base);
	if (ifb->obj)
	if (ifb->obj) {
		drm_gem_object_handle_unreference(ifb->obj);
		drm_gem_object_unreference(ifb->obj);
	}

	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -352,6 +352,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)

	if (nouveau_fb->nvbo) {
		nouveau_bo_unmap(nouveau_fb->nvbo);
		drm_gem_object_handle_unreference_unlocked(nouveau_fb->nvbo->gem);
		drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
		nouveau_fb->nvbo = NULL;
	}
Loading